Fix for "doubleton" error using LLInstanceTracker across shared library boundaries.

master
brad kittenbrink 2011-03-09 17:01:08 -08:00
parent 30a772c5f1
commit b9a9b0017d
3 changed files with 33 additions and 15 deletions

View File

@ -62,6 +62,7 @@ set(llcommon_SOURCE_FILES
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
llinstancetracker.cpp
llliveappconfig.cpp
lllivefile.cpp
lllog.cpp

View File

@ -32,6 +32,17 @@
// external library headers
// other Linden headers
// llinstancetracker.h is presently header-only. This file exists only because our CMake
// test macro ADD_BUILD_TEST requires it.
int dummy = 0;
//static
void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
{
static std::map<std::string, void *> instances;
std::string k = info.name();
if(instances.find(k) == instances.end())
{
instances[k] = NULL;
}
return instances[k];
}

View File

@ -37,14 +37,21 @@
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
{
protected:
static void * & getInstances(std::type_info const & info);
};
/// This mix-in class adds support for tracking all instances of the specified class parameter T
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
/// If KEY is not provided, then instances are stored in a simple set
/// @NOTE: see explicit specialization below for default KEY==T* case
template<typename T, typename KEY = T*>
class LLInstanceTracker : boost::noncopyable
class LLInstanceTracker : public LLInstanceTrackerBase
{
typedef typename std::map<KEY, T*> InstanceMap;
typedef LLInstanceTracker<T, KEY> MyT;
typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
public:
@ -99,25 +106,26 @@ private:
static InstanceMap& getMap_()
{
if (! sInstances)
void * & instances = getInstances(typeid(MyT));
if (! instances)
{
sInstances = new InstanceMap;
instances = new InstanceMap;
}
return *sInstances;
return * static_cast<InstanceMap*>(instances);
}
private:
KEY mKey;
static InstanceMap* sInstances;
};
/// explicit specialization for default case where KEY is T*
/// use a simple std::set<T*>
template<typename T>
class LLInstanceTracker<T, T*>
class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
{
typedef typename std::set<T*> InstanceSet;
typedef LLInstanceTracker<T, T*> MyT;
public:
/// Dereferencing key_iter gives you a T* (since T* is the key)
typedef typename InstanceSet::iterator key_iter;
@ -172,19 +180,17 @@ protected:
static InstanceSet& getSet_()
{
if (! sInstances)
void * & instances = getInstances(typeid(MyT));
if (! instances)
{
sInstances = new InstanceSet;
instances = new InstanceSet;
}
return *sInstances;
return * static_cast<InstanceSet *>(instances);
}
static InstanceSet* sInstances;
static S32 sIterationNestDepth;
};
template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
#endif