Skip to content
Snippets Groups Projects
  1. Apr 09, 2020
  2. Mar 25, 2020
    • Nat Goodspeed's avatar
      DRTVWR-476: Eliminate static LLEventPump factory maps. · 95a218fc
      Nat Goodspeed authored
      Having a map from std::string to a factory function returning LLEventPump* is
      a cool idea, especially since you could statically populate such a map with
      string literals and little lambdas.
      
      Unfortunately, static initialization of any data is a bad idea when control
      can reach consuming code before that module's static data are constructed.
      
      Since LLEventPumps is already an LLSingleton, it's simple enough to make its
      map non-static and initialize it in the constructor.
      
      But another recent static factory-function map was introduced in
      llleaplistener.cpp to support the LLLeapListener::newpump() operation. That
      involves no LLSingletons.
      
      Introduce LLEventPumps::make(name, tweak, type) to instantiate an LLEventPump
      subclass of the specified type with specified (name, tweak) parameters.
      Instances returned by make() are owned by LLEventPumps, as with obtain().
      Introduce LLEventPumps::BadType exception for when the type string isn't
      recognized.
      
      LLEventPumps::obtain() can then simply call make() when the specified instance
      name doesn't already exist. The configuration data used internally by obtain()
      becomes { string instance name, string subclass name }. Although this too is
      currently initialized in the LLEventPumps constructor, migrating it to a
      configuration file would now be far more straightforward than before.
      
      LLLeapListener::newpump(), too, can call LLEventPumps::make() with the
      caller-specified type string. This eliminates that static factory map.
      newpump() must catch BadType and report the error back to its invoker.
      
      Given that the LLEventPump subclass instances returned by make() are owned by
      LLEventPumps rather than LLLeapListener, there is no further need for the
      LLLeapListener::mEventPumps ptr_map, which was used only to manage lifetime.
      Also remove LLLeapListener's "killpump" operation since LLEventPumps provides
      no corresponding functionality.
      95a218fc
    • Nat Goodspeed's avatar
      DRTVWR-476: Kill LLEventQueue, per-frame LLEventPump::flush() calls. · 79a3e391
      Nat Goodspeed authored
      No one uses LLEventQueue to defer posted events until the next mainloop tick
      -- and with LLCoros moving to Boost.Fiber, cross-coroutine event posting works
      that way anyway, making LLEventQueue pretty unnecessary.
      
      The static RegisterFlush instance in llevents.cpp was used to call
      LLEventPumps::flush() once per mainloop tick, which in turn called flush() on
      every registered LLEventPump. But the only reason for that mechanism was to
      support LLEventQueue. In fact, when LLEventMailDrop overrode its flush()
      method for something quite different, it was startling to find that the new
      flush() override was being called once per frame -- which caused at least one
      fairly mysterious bug. Remove RegisterFlush. Both LLEventPumps::flush() and
      LLEventPump::flush() remain for now, though intended usage is unclear.
      
      Eliminating LLEventQueue means we must at least repurpose
      LLEventPumps::mQueueNames, a map intended to make LLEventPumps::obtain()
      instantiate an LLEventQueue rather than the default LLEventPump. Replace it
      with mFactories, a map from desired instance name to a callable returning
      LLEventPump*. New map initialization syntax plus lambda support allows us to
      populate that map at compile time with little lambdas returning the correct
      subclass instance.
      
      Similarly, LLLeapListener::newpump() used to check the ["type"] entry in the
      LLSD request specifically for "LLEventQueue". Introduce another such map in
      llleaplistener.cpp for potential future extensibility.
      
      Eliminate the LLEventQueue-specific test.
      79a3e391
    • Nat Goodspeed's avatar
      DRTVWR-494: Defend LLInstanceTracker against multi-thread usage. · 9d5b8976
      Nat Goodspeed authored
      The previous implementation went to some effort to crash if anyone attempted
      to create or destroy an LLInstanceTracker subclass instance during traversal.
      That restriction is manageable within a single thread, but becomes unworkable
      if it's possible that a given subclass might be used on more than one thread.
      
      Remove LLInstanceTracker::instance_iter, beginInstances(), endInstances(),
      also key_iter, beginKeys() and endKeys(). Instead, introduce key_snapshot()
      and instance_snapshot(), the only means of iterating over LLInstanceTracker
      instances. (These are intended to resemble functions, but in fact the current
      implementation simply presents the classes.) Iterating over a captured
      snapshot defends against container modifications during traversal. The term
      'snapshot' reminds the coder that a new instance created during traversal will
      not be considered. To defend against instance deletion during traversal, a
      snapshot stores std::weak_ptrs which it lazily dereferences, skipping on the
      fly any that have expired.
      
      Dereferencing instance_snapshot::iterator gets you a reference rather than a
      pointer. Because some use cases want to delete all existing instances, add an
      instance_snapshot::deleteAll() method that extracts the pointer. Those cases
      used to require explicitly copying instance pointers into a separate
      container; instance_snapshot() now takes care of that. It remains the caller's
      responsibility to ensure that all instances of that LLInstanceTracker subclass
      were allocated on the heap.
      
      Replace unkeyed static LLInstanceTracker::getInstance(T*) -- which returned
      nullptr if that instance had been destroyed -- with new getWeak() method
      returning std::weak_ptr<T>. Caller must detect expiration of that weak_ptr.
      
      Adjust tests accordingly.
      
      Use of std::weak_ptr to detect expired instances requires engaging
      std::shared_ptr in the constructor. We now store shared_ptrs in the static
      containers (std::map for keyed, std::set for unkeyed).
      
      Make LLInstanceTrackerBase a template parameterized on the type of the static
      data it manages. For that reason, hoist static data class declarations out of
      the class definitions to an LLInstanceTrackerStuff namespace.
      
      Remove the static atomic sIterationNestDepth and its methods incrementDepth(),
      decrementDepth() and getDepth(), since they were used only to forbid creation
      and destruction during traversal.
      
      Add a std::mutex to static data. Introduce an internal LockStatic class that
      locks the mutex while providing a pointer to static data, making that the only
      way to access the static data.
      
      The LLINSTANCETRACKER_DTOR_NOEXCEPT macro goes away because we no longer
      expect ~LLInstanceTracker() to throw an exception in test programs.
      That affects LLTrace::StatBase as well as LLInstanceTracker itself.
      
      Adapt consumers to the new LLInstanceTracker API.
      9d5b8976
  3. Nov 10, 2015
  4. Mar 29, 2013
  5. Mar 16, 2012
Loading