Fix teh Singletons to have a global registry

This commit is contained in:
Lirusaito
2014-09-06 11:30:25 -04:00
parent 2772daa964
commit 1b8779f93e
2 changed files with 54 additions and 9 deletions

View File

@@ -28,4 +28,5 @@
#include "llsingleton.h" #include "llsingleton.h"
std::map<std::string, void*>* LLSingletonRegistry::sSingletonMap = NULL;

View File

@@ -27,9 +27,33 @@
#include "llerror.h" // *TODO: eliminate this #include "llerror.h" // *TODO: eliminate this
#include <map>
#include <typeinfo> #include <typeinfo>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
/// @brief A global registry of all singletons to prevent duplicate allocations
/// across shared library boundaries
class LL_COMMON_API LLSingletonRegistry
{
typedef std::map<std::string, void *> TypeMap;
static TypeMap* sSingletonMap;
public:
template<typename T> static void * & get()
{
std::string name(typeid(T).name());
if (!sSingletonMap) sSingletonMap = new TypeMap();
// the first entry of the pair returned by insert will be either the existing
// iterator matching our key, or the newly inserted NULL initialized entry
// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
TypeMap::iterator result =
sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
return result->second;
}
};
// LLSingleton implements the getInstance() method part of the Singleton // LLSingleton implements the getInstance() method part of the Singleton
// pattern. It can't make the derived class constructors protected, though, so // pattern. It can't make the derived class constructors protected, though, so
// you have to do that yourself. // you have to do that yourself.
@@ -57,7 +81,7 @@
template <typename DERIVED_TYPE> template <typename DERIVED_TYPE>
class LLSingleton : private boost::noncopyable class LLSingleton : private boost::noncopyable
{ {
private: private:
typedef enum e_init_state typedef enum e_init_state
{ {
@@ -67,12 +91,14 @@ private:
INITIALIZED, INITIALIZED,
DELETED DELETED
} EInitState; } EInitState;
static DERIVED_TYPE* constructSingleton() static DERIVED_TYPE* constructSingleton()
{ {
return new DERIVED_TYPE(); return new DERIVED_TYPE();
} }
struct SingletonData;
// stores pointer to singleton instance // stores pointer to singleton instance
struct SingletonLifetimeManager struct SingletonLifetimeManager
{ {
@@ -83,6 +109,7 @@ private:
static void construct() static void construct()
{ {
SingletonData& sData(getData());
sData.mInitState = CONSTRUCTING; sData.mInitState = CONSTRUCTING;
sData.mInstance = constructSingleton(); sData.mInstance = constructSingleton();
sData.mInitState = INITIALIZING; sData.mInitState = INITIALIZING;
@@ -90,16 +117,18 @@ private:
~SingletonLifetimeManager() ~SingletonLifetimeManager()
{ {
SingletonData& sData(getData());
if (sData.mInitState != DELETED) if (sData.mInitState != DELETED)
{ {
deleteSingleton(); deleteSingleton();
} }
} }
}; };
public: public:
virtual ~LLSingleton() virtual ~LLSingleton()
{ {
SingletonData& sData(getData());
sData.mInstance = NULL; sData.mInstance = NULL;
sData.mInitState = DELETED; sData.mInitState = DELETED;
} }
@@ -126,15 +155,31 @@ public:
*/ */
static void deleteSingleton() static void deleteSingleton()
{ {
SingletonData& sData(getData());
delete sData.mInstance; delete sData.mInstance;
sData.mInstance = NULL; sData.mInstance = NULL;
sData.mInitState = DELETED; sData.mInitState = DELETED;
} }
static SingletonData& getData()
{
// this is static to cache the lookup results
static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
// *TODO - look into making this threadsafe
if (!registry)
{
static SingletonData data;
registry = &data;
}
return *static_cast<SingletonData *>(registry);
}
static DERIVED_TYPE* getInstance() static DERIVED_TYPE* getInstance()
{ {
static SingletonLifetimeManager sLifeTimeMgr; static SingletonLifetimeManager sLifeTimeMgr;
SingletonData& sData(getData());
switch (sData.mInitState) switch (sData.mInitState)
{ {
@@ -168,6 +213,7 @@ public:
static DERIVED_TYPE* getIfExists() static DERIVED_TYPE* getIfExists()
{ {
SingletonData& sData(getData());
return sData.mInstance; return sData.mInstance;
} }
@@ -177,18 +223,20 @@ public:
{ {
return *getInstance(); return *getInstance();
} }
// Has this singleton been created uet? // Has this singleton been created uet?
// Use this to avoid accessing singletons before the can safely be constructed // Use this to avoid accessing singletons before the can safely be constructed
static bool instanceExists() static bool instanceExists()
{ {
SingletonData& sData(getData());
return sData.mInitState == INITIALIZED; return sData.mInitState == INITIALIZED;
} }
// Has this singleton already been deleted? // Has this singleton already been deleted?
// Use this to avoid accessing singletons from a static object's destructor // Use this to avoid accessing singletons from a static object's destructor
static bool destroyed() static bool destroyed()
{ {
SingletonData& sData(getData());
return sData.mInitState == DELETED; return sData.mInitState == DELETED;
} }
@@ -203,10 +251,6 @@ private:
EInitState mInitState; EInitState mInitState;
DERIVED_TYPE* mInstance; DERIVED_TYPE* mInstance;
}; };
static SingletonData sData;
}; };
template<typename T>
typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
#endif #endif