llevents.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:43k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   llevents.h
  3.  * @author Kent Quirk, Nat Goodspeed
  4.  * @date   2008-09-11
  5.  * @brief  This is an implementation of the event system described at
  6.  *         https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
  7.  *         originally introduced in llnotifications.h. It has nothing
  8.  *         whatsoever to do with the older system in llevent.h.
  9.  * 
  10.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  11.  * 
  12.  * Copyright (c) 2008-2010, Linden Research, Inc.
  13.  * 
  14.  * Second Life Viewer Source Code
  15.  * The source code in this file ("Source Code") is provided by Linden Lab
  16.  * to you under the terms of the GNU General Public License, version 2.0
  17.  * ("GPL"), unless you have obtained a separate licensing agreement
  18.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  19.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  20.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  21.  * 
  22.  * There are special exceptions to the terms and conditions of the GPL as
  23.  * it is applied to this Source Code. View the full text of the exception
  24.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  25.  * online at
  26.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  27.  * 
  28.  * By copying, modifying or distributing this software, you acknowledge
  29.  * that you have read and understood your obligations described above,
  30.  * and agree to abide by those obligations.
  31.  * 
  32.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  33.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  34.  * COMPLETENESS OR PERFORMANCE.
  35.  * $/LicenseInfo$
  36.  */
  37. #if ! defined(LL_LLEVENTS_H)
  38. #define LL_LLEVENTS_H
  39. #include <string>
  40. #include <map>
  41. #include <set>
  42. #include <vector>
  43. #include <deque>
  44. #include <stdexcept>
  45. #if LL_WINDOWS
  46. #pragma warning (push)
  47. #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
  48. #pragma warning (disable : 4264) 
  49. #endif
  50. #include <boost/signals2.hpp>
  51. #if LL_WINDOWS
  52. #pragma warning (pop)
  53. #endif
  54. #include <boost/bind.hpp>
  55. #include <boost/shared_ptr.hpp>
  56. #include <boost/enable_shared_from_this.hpp>
  57. #include <boost/utility.hpp>        // noncopyable
  58. #include <boost/optional/optional.hpp>
  59. #include <boost/visit_each.hpp>
  60. #include <boost/ref.hpp>            // reference_wrapper
  61. #include <boost/type_traits/is_pointer.hpp>
  62. #include <boost/function.hpp>
  63. #include <boost/static_assert.hpp>
  64. #include "llsd.h"
  65. #include "llsingleton.h"
  66. #include "lldependencies.h"
  67. #include "ll_template_cast.h"
  68. /*==========================================================================*|
  69. // override this to allow binding free functions with more parameters
  70. #ifndef LLEVENTS_LISTENER_ARITY
  71. #define LLEVENTS_LISTENER_ARITY 10
  72. #endif
  73. |*==========================================================================*/
  74. // hack for testing
  75. #ifndef testable
  76. #define testable private
  77. #endif
  78. /*****************************************************************************
  79. *   Signal and handler declarations
  80. *   Using a single handler signature means that we can have a common handler
  81. *   type, rather than needing a distinct one for each different handler.
  82. *****************************************************************************/
  83. /**
  84.  * A boost::signals Combiner that stops the first time a handler returns true
  85.  * We need this because we want to have our handlers return bool, so that
  86.  * we have the option to cause a handler to stop further processing. The
  87.  * default handler fails when the signal returns a value but has no slots.
  88.  */
  89. struct LLStopWhenHandled
  90. {
  91.     typedef bool result_type;
  92.     template<typename InputIterator>
  93.     result_type operator()(InputIterator first, InputIterator last) const
  94.     {
  95.         for (InputIterator si = first; si != last; ++si)
  96. {
  97.             if (*si)
  98. {
  99.                 return true;
  100. }
  101. }
  102.         return false;
  103.     }
  104. };
  105. /**
  106.  * We want to have a standard signature for all signals; this way,
  107.  * we can easily document a protocol for communicating across
  108.  * dlls and into scripting languages someday.
  109.  *
  110.  * We want to return a bool to indicate whether the signal has been
  111.  * handled and should NOT be passed on to other listeners.
  112.  * Return true to stop further handling of the signal, and false
  113.  * to continue.
  114.  *
  115.  * We take an LLSD because this way the contents of the signal
  116.  * are independent of the API used to communicate it.
  117.  * It is const ref because then there's low cost to pass it;
  118.  * if you only need to inspect it, it's very cheap.
  119.  *
  120.  * @internal
  121.  * The @c float template parameter indicates that we will internally use @c
  122.  * float to indicate relative listener order on a given LLStandardSignal.
  123.  * Don't worry, the @c float values are strictly internal! They are not part
  124.  * of the interface, for the excellent reason that requiring the caller to
  125.  * specify a numeric key to establish order means that the caller must know
  126.  * the universe of possible values. We use LLDependencies for that instead.
  127.  */
  128. typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float>  LLStandardSignal;
  129. /// Methods that forward listeners (e.g. constructed with
  130. /// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
  131. typedef LLStandardSignal::slot_type LLEventListener;
  132. /// Result of registering a listener, supports <tt>connected()</tt>,
  133. /// <tt>disconnect()</tt> and <tt>blocked()</tt>
  134. typedef boost::signals2::connection LLBoundListener;
  135. /// Storing an LLBoundListener in LLTempBoundListener will disconnect the
  136. /// referenced listener when the LLTempBoundListener instance is destroyed.
  137. typedef boost::signals2::scoped_connection LLTempBoundListener;
  138. /**
  139.  * A common idiom for event-based code is to accept either a callable --
  140.  * directly called on completion -- or the string name of an LLEventPump on
  141.  * which to post the completion event. Specifying a parameter as <tt>const
  142.  * LLListenerOrPumpName&</tt> allows either.
  143.  *
  144.  * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD
  145.  * 'event' object, either calls the callable or posts the event to the named
  146.  * LLEventPump.
  147.  *
  148.  * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as
  149.  * the default value of an optional method parameter.) Calling it throws
  150.  * LLListenerOrPumpName::Empty. Test for this condition beforehand using
  151.  * either <tt>if (param)</tt> or <tt>if (! param)</tt>.
  152.  */
  153. class LL_COMMON_API LLListenerOrPumpName
  154. {
  155. public:
  156.     /// passing string name of LLEventPump
  157.     LLListenerOrPumpName(const std::string& pumpname);
  158.     /// passing string literal (overload so compiler isn't forced to infer
  159.     /// double conversion)
  160.     LLListenerOrPumpName(const char* pumpname);
  161.     /// passing listener -- the "anything else" catch-all case. The type of an
  162.     /// object constructed by boost::bind() isn't intended to be written out.
  163.     /// Normally we'd just accept 'const LLEventListener&', but that would
  164.     /// require double implicit conversion: boost::bind() object to
  165.     /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a
  166.     /// template to forward anything.
  167.     template<typename T>
  168.     LLListenerOrPumpName(const T& listener): mListener(listener) {}
  169.     /// for omitted method parameter: uninitialized mListener
  170.     LLListenerOrPumpName() {}
  171.     /// test for validity
  172.     operator bool() const { return bool(mListener); }
  173.     bool operator! () const { return ! mListener; }
  174.     /// explicit accessor
  175.     const LLEventListener& getListener() const { return *mListener; }
  176.     /// implicit conversion to LLEventListener
  177.     operator LLEventListener() const { return *mListener; }
  178.     /// allow calling directly
  179.     bool operator()(const LLSD& event) const;
  180.     /// exception if you try to call when empty
  181.     struct Empty: public std::runtime_error
  182.     {
  183.         Empty(const std::string& what):
  184.             std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
  185.     };
  186. private:
  187.     boost::optional<LLEventListener> mListener;
  188. };
  189. /*****************************************************************************
  190. *   LLEventPumps
  191. *****************************************************************************/
  192. class LLEventPump;
  193. /**
  194.  * LLEventPumps is a Singleton manager through which one typically accesses
  195.  * this subsystem.
  196.  */
  197. class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
  198. {
  199.     friend class LLSingleton<LLEventPumps>;
  200. public:
  201.     /**
  202.      * Find or create an LLEventPump instance with a specific name. We return
  203.      * a reference so there's no question about ownership. obtain() @em finds
  204.      * an instance without conferring @em ownership.
  205.      */
  206.     LLEventPump& obtain(const std::string& name);
  207.     /**
  208.      * Flush all known LLEventPump instances
  209.      */
  210.     void flush();
  211.     /**
  212.      * Reset all known LLEventPump instances
  213.      * workaround for DEV-35406 crash on shutdown
  214.      */
  215.     void reset();
  216. private:
  217.     friend class LLEventPump;
  218.     /**
  219.      * Register a new LLEventPump instance (internal)
  220.      */
  221.     std::string registerNew(const LLEventPump&, const std::string& name, bool tweak);
  222.     /**
  223.      * Unregister a doomed LLEventPump instance (internal)
  224.      */
  225.     void unregister(const LLEventPump&);
  226. private:
  227.     LLEventPumps();
  228.     ~LLEventPumps();
  229. testable:
  230.     // Map of all known LLEventPump instances, whether or not we instantiated
  231.     // them. We store a plain old LLEventPump* because this map doesn't claim
  232.     // ownership of the instances. Though the common usage pattern is to
  233.     // request an instance using obtain(), it's fair to instantiate an
  234.     // LLEventPump subclass statically, as a class member, on the stack or on
  235.     // the heap. In such cases, the instantiating party is responsible for its
  236.     // lifespan.
  237.     typedef std::map<std::string, LLEventPump*> PumpMap;
  238.     PumpMap mPumpMap;
  239.     // Set of all LLEventPumps we instantiated. Membership in this set means
  240.     // we claim ownership, and will delete them when this LLEventPumps is
  241.     // destroyed.
  242.     typedef std::set<LLEventPump*> PumpSet;
  243.     PumpSet mOurPumps;
  244.     // LLEventPump names that should be instantiated as LLEventQueue rather
  245.     // than as LLEventStream
  246.     typedef std::set<std::string> PumpNames;
  247.     PumpNames mQueueNames;
  248. };
  249. /*****************************************************************************
  250. *   details
  251. *****************************************************************************/
  252. namespace LLEventDetail
  253. {
  254.     /// Any callable capable of connecting an LLEventListener to an
  255.     /// LLStandardSignal to produce an LLBoundListener can be mapped to this
  256.     /// signature.
  257.     typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc;
  258.     /// overload of visit_and_connect() when we have a string identifier available
  259.     template <typename LISTENER>
  260.     LLBoundListener visit_and_connect(const std::string& name,
  261.                                       const LISTENER& listener,
  262.                                       const ConnectFunc& connect_func);
  263.     /**
  264.      * Utility template function to use Visitor appropriately
  265.      *
  266.      * @param listener Callable to connect, typically a boost::bind()
  267.      * expression. This will be visited by Visitor using boost::visit_each().
  268.      * @param connect_func Callable that will connect() @a listener to an
  269.      * LLStandardSignal, returning LLBoundListener.
  270.      */
  271.     template <typename LISTENER>
  272.     LLBoundListener visit_and_connect(const LISTENER& listener,
  273.                                       const ConnectFunc& connect_func)
  274.     {
  275.         return visit_and_connect("", listener, connect_func);
  276.     }
  277. } // namespace LLEventDetail
  278. /*****************************************************************************
  279. *   LLEventTrackable
  280. *****************************************************************************/
  281. /**
  282.  * LLEventTrackable wraps boost::signals2::trackable, which resembles
  283.  * boost::trackable. Derive your listener class from LLEventTrackable instead,
  284.  * and use something like
  285.  * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
  286.  * instance, _1))</tt>. This will implicitly disconnect when the object
  287.  * referenced by @c instance is destroyed.
  288.  *
  289.  * @note
  290.  * LLEventTrackable doesn't address a couple of cases:
  291.  * * Object destroyed during call
  292.  *   - You enter a slot call in thread A.
  293.  *   - Thread B destroys the object, which of course disconnects it from any
  294.  *     future slot calls.
  295.  *   - Thread A's call uses 'this', which now refers to a defunct object.
  296.  *     Undefined behavior results.
  297.  * * Call during destruction
  298.  *   - @c MySubclass is derived from LLEventTrackable.
  299.  *   - @c MySubclass registers one of its own methods using
  300.  *     <tt>LLEventPump::listen()</tt>.
  301.  *   - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
  302.  *     runs, destroying state specific to the subclass. (For instance, a
  303.  *     <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
  304.  *   - The listening method will not be disconnected until
  305.  *     <tt>~LLEventTrackable()</tt> runs.
  306.  *   - Before we get there, another thread posts data to the @c LLEventPump
  307.  *     instance, calling the @c MySubclass method.
  308.  *   - The method in question relies on valid @c MySubclass state. (For
  309.  *     instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
  310.  *     <tt>delete</tt>d but not zeroed.)
  311.  *   - Undefined behavior results.
  312.  * If you suspect you may encounter any such scenario, you're better off
  313.  * managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
  314.  * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
  315.  * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
  316.  * thread-safe Boost.Signals2 machinery.
  317.  */
  318. typedef boost::signals2::trackable LLEventTrackable;
  319. /*****************************************************************************
  320. *   LLEventPump
  321. *****************************************************************************/
  322. /**
  323.  * LLEventPump is the base class interface through which we access the
  324.  * concrete subclasses LLEventStream and LLEventQueue.
  325.  *
  326.  * @NOTE
  327.  * LLEventPump derives from LLEventTrackable so that when you "chain"
  328.  * LLEventPump instances together, they will automatically disconnect on
  329.  * destruction. Please see LLEventTrackable documentation for situations in
  330.  * which this may be perilous across threads.
  331.  */
  332. class LL_COMMON_API LLEventPump: public LLEventTrackable
  333. {
  334. public:
  335.     /**
  336.      * Exception thrown by LLEventPump(). You are trying to instantiate an
  337.      * LLEventPump (subclass) using the same name as some other instance, and
  338.      * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
  339.      * variant.
  340.      */
  341.     struct DupPumpName: public std::runtime_error
  342.     {
  343.         DupPumpName(const std::string& what):
  344.             std::runtime_error(std::string("DupPumpName: ") + what) {}
  345.     };
  346.     /**
  347.      * Instantiate an LLEventPump (subclass) with the string name by which it
  348.      * can be found using LLEventPumps::obtain().
  349.      *
  350.      * If you pass (or default) @a tweak to @c false, then a duplicate name
  351.      * will throw DupPumpName. This won't happen if LLEventPumps::obtain()
  352.      * instantiates the LLEventPump, because obtain() uses find-or-create
  353.      * logic. It can only happen if you instantiate an LLEventPump in your own
  354.      * code -- and a collision with the name of some other LLEventPump is
  355.      * likely to cause much more subtle problems!
  356.      *
  357.      * When you hand-instantiate an LLEventPump, consider passing @a tweak as
  358.      * @c true. This directs LLEventPump() to append a suffix to the passed @a
  359.      * name to make it unique. You can retrieve the adjusted name by calling
  360.      * getName() on your new instance.
  361.      */
  362.     LLEventPump(const std::string& name, bool tweak=false);
  363.     virtual ~LLEventPump();
  364.     /// group exceptions thrown by listen(). We use exceptions because these
  365.     /// particular errors are likely to be coding errors, found and fixed by
  366.     /// the developer even before preliminary checkin.
  367.     struct ListenError: public std::runtime_error
  368.     {
  369.         ListenError(const std::string& what): std::runtime_error(what) {}
  370.     };
  371.     /**
  372.      * exception thrown by listen(). You are attempting to register a
  373.      * listener on this LLEventPump using the same listener name as an
  374.      * already-registered listener.
  375.      */
  376.     struct DupListenerName: public ListenError
  377.     {
  378.         DupListenerName(const std::string& what):
  379.             ListenError(std::string("DupListenerName: ") + what)
  380.         {}
  381.     };
  382.     /**
  383.      * exception thrown by listen(). The order dependencies specified for your
  384.      * listener are incompatible with existing listeners.
  385.      *
  386.      * Consider listener "a" which specifies before "b" and "b" which
  387.      * specifies before "c". You are now attempting to register "c" before
  388.      * "a". There is no order that can satisfy all constraints.
  389.      */
  390.     struct Cycle: public ListenError
  391.     {
  392.         Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {}
  393.     };
  394.     /**
  395.      * exception thrown by listen(). This one means that your new listener
  396.      * would force a change to the order of previously-registered listeners,
  397.      * and we don't have a good way to implement that.
  398.      *
  399.      * Consider listeners "some", "other" and "third". "some" and "other" are
  400.      * registered earlier without specifying relative order, so "other"
  401.      * happens to be first. Now you attempt to register "third" after "some"
  402.      * and before "other". Whoops, that would require swapping "some" and
  403.      * "other", which we can't do. Instead we throw this exception.
  404.      *
  405.      * It may not be possible to change the registration order so we already
  406.      * know "third"s order requirement by the time we register the second of
  407.      * "some" and "other". A solution would be to specify that "some" must
  408.      * come before "other", or equivalently that "other" must come after
  409.      * "some".
  410.      */
  411.     struct OrderChange: public ListenError
  412.     {
  413.         OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {}
  414.     };
  415.     /// used by listen()
  416.     typedef std::vector<std::string> NameList;
  417.     /// convenience placeholder for when you explicitly want to pass an empty
  418.     /// NameList
  419.     const static NameList empty;
  420.     /// Get this LLEventPump's name
  421.     std::string getName() const { return mName; }
  422.     /**
  423.      * Register a new listener with a unique name. Specify an optional list
  424.      * of other listener names after which this one must be called, likewise
  425.      * an optional list of other listener names before which this one must be
  426.      * called. The other listeners mentioned need not yet be registered
  427.      * themselves. listen() can throw any ListenError; see ListenError
  428.      * subclasses.
  429.      *
  430.      * The listener name must be unique among active listeners for this
  431.      * LLEventPump, else you get DupListenerName. If you don't care to invent
  432.      * a name yourself, use inventName(). (I was tempted to recognize e.g. ""
  433.      * and internally generate a distinct name for that case. But that would
  434.      * handle badly the scenario in which you want to add, remove, re-add,
  435.      * etc. the same listener: each new listen() call would necessarily
  436.      * perform a new dependency sort. Assuming you specify the same
  437.      * after/before lists each time, using inventName() when you first
  438.      * instantiate your listener, then passing the same name on each listen()
  439.      * call, allows us to optimize away the second and subsequent dependency
  440.      * sorts.
  441.      *
  442.      * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
  443.      * listener, listen() will inspect the components of that expression. If a
  444.      * bound object matches any of several cases, the connection will
  445.      * automatically be disconnected when that object is destroyed.
  446.      *
  447.      * * You bind a <tt>boost::weak_ptr</tt>.
  448.      * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
  449.      *   referenced object would @em never be destroyed, since the @c
  450.      *   shared_ptr stored in the LLEventPump would remain an outstanding
  451.      *   reference. Use the weaken() function to convert your @c shared_ptr to
  452.      *   @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr
  453.      *   will produce a compile error (@c BOOST_STATIC_ASSERT failure).
  454.      * * You bind a simple pointer or reference to an object derived from
  455.      *   <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION)
  456.      * * You bind a simple pointer or reference to an object derived from
  457.      *   LLEventTrackable. Unlike the cases described above, though, this is
  458.      *   vulnerable to a couple of cross-thread race conditions, as described
  459.      *   in the LLEventTrackable documentation.
  460.      */
  461.     template <typename LISTENER>
  462.     LLBoundListener listen(const std::string& name, const LISTENER& listener,
  463.                            const NameList& after=NameList(),
  464.                            const NameList& before=NameList())
  465.     {
  466.         // Examine listener, using our listen_impl() method to make the
  467.         // actual connection.
  468.         // This is why listen() is a template. Conversion from boost::bind()
  469.         // to LLEventListener performs type erasure, so it's important to look
  470.         // at the boost::bind object itself before that happens.
  471.         return LLEventDetail::visit_and_connect(name,
  472.                                                 listener,
  473.                                                 boost::bind(&LLEventPump::listen_impl,
  474.                                                             this,
  475.                                                             name,
  476.                                                             _1,
  477.                                                             after,
  478.                                                             before));
  479.     }
  480.     /// Get the LLBoundListener associated with the passed name (dummy
  481.     /// LLBoundListener if not found)
  482.     virtual LLBoundListener getListener(const std::string& name) const;
  483.     /**
  484.      * Instantiate one of these to block an existing connection:
  485.      * @code
  486.      * { // in some local scope
  487.      *     LLEventPump::Blocker block(someLLBoundListener);
  488.      *     // code that needs the connection blocked
  489.      * } // unblock the connection again
  490.      * @endcode
  491.      */
  492.     typedef boost::signals2::shared_connection_block Blocker;
  493.     /// Unregister a listener by name. Prefer this to
  494.     /// <tt>getListener(name).disconnect()</tt> because stopListening() also
  495.     /// forgets this name.
  496.     virtual void stopListening(const std::string& name);
  497.     /// Post an event to all listeners. The @c bool return is only meaningful
  498.     /// if the underlying leaf class is LLEventStream -- beware of relying on
  499.     /// it too much! Truthfully, we return @c bool mostly to permit chaining
  500.     /// one LLEventPump as a listener on another.
  501.     virtual bool post(const LLSD&) = 0;
  502.     /// Enable/disable: while disabled, silently ignore all post() calls
  503.     virtual void enable(bool enabled=true) { mEnabled = enabled; }
  504.     /// query
  505.     virtual bool enabled() const { return mEnabled; }
  506.     /// Generate a distinct name for a listener -- see listen()
  507.     static std::string inventName(const std::string& pfx="listener");
  508. private:
  509.     friend class LLEventPumps;
  510.     /// flush queued events
  511.     virtual void flush() {}
  512.     virtual void reset();
  513. private:
  514.     virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
  515.                                         const NameList& after,
  516.                                         const NameList& before);
  517.     std::string mName;
  518. protected:
  519.     /// implement the dispatching
  520.     boost::shared_ptr<LLStandardSignal> mSignal;
  521.     /// valve open?
  522.     bool mEnabled;
  523.     /// Map of named listeners. This tracks the listeners that actually exist
  524.     /// at this moment. When we stopListening(), we discard the entry from
  525.     /// this map.
  526.     typedef std::map<std::string, boost::signals2::connection> ConnectionMap;
  527.     ConnectionMap mConnections;
  528.     typedef LLDependencies<std::string, float> DependencyMap;
  529.     /// Dependencies between listeners. For each listener, track the float
  530.     /// used to establish its place in mSignal's order. This caches all the
  531.     /// listeners that have ever registered; stopListening() does not discard
  532.     /// the entry from this map. This is to avoid a new dependency sort if the
  533.     /// same listener with the same dependencies keeps hopping on and off this
  534.     /// LLEventPump.
  535.     DependencyMap mDeps;
  536. };
  537. /*****************************************************************************
  538. *   LLEventStream
  539. *****************************************************************************/
  540. /**
  541.  * LLEventStream is a thin wrapper around LLStandardSignal. Posting an
  542.  * event immediately calls all registered listeners.
  543.  */
  544. class LL_COMMON_API LLEventStream: public LLEventPump
  545. {
  546. public:
  547.     LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
  548.     virtual ~LLEventStream() {}
  549.     /// Post an event to all listeners
  550.     virtual bool post(const LLSD& event);
  551. };
  552. /*****************************************************************************
  553. *   LLEventQueue
  554. *****************************************************************************/
  555. /**
  556.  * LLEventQueue isa LLEventPump whose post() method defers calling registered
  557.  * listeners until flush() is called.
  558.  */
  559. class LL_COMMON_API LLEventQueue: public LLEventPump
  560. {
  561. public:
  562.     LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
  563.     virtual ~LLEventQueue() {}
  564.     /// Post an event to all listeners
  565.     virtual bool post(const LLSD& event);
  566. private:
  567.     /// flush queued events
  568.     virtual void flush();
  569. private:
  570.     typedef std::deque<LLSD> EventQueue;
  571.     EventQueue mEventQueue;
  572. };
  573. /*****************************************************************************
  574. *   LLReqID
  575. *****************************************************************************/
  576. /**
  577.  * This class helps the implementer of a given event API to honor the
  578.  * ["reqid"] convention. By this convention, each event API stamps into its
  579.  * response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
  580.  * any, from the corresponding request.
  581.  *
  582.  * This supports an (atypical, but occasionally necessary) use case in which
  583.  * two or more asynchronous requests are multiplexed onto the same ["reply"]
  584.  * LLEventPump. Since the response events could arrive in arbitrary order, the
  585.  * caller must be able to demux them. It does so by matching the ["reqid"]
  586.  * value in each response with the ["reqid"] value in the corresponding
  587.  * request.
  588.  *
  589.  * It is the caller's responsibility to ensure distinct ["reqid"] values for
  590.  * that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
  591.  * the "namespace" of unique ["reqid"] values is simply the set of requests
  592.  * specifying the same ["reply"] LLEventPump name.
  593.  *
  594.  * Making a given event API echo the request's ["reqid"] into the response is
  595.  * nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
  596.  * place to put these comments. We hope that each time a coder implements a
  597.  * new event API based on some existing one, s/he will say, "Huh, what's an
  598.  * LLReqID?" and look up this material.
  599.  *
  600.  * The hardest part about the convention is deciding where to store the
  601.  * ["reqid"] value. Ironically, LLReqID can't help with that: you must store
  602.  * an LLReqID instance in whatever storage will persist until the reply is
  603.  * sent. For example, if the request ultimately ends up using a Responder
  604.  * subclass, storing an LLReqID instance in the Responder works.
  605.  *
  606.  * @note
  607.  * The @em implementer of an event API must honor the ["reqid"] convention.
  608.  * However, the @em caller of an event API need only use it if s/he is sharing
  609.  * the same ["reply"] LLEventPump for two or more asynchronous event API
  610.  * requests.
  611.  *
  612.  * In most cases, it's far easier for the caller to instantiate a local
  613.  * LLEventStream and pass its name to the event API in question. Then it's
  614.  * perfectly reasonable not to set a ["reqid"] key in the request, ignoring
  615.  * the @c isUndefined() ["reqid"] value in the response.
  616.  */
  617. class LL_COMMON_API LLReqID
  618. {
  619. public:
  620.     /**
  621.      * If you have the request in hand at the time you instantiate the
  622.      * LLReqID, pass that request to extract its ["reqid"].
  623.  */
  624.     LLReqID(const LLSD& request):
  625.         mReqid(request["reqid"])
  626.     {}
  627.     /// If you don't yet have the request, use setFrom() later.
  628.     LLReqID() {}
  629.     /// Extract and store the ["reqid"] value from an incoming request.
  630.     void setFrom(const LLSD& request)
  631.     {
  632.         mReqid = request["reqid"];
  633.     }
  634.     /// Set ["reqid"] key into a pending response LLSD object.
  635.     void stamp(LLSD& response) const;
  636.     /// Make a whole new response LLSD object with our ["reqid"].
  637.     LLSD makeResponse() const
  638.     {
  639.         LLSD response;
  640.         stamp(response);
  641.         return response;
  642.     }
  643.     /// Not really sure of a use case for this accessor...
  644.     LLSD getReqID() const { return mReqid; }
  645. private:
  646.     LLSD mReqid;
  647. };
  648. /**
  649.  * Base class for LLListenerWrapper. See visit_and_connect() and llwrap(). We
  650.  * provide virtual @c accept_xxx() methods, customization points allowing a
  651.  * subclass access to certain data visible at LLEventPump::listen() time.
  652.  * Example subclass usage:
  653.  *
  654.  * @code
  655.  * myEventPump.listen("somename",
  656.  *                    llwrap<MyListenerWrapper>(boost::bind(&MyClass::method, instance, _1)));
  657.  * @endcode
  658.  *
  659.  * Because of the anticipated usage (note the anonymous temporary
  660.  * MyListenerWrapper instance in the example above), the @c accept_xxx()
  661.  * methods must be @c const.
  662.  */
  663. class LL_COMMON_API LLListenerWrapperBase
  664. {
  665. public:
  666.     /// New instance. The accept_xxx() machinery makes it important to use
  667.     /// shared_ptrs for our data. Many copies of this object are made before
  668.     /// the instance that actually ends up in the signal, yet accept_xxx()
  669.     /// will later be called on the @em original instance. All copies of the
  670.     /// same original instance must share the same data.
  671.     LLListenerWrapperBase():
  672.         mName(new std::string),
  673.         mConnection(new LLBoundListener)
  674.     {
  675.     }
  676.     /// Copy constructor. Copy shared_ptrs to original instance data.
  677.     LLListenerWrapperBase(const LLListenerWrapperBase& that):
  678.         mName(that.mName),
  679.         mConnection(that.mConnection)
  680.     {
  681.     }
  682. virtual ~LLListenerWrapperBase() {}
  683.     /// Ask LLEventPump::listen() for the listener name
  684.     virtual void accept_name(const std::string& name) const
  685.     {
  686.         *mName = name;
  687.     }
  688.     /// Ask LLEventPump::listen() for the new connection
  689.     virtual void accept_connection(const LLBoundListener& connection) const
  690.     {
  691.         *mConnection = connection;
  692.     }
  693. protected:
  694.     /// Listener name.
  695.     boost::shared_ptr<std::string> mName;
  696.     /// Connection.
  697.     boost::shared_ptr<LLBoundListener> mConnection;
  698. };
  699. /*****************************************************************************
  700. *   Underpinnings
  701. *****************************************************************************/
  702. /**
  703.  * We originally provided a suite of overloaded
  704.  * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
  705.  * LLEventPump::listen(...) and then pass the returned LLBoundListener to
  706.  * LLEventTrackable::track(). This was workable but error-prone: the coder
  707.  * must remember to call listenTo() rather than the more straightforward
  708.  * listen() method.
  709.  *
  710.  * Now we publish only the single canonical listen() method, so there's a
  711.  * uniform mechanism. Having a single way to do this is good, in that there's
  712.  * no question in the coder's mind which of several alternatives to choose.
  713.  *
  714.  * To support automatic connection management, we use boost::visit_each
  715.  * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to
  716.  * inspect each argument of a boost::bind expression. (Although the visit_each
  717.  * mechanism was first introduced with the original Boost.Signals library, it
  718.  * was only later documented.)
  719.  *
  720.  * Cases:
  721.  * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass
  722.  *   the corresponding shared_ptr to slot_type::track(). Ideally that would be
  723.  *   the object whose method we want to call, but in fact we do the same for
  724.  *   any weak_ptr we might find among the bound arguments. If we're passing
  725.  *   our bound method a weak_ptr to some object, wouldn't the destruction of
  726.  *   that object invalidate the call? So we disconnect automatically when any
  727.  *   such object is destroyed. This is the mechanism preferred by boost::
  728.  *   signals2.
  729.  * * One of the functions's arguments is a boost::shared_ptr<T>. This produces
  730.  *   a compile error: the bound copy of the shared_ptr stored in the
  731.  *   boost_bind object stored in the signal object would make the referenced
  732.  *   T object immortal. We provide a weaken() function. Pass
  733.  *   weaken(your_shared_ptr) instead. (We can inspect, but not modify, the
  734.  *   boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr
  735.  *   implicitly and just proceed.)
  736.  * * One of the function's arguments is a plain pointer/reference to an object
  737.  *   derived from boost::enable_shared_from_this. We assume that this object
  738.  *   is managed using boost::shared_ptr, so we implicitly extract a shared_ptr
  739.  *   and track that. (UNDER CONSTRUCTION)
  740.  * * One of the function's arguments is derived from LLEventTrackable. Pass
  741.  *   the LLBoundListener to its LLEventTrackable::track(). This is vulnerable
  742.  *   to a couple different race conditions, as described in LLEventTrackable
  743.  *   documentation. (NOTE: Now that LLEventTrackable is a typedef for
  744.  *   boost::signals2::trackable, the Signals2 library handles this itself, so
  745.  *   our visitor needs no special logic for this case.)
  746.  * * Any other argument type is irrelevant to automatic connection management.
  747.  */
  748. namespace LLEventDetail
  749. {
  750.     template <typename F>
  751.     const F& unwrap(const F& f) { return f; }
  752.     template <typename F>
  753.     const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); }
  754.     // Most of the following is lifted from the Boost.Signals use of
  755.     // visit_each.
  756.     template<bool Cond> struct truth {};
  757.     /**
  758.      * boost::visit_each() Visitor, used on a template argument <tt>const F&
  759.      * f</tt> as follows (see visit_and_connect()):
  760.      * @code
  761.      * LLEventListener listener(f);
  762.      * Visitor visitor(listener); // bind listener so it can track() shared_ptrs
  763.      * using boost::visit_each;   // allow unqualified visit_each() call for ADL
  764.      * visit_each(visitor, unwrap(f));
  765.      * @endcode
  766.      */
  767.     class Visitor
  768.     {
  769.     public:
  770.         /**
  771.          * Visitor binds a reference to LLEventListener so we can track() any
  772.          * shared_ptrs we find in the argument list.
  773.          */
  774.         Visitor(LLEventListener& listener):
  775.             mListener(listener)
  776.         {
  777.         }
  778.         /**
  779.          * boost::visit_each() calls this method for each component of a
  780.          * boost::bind() expression.
  781.          */
  782.         template <typename T>
  783.         void operator()(const T& t) const
  784.         {
  785.             decode(t, 0);
  786.         }
  787.     private:
  788.         // decode() decides between a reference wrapper and anything else
  789.         // boost::ref() variant
  790.         template<typename T>
  791.         void decode(const boost::reference_wrapper<T>& t, int) const
  792.         {
  793. //          add_if_trackable(t.get_pointer());
  794.         }
  795.         // decode() anything else
  796.         template<typename T>
  797.         void decode(const T& t, long) const
  798.         {
  799.             typedef truth<(boost::is_pointer<T>::value)> is_a_pointer;
  800.             maybe_get_pointer(t, is_a_pointer());
  801.         }
  802.         // maybe_get_pointer() decides between a pointer and a non-pointer
  803.         // plain pointer variant
  804.         template<typename T>
  805.         void maybe_get_pointer(const T& t, truth<true>) const
  806.         {
  807. //          add_if_trackable(t);
  808.         }
  809.         // shared_ptr variant
  810.         template<typename T>
  811.         void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const
  812.         {
  813.             // If we have a shared_ptr to this object, it doesn't matter
  814.             // whether the object is derived from LLEventTrackable, so no
  815.             // further analysis of T is needed.
  816. //          mListener.track(t);
  817.             // Make this case illegal. Passing a bound shared_ptr to
  818.             // slot_type::track() is useless, since the bound shared_ptr will
  819.             // keep the object alive anyway! Force the coder to cast to weak_ptr.
  820.             // Trivial as it is, make the BOOST_STATIC_ASSERT() condition
  821.             // dependent on template param so the macro is only evaluated if
  822.             // this method is in fact instantiated, as described here:
  823.             // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html
  824.             // ATTENTION: Don't bind a shared_ptr<anything> using
  825.             // LLEventPump::listen(boost::bind()). Doing so captures a copy of
  826.             // the shared_ptr, making the referenced object effectively
  827.             // immortal. Use the weaken() function, e.g.:
  828.             // somepump.listen(boost::bind(...weaken(my_shared_ptr)...));
  829.             // This lets us automatically disconnect when the referenced
  830.             // object is destroyed.
  831.             BOOST_STATIC_ASSERT(sizeof(T) == 0);
  832.         }
  833.         // weak_ptr variant
  834.         template<typename T>
  835.         void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const
  836.         {
  837.             // If we have a weak_ptr to this object, it doesn't matter
  838.             // whether the object is derived from LLEventTrackable, so no
  839.             // further analysis of T is needed.
  840.             mListener.track(t);
  841. //          std::cout << "Found weak_ptr<" << typeid(T).name() << ">!n";
  842.         }
  843. #if 0
  844.         // reference to anything derived from boost::enable_shared_from_this
  845.         template <typename T>
  846.         inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct,
  847.                                       truth<false>) const
  848.         {
  849.             // Use the slot_type::track(shared_ptr) mechanism. Cast away
  850.             // const-ness because (in our code base anyway) it's unusual
  851.             // to find shared_ptr<const T>.
  852.             boost::enable_shared_from_this<T>&
  853.                 t(const_cast<boost::enable_shared_from_this<T>&>(ct));
  854.             std::cout << "Capturing shared_from_this()" << std::endl;
  855.             boost::shared_ptr<T> sp(t.shared_from_this());
  856. /*==========================================================================*|
  857.             std::cout << "Capturing weak_ptr" << std::endl;
  858.             boost::weak_ptr<T> wp(sp);
  859. |*==========================================================================*/
  860.             std::cout << "Tracking shared__ptr" << std::endl;
  861.             mListener.track(sp);
  862.         }
  863. #endif
  864.         // non-pointer variant
  865.         template<typename T>
  866.         void maybe_get_pointer(const T& t, truth<false>) const
  867.         {
  868.             // Take the address of this object, because the object itself may be
  869.             // trackable
  870. //          add_if_trackable(boost::addressof(t));
  871.         }
  872. /*==========================================================================*|
  873.         // add_if_trackable() adds LLEventTrackable objects to mTrackables
  874.         inline void add_if_trackable(const LLEventTrackable* t) const
  875.         {
  876.             if (t)
  877.             {
  878.             }
  879.         }
  880.         // pointer to anything not an LLEventTrackable subclass
  881.         inline void add_if_trackable(const void*) const
  882.         {
  883.         }
  884.         // pointer to free function
  885.         // The following construct uses the preprocessor to generate
  886.         // add_if_trackable() overloads accepting pointer-to-function taking
  887.         // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type.
  888. #define BOOST_PP_LOCAL_MACRO(n)                                     
  889.         template <typename R                                        
  890.                   BOOST_PP_COMMA_IF(n)                              
  891.                   BOOST_PP_ENUM_PARAMS(n, typename T)>              
  892.         inline void                                                 
  893.         add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const   
  894.         {                                                           
  895.         }
  896. #define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY)
  897. #include BOOST_PP_LOCAL_ITERATE()
  898. #undef  BOOST_PP_LOCAL_MACRO
  899. #undef  BOOST_PP_LOCAL_LIMITS
  900. |*==========================================================================*/
  901.         /// Bind a reference to the LLEventListener to call its track() method.
  902.         LLEventListener& mListener;
  903.     };
  904.     /**
  905.      * Utility template function to use Visitor appropriately
  906.      *
  907.      * @param raw_listener Callable to connect, typically a boost::bind()
  908.      * expression. This will be visited by Visitor using boost::visit_each().
  909.      * @param connect_funct Callable that will connect() @a raw_listener to an
  910.      * LLStandardSignal, returning LLBoundListener.
  911.      */
  912.     template <typename LISTENER>
  913.     LLBoundListener visit_and_connect(const std::string& name,
  914.                                       const LISTENER& raw_listener,
  915.                                       const ConnectFunc& connect_func)
  916.     {
  917.         // Capture the listener
  918.         LLEventListener listener(raw_listener);
  919.         // Define our Visitor, binding the listener so we can call
  920.         // listener.track() if we discover any shared_ptr<Foo>.
  921.         LLEventDetail::Visitor visitor(listener);
  922.         // Allow unqualified visit_each() call for ADL
  923.         using boost::visit_each;
  924.         // Visit each component of a boost::bind() expression. Pass
  925.         // 'raw_listener', our template argument, rather than 'listener' from
  926.         // which type details have been erased. unwrap() comes from
  927.         // Boost.Signals, in case we were passed a boost::ref().
  928.         visit_each(visitor, LLEventDetail::unwrap(raw_listener));
  929.         // Make the connection using passed function.
  930.         LLBoundListener connection(connect_func(listener));
  931.         // If the LISTENER is an LLListenerWrapperBase subclass, pass it the
  932.         // desired information. It's important that we pass the raw_listener
  933.         // so the compiler can make decisions based on its original type.
  934.         const LLListenerWrapperBase* lwb =
  935.             ll_template_cast<const LLListenerWrapperBase*>(&raw_listener);
  936.         if (lwb)
  937.         {
  938.             lwb->accept_name(name);
  939.             lwb->accept_connection(connection);
  940.         }
  941.         // In any case, show new connection to caller.
  942.         return connection;
  943.     }
  944. } // namespace LLEventDetail
  945. // Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
  946. // listen() fails in Boost code trying to instantiate LLEventListener (i.e.
  947. // LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
  948. // specialized for boost::weak_ptr. This remedies that omission.
  949. namespace boost
  950. {
  951.     template <typename T>
  952.     T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
  953. }
  954. /// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an
  955. /// easy way to cast to the corresponding weak_ptr.
  956. template <typename T>
  957. boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr)
  958. {
  959.     return boost::weak_ptr<T>(ptr);
  960. }
  961. #endif /* ! defined(LL_LLEVENTS_H) */