summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2015-06-26 13:03:59 -0400
committerNat Goodspeed <nat@lindenlab.com>2015-06-26 13:03:59 -0400
commit687efd84eabc524e339e61458b0cbf53f9a38f8a (patch)
tree492879aa9fa5e9383a5a3a7c285e7aaf4cc6df13
parentaefdba1230de456784d220982ab8b4dbe3cde17d (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-xindra/llcommon/llsingleton.cpp19
-rwxr-xr-xindra/llcommon/llsingleton.h22
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;
}