diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2015-06-26 13:03:59 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2015-06-26 13:03:59 -0400 | 
| commit | 687efd84eabc524e339e61458b0cbf53f9a38f8a (patch) | |
| tree | 492879aa9fa5e9383a5a3a7c285e7aaf4cc6df13 | |
| parent | aefdba1230de456784d220982ab8b4dbe3cde17d (diff) | |
MAINT-5232: Loosen LLSingleton circularity constraints slightly.
LLSingleton explicitly supports circular dependencies: initialization
performed during an LLSingleton subclass's initSingleton() method may
recursively call that same subclass's getInstance() method. On the other hand,
circularity from a subclass constructor cannot be permitted, else
getInstance() would have to return a partially-constructed object.
Our dependency tracking circularity check initially forbade both. Loosen it to
permit references from within initSingleton().
| -rwxr-xr-x | indra/llcommon/llsingleton.cpp | 19 | ||||
| -rwxr-xr-x | indra/llcommon/llsingleton.h | 22 | 
2 files changed, 24 insertions, 17 deletions
| diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index a3edf925ad..2813814ae1 100755 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -123,7 +123,7 @@ void LLSingletonBase::pop_initializing()      list.pop_back();  } -void LLSingletonBase::capture_dependency() +void LLSingletonBase::capture_dependency(EInitState initState)  {      // Did this getInstance() call come from another LLSingleton, or from      // vanilla application code? Note that although this is a nontrivial @@ -150,11 +150,18 @@ void LLSingletonBase::capture_dependency()                  // is the actual LLSingletonBase instance.                  out << typeid(**found).name() << " -> ";              } -            // DEBUGGING: Initially, make this crump. We want to know how bad -            // the problem is before we add it to the long, sad list of -            // ominous warnings that everyone always ignores. -            logerrs("LLSingleton circularity: ", out.str().c_str(), -                    typeid(*this).name()); +            // We promise to capture dependencies from both the constructor +            // and the initSingleton() method, so an LLSingleton's instance +            // pointer is on the initializing list during both. Now that we've +            // detected circularity, though, we must distinguish the two. If +            // the recursive call is from the constructor, we CAN'T honor it: +            // otherwise we'd be returning a pointer to a partially- +            // constructed object! But from initSingleton() is okay: that +            // method exists specifically to support circularity. +            // Decide which log helper to call based on initState. They have +            // identical signatures. +            ((initState == CONSTRUCTING)? logerrs : logwarns) +                ("LLSingleton circularity: ", out.str().c_str(), typeid(*this).name(), "");          }          else          { diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 25bdba0a0d..a82101c367 100755 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -58,6 +58,15 @@ private:      set_t mDepends;  protected: +    typedef enum e_init_state +    { +        UNINITIALIZED = 0,          // must be default-initialized state +        CONSTRUCTING, +        INITIALIZING, +        INITIALIZED, +        DELETED +    } EInitState; +      // Base-class constructor should only be invoked by the DERIVED_TYPE      // constructor.      LLSingletonBase(); @@ -87,7 +96,7 @@ protected:      void pop_initializing();      // If a given call to B::getInstance() happens during either A::A() or      // A::initSingleton(), record that A directly depends on B. -    void capture_dependency(); +    void capture_dependency(EInitState);      // delegate LL_ERRS() logging to llsingleton.cpp      static void logerrs(const char* p1, const char* p2="", @@ -232,15 +241,6 @@ template <typename DERIVED_TYPE>  class LLSingleton : public LLSingletonBase  {  private: -    typedef enum e_init_state -    { -        UNINITIALIZED = 0,          // must be default-initialized state -        CONSTRUCTING, -        INITIALIZING, -        INITIALIZED, -        DELETED -    } EInitState; -      static DERIVED_TYPE* constructSingleton()      {          return new DERIVED_TYPE(); @@ -377,7 +377,7 @@ public:          // an LLSingleton that directly depends on DERIVED_TYPE. If this call          // came from another LLSingleton, rather than from vanilla application          // code, record the dependency. -        sData.mInstance->capture_dependency(); +        sData.mInstance->capture_dependency(sData.mInitState);          return sData.mInstance;      } | 
