Revert memory leak commits

5f7001e: "Added a new branch"
01456ed: "Fixed a lot of memory leaks"
dac4493: "Fixed all remaining memory leaks that I could figure out"
0792db7: "Removed the smnew macro and the call to _CrtSetDbgFlag()"

Some of these caused destructor-time problems due to static initialization
order fiasco and related issues.  Notably, the program would no longer exit on
OSX and had to be killed.

There were probably legitimate fixes in here, but since these are monolithic
commits it's too much work to extract them now.  Let's reapply them
individually and in the forward direction.
This commit is contained in:
Devin J. Pohly
2013-04-27 00:05:14 -04:00
parent ef9c5294a0
commit feb919f0bf
33 changed files with 182 additions and 266 deletions
+27 -17
View File
@@ -5,36 +5,46 @@
#include <set>
// When using this class be sure to use the global static initializer trick by wrapping the static object in a function like the
// following example:
//
// SubscriptionManager<T> & GetSubscribers()
// {
// static SubscriptionManager<T> subscribers;
// return subscribers;
// }
//
// This ensures that the object is always available when it's needed.
// Since this class has only POD types and no constructor, there's no
// initialize order problem.
template<class T>
class SubscriptionManager
{
public:
set<T*> m_pSubscribers;
// TRICKY: If we make this a global instead of a global pointer,
// then we'd have to be careful that the static constructors of all
// subscribers are called before the collection constructor. It's
// impossible to enfore that in C++. Instead, we'll allocate the
// collection ourself on first use. SubscriptionHandler itself is
// a POD type, so a static SubscriptionHandler will always have
// m_pSubscribers == NULL (before any static constructors are called).
set<T*>* m_pSubscribers;
// Use this to access m_pSubscribers, so you don't have to worry about
// it being NULL.
set<T*> &Get()
{
if( m_pSubscribers == NULL )
m_pSubscribers = new set<T*>;
return *m_pSubscribers;
}
void Subscribe( T* p )
{
if( m_pSubscribers == NULL )
m_pSubscribers = new set<T*>;
#ifdef DEBUG
typename set<T*>::iterator iter = m_pSubscribers.find( p );
ASSERT_M( iter == m_pSubscribers.end(), "already subscribed" );
typename set<T*>::iterator iter = m_pSubscribers->find( p );
ASSERT_M( iter == m_pSubscribers->end(), "already subscribed" );
#endif
m_pSubscribers.insert( p );
m_pSubscribers->insert( p );
}
void Unsubscribe( T* p )
{
typename set<T*>::iterator iter = m_pSubscribers.find( p );
ASSERT( iter != m_pSubscribers.end() );
m_pSubscribers.erase( iter );
typename set<T*>::iterator iter = m_pSubscribers->find( p );
ASSERT( iter != m_pSubscribers->end() );
m_pSubscribers->erase( iter );
}
};