diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llsingleton.cpp | 67 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 16 | 
2 files changed, 66 insertions, 17 deletions
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index cd5c2a7f0e..479244400d 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -38,7 +38,11 @@  namespace {  void log(LLError::ELevel level, -         const char* p1="", const char* p2="", const char* p3="", const char* p4=""); +         const char* p1, const char* p2, const char* p3, const char* p4); + +void logdebugs(const char* p1="", const char* p2="", const char* p3="", const char* p4=""); + +bool oktolog();  } // anonymous namespace  // Our master list of all LLSingletons is itself an LLSingleton. We used to @@ -95,38 +99,64 @@ LLSingletonBase::list_t& LLSingletonBase::get_initializing()      return sList;  } -LLSingletonBase::LLSingletonBase(): +LLSingletonBase::LLSingletonBase(const char* name):      mCleaned(false),      mDeleteSingleton(NULL)  {      // Make this the currently-initializing LLSingleton. -    push_initializing(); +    push_initializing(name);  }  LLSingletonBase::~LLSingletonBase() {} -void LLSingletonBase::push_initializing() +void LLSingletonBase::push_initializing(const char* name)  { +    // log BEFORE pushing so logging singletons don't cry circularity +    log_initializing("Pushing", name);      get_initializing().push_back(this);  }  void LLSingletonBase::pop_initializing()  {      list_t& list(get_initializing()); +      if (list.empty())      {          logerrs("Underflow in stack of currently-initializing LLSingletons at ",                  demangle(typeid(*this).name()).c_str(), "::getInstance()");      } -    if (list.back() != this) + +    // Now we know list.back() exists: capture it +    LLSingletonBase* back(list.back()); +    // and pop it +    list.pop_back(); + +    if (back != this)      { -        LLSingletonBase* back(list.back());          logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ",                  demangle(typeid(*this).name()).c_str(), "::getInstance() trying to pop ",                  demangle(typeid(*back).name()).c_str());      } -    // Here we're sure that list.back() == this. Whew, pop it. -    list.pop_back(); + +    // log AFTER popping so logging singletons don't cry circularity +    log_initializing("Popping", typeid(*back).name()); +} + +//static +void LLSingletonBase::log_initializing(const char* verb, const char* name) +{ +    if (oktolog()) +    { +        LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';'; +        list_t& list(get_initializing()); +        for (list_t::const_reverse_iterator ri(list.rbegin()), rend(list.rend()); +             ri != rend; ++ri) +        { +            LLSingletonBase* sb(*ri); +            LL_CONT << ' ' << demangle(typeid(*sb).name()); +        } +        LL_ENDL; +    }  }  void LLSingletonBase::capture_dependency(EInitState initState) @@ -181,8 +211,8 @@ void LLSingletonBase::capture_dependency(EInitState initState)              if (current->mDepends.insert(this).second)              {                  // only log the FIRST time we hit this dependency! -                log(LLError::LEVEL_DEBUG, demangle(typeid(*current).name()).c_str(), -                    " depends on ", demangle(typeid(*this).name()).c_str()); +                logdebugs(demangle(typeid(*current).name()).c_str(), +                          " depends on ", demangle(typeid(*this).name()).c_str());              }          }      } @@ -240,8 +270,8 @@ void LLSingletonBase::cleanupAll()          {              sp->mCleaned = true; -            log(LLError::LEVEL_DEBUG, "calling ", -                demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()"); +            logdebugs("calling ", +                      demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()");              try              {                  sp->cleanupSingleton(); @@ -280,7 +310,7 @@ void LLSingletonBase::deleteAll()              else              {                  // properly initialized: call it. -                log(LLError::LEVEL_DEBUG, "calling ", name.c_str(), "::deleteSingleton()"); +                logdebugs("calling ", name.c_str(), "::deleteSingleton()");                  // From this point on, DO NOT DEREFERENCE sp!                  sp->mDeleteSingleton();              } @@ -331,6 +361,12 @@ void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc)  /*---------------------------- Logging helpers -----------------------------*/  namespace { +bool oktolog() +{ +    // See comments in log() below. +    return sMasterRefcount.refcount && LLError::is_available(); +} +  void log(LLError::ELevel level,           const char* p1, const char* p2, const char* p3, const char* p4)  { @@ -362,6 +398,11 @@ void log(LLError::ELevel level,          std::cerr << p1 << p2 << p3 << p4 << std::endl;      }  } + +void logdebugs(const char* p1, const char* p2, const char* p3, const char* p4) +{ +    log(LLError::LEVEL_DEBUG, p1, p2, p3, p4); +}  } // anonymous namespace          //static diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 6a7f27bed4..78092fdc11 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -66,8 +66,10 @@ protected:      } EInitState;      // Base-class constructor should only be invoked by the DERIVED_TYPE -    // constructor. -    LLSingletonBase(); +    // constructor, which passes the DERIVED_TYPE class name for logging +    // purposes. Within LLSingletonBase::LLSingletonBase, of course the +    // formula typeid(*this).name() produces "LLSingletonBase". +    LLSingletonBase(const char* name);      virtual ~LLSingletonBase();      // Every new LLSingleton should be added to/removed from the master list @@ -87,11 +89,15 @@ protected:      // single C++ scope, else we'd use RAII to track it. But we do know that      // LLSingletonBase's constructor definitely runs just before      // LLSingleton's, which runs just before the specific subclass's. -    void push_initializing(); +    void push_initializing(const char*);      // LLSingleton is, and must remain, the only caller to initSingleton().      // That being the case, we control exactly when it happens -- and we can      // pop the stack immediately thereafter.      void pop_initializing(); +private: +    // logging +    static void log_initializing(const char* verb, const char* name); +protected:      // 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(EInitState); @@ -281,7 +287,9 @@ private:      };  protected: -    LLSingleton() +    // Use typeid(DERIVED_TYPE) rather than typeid(*this) because, until our +    // constructor completes, *this isn't yet a full-fledged DERIVED_TYPE. +    LLSingleton(): LLSingletonBase(typeid(DERIVED_TYPE).name())      {          // populate base-class function pointer with the static          // deleteSingleton() function for this particular specialization  | 
