1. 10 Oct, 2019 1 commit
  2. 16 Sep, 2019 1 commit
  3. 10 Sep, 2019 3 commits
  4. 05 Sep, 2019 1 commit
  5. 04 Sep, 2019 4 commits
  6. 02 Sep, 2019 1 commit
  7. 29 Aug, 2019 1 commit
  8. 26 Aug, 2019 3 commits
  9. 20 Aug, 2019 3 commits
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-493: Clarify capturing LLError::getFatalFunction() in a var. · 5b5eb55f
      Nat Goodspeed authored
      VS 2013 thought we were storing an initialization-list.
      5b5eb55f
    • Nat Goodspeed's avatar
      DRTVWR-493: Defend LL[Param]Singleton against ctor/init exceptions. · 54b98cb8
      Nat Goodspeed authored
      An exception in the LLSingleton subclass constructor, or in its
      initSingleton() method, could leave the LLSingleton machinery in a bad state:
      the failing instance would remain in the MasterList, also on the stack of
      initializing LLSingletons. Catch exceptions in either and perform relevant
      cleanup.
      
      This problem is highlighted by test programs, in which LL_ERRS throws an
      exception rather than crashing the whole process.
      
      In the relevant catch clauses, clean up the initializing stack BEFORE logging.
      Otherwise we get tangled up recording bogus dependencies.
      
      Move capture_dependency() out of finishInitializing(): it must be called by
      every valid getInstance() call, both from LLSingleton and LLParamSingleton.
      
      Introduce new CONSTRUCTED EInitState value to distinguish "have called the
      constructor but not yet the initSingleton() method" from "currently within
      initSingleton() method." This is transient, but we execute the 'switch' on
      state within that moment. One could argue that the previous enum used
      INITIALIZING for current CONSTRUCTED, and INITIALIZED meant INITIALIZING too,
      but this is clearer.
      
      Introduce template LLSingletonBase::classname() helper methods to clarify
      verbose demangle(typeid(stuff).name()) calls.
      
      Similarly, introduce LLSingleton::pop_initializing() shorthand method.
      54b98cb8
  10. 19 Aug, 2019 2 commits
    • Nat Goodspeed's avatar
      DRTVWR-493: Improve exception safety of LLSingleton initialization. · 310db14b
      Nat Goodspeed authored
      Add try/catch clauses to constructSingleton() (to catch exceptions in the
      subclass constructor) and finishInitializing() (to catch exceptions in the
      subclass initSingleton() method). Each of these catch clauses rethrows the
      exception -- they're for cleanup, not for ultimate handling.
      
      Introduce LLSingletonBase::reset_initializing(list_t::size_t). The idea is
      that since we can't know whether the exception happened before or after the
      push_initializing() call in LLSingletonBase's constructor, we can't just pop
      the stack. Instead, constructSingleton() captures the stack size before
      attempting to construct the new LLSingleton subclass. On exception, it calls
      reset_initializing() to restore the stack to that size.
      
      Naturally that requires a corresponding LLSingleton_manage_master method,
      whose MasterList specialization is a no-op.
      
      finishInitializing()'s exception handling is a bit simpler because it has a
      constructed LLSingleton subclass instance in hand, therefore
      push_initializing() has definitely been called, therefore it can call
      pop_initializing().
      
      Break out new static capture_dependency() method from finishInitializing()
      because, in the previous LLSingleton::getInstance() implementation, the logic
      now wrapped in capture_dependency() was reached even in the INITIALIZED case.
      TODO: Add a new EInitState to differentiate "have been constructed, now
      calling initSingleton()" from "fully initialized, normal case" -- in the
      latter control path we should not be calling capture_dependency().
      
      The LLSingleton_manage_master<LLSingletonBase::MasterList> specialization's
      get_initializing() function (which called get_initializing_from()) was
      potentially dangerous. get_initializing() is called by push_initializing(),
      which (in the general case) is called by LLSingletonBase's constructor. If
      somehow the MasterList's LLSingletonBase constructor ended up calling
      get_initializing(), it would have called get_initializing_from(), passing an
      LLSingletonBase which had not yet been constructed into the MasterList. In
      particular, its mInitializing map would not yet have been initialized at all.
      
      Since the MasterList must not, by design, depend on any other LLSingletons,
      LLSingleton_manage_master<LLSingletonBase::MasterList>::get_initializing()
      need not return a list from the official mInitializing map anyway. It can, and
      should, and now does, return a static dummy list. That obviates
      get_initializing_from(), which is removed.
      
      That in turn means we no longer need to pass get_initializing() an
      LLSingletonBase*. Remove that parameter.
      310db14b
    • Nat Goodspeed's avatar
  11. 15 Aug, 2019 1 commit
  12. 14 Aug, 2019 3 commits
  13. 13 Aug, 2019 8 commits
  14. 12 Aug, 2019 8 commits
    • Nat Goodspeed's avatar
      DRTVWR-493: Rely on recursive_mutex to handle circularity · 5196af86
      Nat Goodspeed authored
      from LLParamSingleton::initSingleton().
      5196af86
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-493: Permit LLParamSingleton::initSingleton() circularity. · 4fce6dc4
      Nat Goodspeed authored
      This was forbidden, but AndreyK points out cases in which LLParamSingleton::
      initSingleton() should in fact be allowed to circle back to its own instance()
      method. Use a recursive_mutex instead of plain mutex to permit that; remove
      LL_ERRS preventing it.
      
      Add LLParamSingleton::instance() method that calls
      LLParamSingleton::getInstance(). Inheriting LLSingleton::instance() called
      LLSingleton::getInstance() -- not at all what we want.
      
      Add LLParamSingleton unit tests.
      4fce6dc4
    • andreykproductengine's avatar
      3c552696
    • andreykproductengine's avatar
      Merge from nat_linden/drtvwr-493 · b6a3901c
      andreykproductengine authored
      b6a3901c
    • AndreyL ProductEngine's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-493: Streamline LLParamSingleton, LLLockedSingleton. · 98be6e14
      Nat Goodspeed authored
      Simplify LLSingleton::SingletonLifetimeManager to SingletonInitializer: that
      struct has not been responsible for deletion ever since LLSingletonBase
      acquired dependency-ordered deleteAll().
      
      Move SingletonData::mInitState changes from SingletonLifetimeManager to
      constructSingleton() method. Similarly, constructSingleton() now sets
      SingletonData::mInstance instead of making its caller store the pointer.
      
      Add variadic arguments to LLSingleton::constructSingleton() so we can reuse it
      for LLParamSingleton.
      
      Add finishInitializing() method to encapsulate logic reused for
      getInstance()'s INITIALIZING and DELETED cases.
      
      Make LLParamSingleton a subclass of LLSingleton, just as LLLockedSingleton is
      a subclass of LLParamSingleton. Make LLParamSingleton a friend of LLSingleton,
      so it can access private members of LLSingleton without also granting access
      to any DERIVED_CLASS subclass. This eliminates the need for protected
      getInitState().
      
      LLParamSingleton::initParamSingleton() reuses LLSingleton::constructSingleton()
      and finishInitializing(). Its getInstance() method completely replaces
      LLSingleton::getInstance(): in most EInitStates, LLParamSingleton::getInstance()
      is an error.
      
      Use a std::mutex to serialize calls to LLParamSingleton::initParamSingleton()
      and getInstance(). While LLSingleton::getInstance() relies on the "initialized
      exactly once" guarantee for block-scope static declarations, LLParamSingleton
      cannot rely on the same mechanism.
      
      LLLockedSingleton is now a very succinct subclass of LLParamSingleton -- they
      have very similar functionality.
      
      Giving the LLSINGLETON() macro variadic arguments eliminates the need for a
      separate LLPARAMSINGLETON() macro, while continuing to support existing usage.
      98be6e14