summaryrefslogtreecommitdiff
path: root/indra/llcommon/lleventdispatcher.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lleventdispatcher.h')
-rw-r--r--indra/llcommon/lleventdispatcher.h131
1 files changed, 115 insertions, 16 deletions
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 <typename CALLABLE>
+ struct AddCallable
+ {
+ void operator()(LLEventDispatcher& disp, const std::string& name,
+ const CALLABLE& callable, const LLSD& required);
+ };
+
+ /// Unbound member function pointer
+ template <class CLASS>
+ struct AddCallable<void (CLASS::*)(const LLSD&)>
+ {
+ 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 <class CLASS>
+ struct AddCallable<void (CLASS::*)(const LLSD&) const>
+ {
+ 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<void(const LLSD&)> 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<CALLABLE>()(*this, name, callable, required);
+ }
+|*==========================================================================*/
- /// Special case: a subclass of this class can register a @a method
- /// without explicitly specifying the <tt>boost::bind()</tt> 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
+ * <tt>boost::bind()</tt> expression.
+ */
template <class CLASS>
void add(const std::string& name, void (CLASS::*method)(const LLSD&),
const LLSD& required=LLSD())
{
- CLASS* downcast = dynamic_cast<CLASS*>(this);
- if (! downcast)
- {
- addFail(name, typeid(CLASS).name());
- }
- else
- {
- add(name, boost::bind(method, downcast, _1), required);
- }
+ addMethod<CLASS>(name, method, required);
+ }
+
+ /// Overload for both const and non-const methods
+ template <class CLASS>
+ void add(const std::string& name, void (CLASS::*method)(const LLSD&) const,
+ const LLSD& required=LLSD())
+ {
+ addMethod<CLASS>(name, method, required);
}
/// Unregister a callable
@@ -78,6 +120,19 @@ public:
void operator()(const LLSD& event) const;
private:
+ template <class CLASS, typename METHOD>
+ void addMethod(const std::string& name, const METHOD& method, const LLSD& required)
+ {
+ CLASS* downcast = dynamic_cast<CLASS*>(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 <typename CALLABLE>
+void LLEventDetail::AddCallable<CALLABLE>::operator()(
+ LLEventDispatcher& disp, const std::string& name, const CALLABLE& callable, const LLSD& required)
+{
+ disp.addImpl(name, callable, required);
+}
+
+template <class CLASS>
+void LLEventDetail::AddCallable<void (CLASS::*)(const LLSD&)>::operator()(
+ LLEventDispatcher& disp, const std::string& name, const Method& method, const LLSD& required)
+{
+ CLASS* downcast = dynamic_cast<CLASS*>(&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 <class CLASS>
+void LLEventDetail::AddCallable<void (CLASS::*)(const LLSD&) const>::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<CLASS*>(&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