PageRenderTime 54ms CodeModel.GetById 10ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llevents.h

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