From dc3833f31b8a20220ddb1775e1625c016c397435 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 19 Jun 2009 00:17:30 +0000 Subject: DEV-31980: extract dispatch-by-string-name logic from LLAresListener to new LLEventDispatcher and LLDispatchListener classes. See LLAresListener for example usage. --- indra/llcommon/lleventdispatcher.h | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 indra/llcommon/lleventdispatcher.h (limited to 'indra/llcommon/lleventdispatcher.h') diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h new file mode 100644 index 0000000000..d75055fd6f --- /dev/null +++ b/indra/llcommon/lleventdispatcher.h @@ -0,0 +1,108 @@ +/** + * @file lleventdispatcher.h + * @author Nat Goodspeed + * @date 2009-06-18 + * @brief Central mechanism for dispatching events by string name. This is + * useful when you have a single LLEventPump listener on which you can + * request different operations, vs. instantiating a different + * LLEventPump for each such operation. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTDISPATCHER_H) +#define LL_LLEVENTDISPATCHER_H + +#include +#include +#include +#include +#include +#include "llevents.h" + +class LLSD; + +/** + * Given an LLSD map, examine a string-valued key and call a corresponding + * callable. This class is designed to be contained by an LLEventPump + * listener class that will register some of its own methods, though any + * callable can be used. + */ +class LLEventDispatcher +{ +public: + LLEventDispatcher(const std::string& desc, const std::string& key); + virtual ~LLEventDispatcher(); + + /// Accept any C++ callable, typically a boost::bind() expression + typedef boost::function Callable; + + /// Register a @a callable by @a name. The optional @a required parameter + /// is used to validate the structure of each incoming event (see + /// llsd_matches()). + void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); + + /// Special case: a subclass of this class can register a @a method + /// without explicitly specifying the boost::bind() expression. + /// The optional @a required parameter is used to validate the structure + /// of each incoming event (see llsd_matches()). + template + void add(const std::string& name, void (CLASS::*method)(const LLSD&), + const LLSD& required=LLSD()) + { + CLASS* downcast = dynamic_cast(this); + if (! downcast) + { + addFail(name, typeid(CLASS).name()); + } + else + { + add(name, boost::bind(method, downcast, _1), required); + } + } + + /// Unregister a callable + bool remove(const std::string& name); + + /// Call a registered callable with an explicitly-specified name. If no + /// such callable exists, die with LL_ERRS. If the @a event fails to match + /// the @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const std::string& name, const LLSD& event) const; + + /// Extract the @a key value from the incoming @a event, and call the + /// callable whose name is specified by that map @a key. If no such + /// callable exists, die with LL_ERRS. If the @a event fails to match the + /// @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const LLSD& event) const; + +private: + void addFail(const std::string& name, const std::string& classname) const; + /// try to dispatch, return @c true if success + bool attemptCall(const std::string& name, const LLSD& event) const; + + std::string mDesc, mKey; + typedef std::map > DispatchMap; + DispatchMap mDispatch; +}; + +/** + * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class + * that contains (or derives from) LLDispatchListener need only specify the + * LLEventPump name and dispatch key, and add() its methods. Incoming events + * will automatically be dispatched. + */ +class LLDispatchListener: public LLEventDispatcher +{ +public: + LLDispatchListener(const std::string& pumpname, const std::string& key); + +private: + bool process(const LLSD& event); + + LLEventStream mPump; + LLTempBoundListener mBoundListener; +}; + +#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */ -- cgit v1.2.3 From da46eb9e7e0f6e069e7fc06176849d213876bfe3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 24 Jun 2009 01:54:57 +0000 Subject: DEV-31980: Extend LLEventDispatcher to handle const as well as non-const methods. Introduce LLAppViewerListener based on LLDispatchListener, instantiate a static one in llappviewer.cpp. Initial implementation only supports ["op"] == "requestQuit". --- indra/llcommon/lleventdispatcher.h | 131 ++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 16 deletions(-) (limited to 'indra/llcommon/lleventdispatcher.h') diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index d75055fd6f..e43d967ed4 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -23,6 +23,40 @@ #include "llevents.h" class LLSD; +/*==========================================================================*| +class LLEventDispatcher; + +namespace LLEventDetail +{ + /// For a given call to add(), decide whether we're being passed an + /// unbound member function pointer or a plain callable. + /// Default case. + template + struct AddCallable + { + void operator()(LLEventDispatcher& disp, const std::string& name, + const CALLABLE& callable, const LLSD& required); + }; + + /// Unbound member function pointer + template + struct AddCallable + { + typedef void (CLASS::*Method)(const LLSD&); + void operator()(LLEventDispatcher& disp, const std::string& name, + Method method, const LLSD& required); + }; + + /// Unbound const member function pointer + template + struct AddCallable + { + typedef void (CLASS::*Method)(const LLSD&) const; + void operator()(LLEventDispatcher& disp, const std::string& name, + Method method, const LLSD& required); + }; +} +|*==========================================================================*/ /** * Given an LLSD map, examine a string-valued key and call a corresponding @@ -39,28 +73,36 @@ public: /// Accept any C++ callable, typically a boost::bind() expression typedef boost::function Callable; - /// Register a @a callable by @a name. The optional @a required parameter - /// is used to validate the structure of each incoming event (see - /// llsd_matches()). + /** + * Register a @a callable by @a name. The optional @a required parameter + * is used to validate the structure of each incoming event (see + * llsd_matches()). + */ void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); +/*==========================================================================*| + { + LLEventDetail::AddCallable()(*this, name, callable, required); + } +|*==========================================================================*/ - /// Special case: a subclass of this class can register a @a method - /// without explicitly specifying the boost::bind() expression. - /// The optional @a required parameter is used to validate the structure - /// of each incoming event (see llsd_matches()). + /** + * Special case: a subclass of this class can pass an unbound member + * function pointer without explicitly specifying the + * boost::bind() expression. + */ template void add(const std::string& name, void (CLASS::*method)(const LLSD&), const LLSD& required=LLSD()) { - CLASS* downcast = dynamic_cast(this); - if (! downcast) - { - addFail(name, typeid(CLASS).name()); - } - else - { - add(name, boost::bind(method, downcast, _1), required); - } + addMethod(name, method, required); + } + + /// Overload for both const and non-const methods + template + void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, + const LLSD& required=LLSD()) + { + addMethod(name, method, required); } /// Unregister a callable @@ -78,6 +120,19 @@ public: void operator()(const LLSD& event) const; private: + template + void addMethod(const std::string& name, const METHOD& method, const LLSD& required) + { + CLASS* downcast = dynamic_cast(this); + if (! downcast) + { + addFail(name, typeid(CLASS).name()); + } + else + { + add(name, boost::bind(method, downcast, _1), required); + } + } void addFail(const std::string& name, const std::string& classname) const; /// try to dispatch, return @c true if success bool attemptCall(const std::string& name, const LLSD& event) const; @@ -87,6 +142,50 @@ private: DispatchMap mDispatch; }; +/*==========================================================================*| +/// Have to implement these template specialization methods after +/// LLEventDispatcher so they can use its methods +template +void LLEventDetail::AddCallable::operator()( + LLEventDispatcher& disp, const std::string& name, const CALLABLE& callable, const LLSD& required) +{ + disp.addImpl(name, callable, required); +} + +template +void LLEventDetail::AddCallable::operator()( + LLEventDispatcher& disp, const std::string& name, const Method& method, const LLSD& required) +{ + CLASS* downcast = dynamic_cast(&disp); + if (! downcast) + { + disp.addFail(name, typeid(CLASS).name()); + } + else + { + disp.addImpl(name, boost::bind(method, downcast, _1), required); + } +} + +/// Have to overload for both const and non-const methods +template +void LLEventDetail::AddCallable::operator()( + LLEventDispatcher& disp, const std::string& name, const Method& method, const LLSD& required) +{ + // I am severely bummed that I have, as yet, found no way short of a + // macro to avoid replicating the (admittedly brief) body of this overload. + CLASS* downcast = dynamic_cast(&disp); + if (! downcast) + { + disp.addFail(name, typeid(CLASS).name()); + } + else + { + disp.addImpl(name, boost::bind(method, downcast, _1), required); + } +} +|*==========================================================================*/ + /** * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class * that contains (or derives from) LLDispatchListener need only specify the -- cgit v1.2.3 From 70d99b2528acb3bc503d3ac799e42d52515b6260 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 24 Jun 2009 16:25:33 +0000 Subject: DEV-31980: remove cruft from lleventdispatcher.h --- indra/llcommon/lleventdispatcher.h | 83 -------------------------------------- 1 file changed, 83 deletions(-) (limited to 'indra/llcommon/lleventdispatcher.h') diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index e43d967ed4..4da0a01c69 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -23,40 +23,6 @@ #include "llevents.h" class LLSD; -/*==========================================================================*| -class LLEventDispatcher; - -namespace LLEventDetail -{ - /// For a given call to add(), decide whether we're being passed an - /// unbound member function pointer or a plain callable. - /// Default case. - template - struct AddCallable - { - void operator()(LLEventDispatcher& disp, const std::string& name, - const CALLABLE& callable, const LLSD& required); - }; - - /// Unbound member function pointer - template - struct AddCallable - { - typedef void (CLASS::*Method)(const LLSD&); - void operator()(LLEventDispatcher& disp, const std::string& name, - Method method, const LLSD& required); - }; - - /// Unbound const member function pointer - template - struct AddCallable - { - typedef void (CLASS::*Method)(const LLSD&) const; - void operator()(LLEventDispatcher& disp, const std::string& name, - Method method, const LLSD& required); - }; -} -|*==========================================================================*/ /** * Given an LLSD map, examine a string-valued key and call a corresponding @@ -79,11 +45,6 @@ public: * llsd_matches()). */ void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); -/*==========================================================================*| - { - LLEventDetail::AddCallable()(*this, name, callable, required); - } -|*==========================================================================*/ /** * Special case: a subclass of this class can pass an unbound member @@ -142,50 +103,6 @@ private: DispatchMap mDispatch; }; -/*==========================================================================*| -/// Have to implement these template specialization methods after -/// LLEventDispatcher so they can use its methods -template -void LLEventDetail::AddCallable::operator()( - LLEventDispatcher& disp, const std::string& name, const CALLABLE& callable, const LLSD& required) -{ - disp.addImpl(name, callable, required); -} - -template -void LLEventDetail::AddCallable::operator()( - LLEventDispatcher& disp, const std::string& name, const Method& method, const LLSD& required) -{ - CLASS* downcast = dynamic_cast(&disp); - if (! downcast) - { - disp.addFail(name, typeid(CLASS).name()); - } - else - { - disp.addImpl(name, boost::bind(method, downcast, _1), required); - } -} - -/// Have to overload for both const and non-const methods -template -void LLEventDetail::AddCallable::operator()( - LLEventDispatcher& disp, const std::string& name, const Method& method, const LLSD& required) -{ - // I am severely bummed that I have, as yet, found no way short of a - // macro to avoid replicating the (admittedly brief) body of this overload. - CLASS* downcast = dynamic_cast(&disp); - if (! downcast) - { - disp.addFail(name, typeid(CLASS).name()); - } - else - { - disp.addImpl(name, boost::bind(method, downcast, _1), required); - } -} -|*==========================================================================*/ - /** * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class * that contains (or derives from) LLDispatchListener need only specify the -- cgit v1.2.3 From ca798b4fb243fbd85f71ea1b384181dd07ab6f66 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 1 Jul 2009 13:35:28 -0400 Subject: DEV-31980: provide a way to retrieve LLDispatchListener's tweaked LLEventPump name --- indra/llcommon/lleventdispatcher.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llcommon/lleventdispatcher.h') diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 4da0a01c69..ffc2f3eb00 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -114,6 +114,8 @@ class LLDispatchListener: public LLEventDispatcher public: LLDispatchListener(const std::string& pumpname, const std::string& key); + std::string getPumpName() const { return mPump.getName(); } + private: bool process(const LLSD& event); -- cgit v1.2.3 From f94d959e84cdcc552f6f5a39ee08a85c1e52d858 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Wed, 1 Jul 2009 19:02:42 -0400 Subject: Fixups for windows llcommon dll linkage errors that got dropped in the merge up to viewer-2.0.0-3 --- indra/llcommon/lleventdispatcher.h | 248 ++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 124 deletions(-) (limited to 'indra/llcommon/lleventdispatcher.h') diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 4da0a01c69..155fe0648f 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -1,124 +1,124 @@ -/** - * @file lleventdispatcher.h - * @author Nat Goodspeed - * @date 2009-06-18 - * @brief Central mechanism for dispatching events by string name. This is - * useful when you have a single LLEventPump listener on which you can - * request different operations, vs. instantiating a different - * LLEventPump for each such operation. - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * Copyright (c) 2009, Linden Research, Inc. - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLEVENTDISPATCHER_H) -#define LL_LLEVENTDISPATCHER_H - -#include -#include -#include -#include -#include -#include "llevents.h" - -class LLSD; - -/** - * Given an LLSD map, examine a string-valued key and call a corresponding - * callable. This class is designed to be contained by an LLEventPump - * listener class that will register some of its own methods, though any - * callable can be used. - */ -class LLEventDispatcher -{ -public: - LLEventDispatcher(const std::string& desc, const std::string& key); - virtual ~LLEventDispatcher(); - - /// Accept any C++ callable, typically a boost::bind() expression - typedef boost::function Callable; - - /** - * Register a @a callable by @a name. The optional @a required parameter - * is used to validate the structure of each incoming event (see - * llsd_matches()). - */ - void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); - - /** - * Special case: a subclass of this class can pass an unbound member - * function pointer without explicitly specifying the - * boost::bind() expression. - */ - template - void add(const std::string& name, void (CLASS::*method)(const LLSD&), - const LLSD& required=LLSD()) - { - addMethod(name, method, required); - } - - /// Overload for both const and non-const methods - template - void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, - const LLSD& required=LLSD()) - { - addMethod(name, method, required); - } - - /// Unregister a callable - bool remove(const std::string& name); - - /// Call a registered callable with an explicitly-specified name. If no - /// such callable exists, die with LL_ERRS. If the @a event fails to match - /// the @a required prototype specified at add() time, die with LL_ERRS. - void operator()(const std::string& name, const LLSD& event) const; - - /// Extract the @a key value from the incoming @a event, and call the - /// callable whose name is specified by that map @a key. If no such - /// callable exists, die with LL_ERRS. If the @a event fails to match the - /// @a required prototype specified at add() time, die with LL_ERRS. - void operator()(const LLSD& event) const; - -private: - template - void addMethod(const std::string& name, const METHOD& method, const LLSD& required) - { - CLASS* downcast = dynamic_cast(this); - if (! downcast) - { - addFail(name, typeid(CLASS).name()); - } - else - { - add(name, boost::bind(method, downcast, _1), required); - } - } - void addFail(const std::string& name, const std::string& classname) const; - /// try to dispatch, return @c true if success - bool attemptCall(const std::string& name, const LLSD& event) const; - - std::string mDesc, mKey; - typedef std::map > DispatchMap; - DispatchMap mDispatch; -}; - -/** - * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class - * that contains (or derives from) LLDispatchListener need only specify the - * LLEventPump name and dispatch key, and add() its methods. Incoming events - * will automatically be dispatched. - */ -class LLDispatchListener: public LLEventDispatcher -{ -public: - LLDispatchListener(const std::string& pumpname, const std::string& key); - -private: - bool process(const LLSD& event); - - LLEventStream mPump; - LLTempBoundListener mBoundListener; -}; - -#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */ +/** + * @file lleventdispatcher.h + * @author Nat Goodspeed + * @date 2009-06-18 + * @brief Central mechanism for dispatching events by string name. This is + * useful when you have a single LLEventPump listener on which you can + * request different operations, vs. instantiating a different + * LLEventPump for each such operation. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTDISPATCHER_H) +#define LL_LLEVENTDISPATCHER_H + +#include +#include +#include +#include +#include +#include "llevents.h" + +class LLSD; + +/** + * Given an LLSD map, examine a string-valued key and call a corresponding + * callable. This class is designed to be contained by an LLEventPump + * listener class that will register some of its own methods, though any + * callable can be used. + */ +class LL_COMMON_API LLEventDispatcher +{ +public: + LLEventDispatcher(const std::string& desc, const std::string& key); + virtual ~LLEventDispatcher(); + + /// Accept any C++ callable, typically a boost::bind() expression + typedef boost::function Callable; + + /** + * Register a @a callable by @a name. The optional @a required parameter + * is used to validate the structure of each incoming event (see + * llsd_matches()). + */ + void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); + + /** + * Special case: a subclass of this class can pass an unbound member + * function pointer without explicitly specifying the + * boost::bind() expression. + */ + template + void add(const std::string& name, void (CLASS::*method)(const LLSD&), + const LLSD& required=LLSD()) + { + addMethod(name, method, required); + } + + /// Overload for both const and non-const methods + template + void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, + const LLSD& required=LLSD()) + { + addMethod(name, method, required); + } + + /// Unregister a callable + bool remove(const std::string& name); + + /// Call a registered callable with an explicitly-specified name. If no + /// such callable exists, die with LL_ERRS. If the @a event fails to match + /// the @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const std::string& name, const LLSD& event) const; + + /// Extract the @a key value from the incoming @a event, and call the + /// callable whose name is specified by that map @a key. If no such + /// callable exists, die with LL_ERRS. If the @a event fails to match the + /// @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const LLSD& event) const; + +private: + template + void addMethod(const std::string& name, const METHOD& method, const LLSD& required) + { + CLASS* downcast = dynamic_cast(this); + if (! downcast) + { + addFail(name, typeid(CLASS).name()); + } + else + { + add(name, boost::bind(method, downcast, _1), required); + } + } + void addFail(const std::string& name, const std::string& classname) const; + /// try to dispatch, return @c true if success + bool attemptCall(const std::string& name, const LLSD& event) const; + + std::string mDesc, mKey; + typedef std::map > DispatchMap; + DispatchMap mDispatch; +}; + +/** + * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class + * that contains (or derives from) LLDispatchListener need only specify the + * LLEventPump name and dispatch key, and add() its methods. Incoming events + * will automatically be dispatched. + */ +class LL_COMMON_API LLDispatchListener: public LLEventDispatcher +{ +public: + LLDispatchListener(const std::string& pumpname, const std::string& key); + +private: + bool process(const LLSD& event); + + LLEventStream mPump; + LLTempBoundListener mBoundListener; +}; + +#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */ -- cgit v1.2.3