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:
+27
-17
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user