This commit is contained in:
Drake Arconis
2014-09-10 01:03:04 -04:00
266 changed files with 3057 additions and 2383 deletions

View File

@@ -270,6 +270,9 @@ list(APPEND llcommon_SOURCE_FILES ${cwdebug_SOURCE_FILES})
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
if(WINDOWS)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
endif(WINDOWS)
add_dependencies(llcommon prepare)
target_link_libraries(
llcommon

View File

@@ -307,8 +307,10 @@ public:
virtual ~StaticRegistrar() {}
StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
{
if(!singleton_t::instance().mStaticScope)
mStaticScope = new ScopedRegistrar();
if (singleton_t::instance().exists(key))
{
llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl;
}
singleton_t::instance().mStaticScope->add(key, value);
}
};
@@ -338,7 +340,7 @@ protected:
virtual void initSingleton()
{
//mStaticScope = new ScopedRegistrar();
mStaticScope = new ScopedRegistrar();
}
virtual ~LLRegistrySingleton()

View File

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

View File

@@ -33,34 +33,25 @@
/// @brief A global registry of all singletons to prevent duplicate allocations
/// across shared library boundaries
class LL_COMMON_API LLSingletonRegistry {
private:
typedef std::map<std::string, void *> TypeMap;
static TypeMap * sSingletonMap;
class LL_COMMON_API LLSingletonRegistry
{
typedef std::map<std::string, void *> TypeMap;
static TypeMap* sSingletonMap;
static void checkInit()
{
if(sSingletonMap == NULL)
{
sSingletonMap = new TypeMap();
}
}
public:
template<typename T> static void * & get()
{
std::string name(typeid(T).name());
if (!sSingletonMap) sSingletonMap = new TypeMap();
public:
template<typename T> static void * & get()
{
std::string name(typeid(T).name());
// 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;
checkInit();
// 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;
}
return result->second;
}
};
// LLSingleton implements the getInstance() method part of the Singleton
@@ -90,7 +81,7 @@ class LL_COMMON_API LLSingletonRegistry {
template <typename DERIVED_TYPE>
class LLSingleton : private boost::noncopyable
{
private:
typedef enum e_init_state
{
@@ -100,34 +91,46 @@ private:
INITIALIZED,
DELETED
} EInitState;
// stores pointer to singleton instance
// and tracks initialization state of singleton
struct SingletonInstanceData
{
EInitState mInitState;
DERIVED_TYPE* mSingletonInstance;
SingletonInstanceData()
: mSingletonInstance(NULL),
mInitState(UNINITIALIZED)
{}
~SingletonInstanceData()
static DERIVED_TYPE* constructSingleton()
{
return new DERIVED_TYPE();
}
struct SingletonData;
// stores pointer to singleton instance
struct SingletonLifetimeManager
{
SingletonLifetimeManager()
{
if (mInitState != DELETED)
construct();
}
static void construct()
{
SingletonData& sData(getData());
sData.mInitState = CONSTRUCTING;
sData.mInstance = constructSingleton();
sData.mInitState = INITIALIZING;
}
~SingletonLifetimeManager()
{
SingletonData& sData(getData());
if (sData.mInitState != DELETED)
{
deleteSingleton();
}
}
};
public:
virtual ~LLSingleton()
{
SingletonInstanceData& data = getData();
data.mSingletonInstance = NULL;
data.mInitState = DELETED;
SingletonData& sData(getData());
sData.mInstance = NULL;
sData.mInitState = DELETED;
}
/**
@@ -152,37 +155,66 @@ public:
*/
static void deleteSingleton()
{
DERIVED_TYPE* instance = getData().mSingletonInstance;
getData().mInitState = DELETED;
getData().mSingletonInstance = NULL;
delete instance;
SingletonData& sData(getData());
delete sData.mInstance;
sData.mInstance = NULL;
sData.mInitState = DELETED;
}
static SingletonInstanceData& getData()
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(NULL == registry)
if (!registry)
{
static SingletonInstanceData data;
static SingletonData data;
registry = &data;
}
return *static_cast<SingletonInstanceData *>(registry);
return *static_cast<SingletonData *>(registry);
}
static DERIVED_TYPE* getInstance()
{
SingletonInstanceData& data = getData();
static SingletonLifetimeManager sLifeTimeMgr;
SingletonData& sData(getData());
if (data.mInitState != INITIALIZED)
switch (sData.mInitState)
{
createInstance(data);
case UNINITIALIZED:
// should never be uninitialized at this point
llassert(false);
return NULL;
case CONSTRUCTING:
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL;
return NULL;
case INITIALIZING:
// go ahead and flag ourselves as initialized so we can be reentrant during initialization
sData.mInitState = INITIALIZED;
// initialize singleton after constructing it so that it can reference other singletons which in turn depend on it,
// thus breaking cyclic dependencies
sData.mInstance->initSingleton();
return sData.mInstance;
case INITIALIZED:
return sData.mInstance;
case DELETED:
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL;
SingletonLifetimeManager::construct();
// same as first time construction
sData.mInitState = INITIALIZED;
sData.mInstance->initSingleton();
return sData.mInstance;
}
return data.mSingletonInstance;
return NULL;
}
static DERIVED_TYPE* getIfExists()
{
SingletonData& sData(getData());
return sData.mInstance;
}
// Reference version of getInstance()
@@ -191,51 +223,34 @@ public:
{
return *getInstance();
}
// Has this singleton been created uet?
// Use this to avoid accessing singletons before the can safely be constructed
static bool instanceExists()
{
return getData().mInitState == INITIALIZED;
SingletonData& sData(getData());
return sData.mInitState == INITIALIZED;
}
// Has this singleton already been deleted?
// Use this to avoid accessing singletons from a static object's destructor
static bool destroyed()
{
return getData().mInitState == DELETED;
SingletonData& sData(getData());
return sData.mInitState == DELETED;
}
private:
static void createInstance(SingletonInstanceData& data);
virtual void initSingleton() {}
struct SingletonData
{
// explicitly has a default constructor so that member variables are zero initialized in BSS
// and only changed by singleton logic, not constructor running during startup
EInitState mInitState;
DERIVED_TYPE* mInstance;
};
};
// Moved this here cause it's too big to be inlined --Aleric.
template<typename DERIVED_TYPE>
void LLSingleton<DERIVED_TYPE>::createInstance(SingletonInstanceData& data)
{
if (data.mInitState == CONSTRUCTING)
{
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
}
if (data.mInitState == DELETED)
{
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
}
if (data.mInitState == INITIALIZING)
{
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from initSingleton(), using half-initialized object" << llendl;
return;
}
data.mInitState = CONSTRUCTING;
data.mSingletonInstance = new DERIVED_TYPE();
data.mInitState = INITIALIZING;
data.mSingletonInstance->initSingleton();
data.mInitState = INITIALIZED;
}
#endif

View File

@@ -35,7 +35,7 @@
const S32 LL_VERSION_MAJOR = 1;
const S32 LL_VERSION_MINOR = 8;
const S32 LL_VERSION_PATCH = 5;
const S32 LL_VERSION_PATCH = 6;
const S32 LL_VERSION_BUILD = ${vBUILD};
const char * const LL_CHANNEL = "${VIEWER_CHANNEL}";