From a087bbeda3229745cb625fbd1106438572dfee4a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 May 2009 23:31:47 +0000 Subject: Any static instance of an STL container introduces static-initializer-order bugs. Use internal, informal singleton pattern to work around that. --- indra/llcommon/llinstancetracker.h | 54 +++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 11f4063a1d..21d16e9ef7 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -39,9 +39,9 @@ #include "string_table.h" #include -// This mix-in class adds support for tracking all instances of the specificed class parameter T +// 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 list +// If KEY is not provided, then instances are stored in a simple set template class LLInstanceTracker : boost::noncopyable { @@ -49,11 +49,11 @@ public: typedef typename std::map::iterator instance_iter; typedef typename std::map::const_iterator instance_const_iter; - static T* getInstance(const KEY& k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; } + static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; } - static instance_iter beginInstances() { return sInstances.begin(); } - static instance_iter endInstances() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } + static instance_iter beginInstances() { return getMap().begin(); } + static instance_iter endInstances() { return getMap().end(); } + static S32 instanceCount() { return getMap().size(); } protected: LLInstanceTracker(KEY key) { add(key); } virtual ~LLInstanceTracker() { remove(); } @@ -64,14 +64,23 @@ private: void add(KEY key) { mKey = key; - sInstances[key] = static_cast(this); + getMap()[key] = static_cast(this); } - void remove() { sInstances.erase(mKey); } + void remove() { getMap().erase(mKey); } + + static std::map& getMap() + { + if (! sInstances) + { + sInstances = new std::map; + } + return *sInstances; + } private: KEY mKey; - static std::map sInstances; + static std::map* sInstances; }; template @@ -81,20 +90,29 @@ public: typedef typename std::set::iterator instance_iter; typedef typename std::set::const_iterator instance_const_iter; - static instance_iter instancesBegin() { return sInstances.begin(); } - static instance_iter instancesEnd() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } + static instance_iter instancesBegin() { return getSet().begin(); } + static instance_iter instancesEnd() { return getSet().end(); } + static S32 instanceCount() { return getSet().size(); } protected: - LLInstanceTracker() { sInstances.insert(static_cast(this)); } - virtual ~LLInstanceTracker() { sInstances.erase(static_cast(this)); } + LLInstanceTracker() { getSet().insert(static_cast(this)); } + virtual ~LLInstanceTracker() { getSet().erase(static_cast(this)); } + + LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast(this)); } - LLInstanceTracker(const LLInstanceTracker& other) { sInstances.insert(static_cast(this)); } + static std::set& getSet() // called after getReady() but before go() + { + if (! sInstances) + { + sInstances = new std::set; + } + return *sInstances; + } - static std::set sInstances; + static std::set* sInstances; }; -template std::map LLInstanceTracker::sInstances; -template std::set LLInstanceTracker::sInstances; +template std::map* LLInstanceTracker::sInstances = NULL; +template std::set* LLInstanceTracker::sInstances = NULL; #endif -- cgit v1.2.3