diff options
Diffstat (limited to 'indra/llcommon/lleventdispatcher.h')
-rw-r--r-- | indra/llcommon/lleventdispatcher.h | 155 |
1 files changed, 86 insertions, 69 deletions
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 9e1244ef5b..6d1df86fea 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -61,7 +61,6 @@ static const auto& nil(nil_); #include <boost/function.hpp> #include <boost/bind.hpp> #include <boost/iterator/transform_iterator.hpp> -#include <boost/utility/enable_if.hpp> #include <boost/function_types/is_nonmember_callable_builtin.hpp> #include <boost/function_types/parameter_types.hpp> #include <boost/function_types/function_arity.hpp> @@ -166,11 +165,12 @@ public: * When calling this name, pass an LLSD::Array. Each entry in turn will be * converted to the corresponding parameter type using LLSDParam. */ - template<typename Function> - typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> - >::type add(const std::string& name, - const std::string& desc, - Function f); + // enable_if usage per https://stackoverflow.com/a/39913395/5533635 + template<typename Function, + typename = typename std::enable_if< + boost::function_types::is_nonmember_callable_builtin<Function>::value + >::type> + void add(const std::string& name, const std::string& desc, Function f); /** * Register a nonstatic class method with arbitrary parameters. @@ -189,12 +189,13 @@ public: * When calling this name, pass an LLSD::Array. Each entry in turn will be * converted to the corresponding parameter type using LLSDParam. */ - template<typename Method, typename InstanceGetter> - typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> - >::type add(const std::string& name, - const std::string& desc, - Method f, - const InstanceGetter& getter); + template<typename Method, typename InstanceGetter, + typename = typename std::enable_if< + boost::function_types::is_member_function_pointer<Method>::value && + ! std::is_convertible<InstanceGetter, LLSD>::value + >::type> + void add(const std::string& name, const std::string& desc, Method f, + const InstanceGetter& getter); /** * Register a free function with arbitrary parameters. (This also works @@ -211,13 +212,12 @@ public: * an LLSD::Array using LLSDArgsMapper and then convert each entry in turn * to the corresponding parameter type using LLSDParam. */ - template<typename Function> - typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> - >::type add(const std::string& name, - const std::string& desc, - Function f, - const LLSD& params, - const LLSD& defaults=LLSD()); + template<typename Function, + typename = typename std::enable_if< + boost::function_types::is_nonmember_callable_builtin<Function>::value + >::type> + void add(const std::string& name, const std::string& desc, Function f, + const LLSD& params, const LLSD& defaults=LLSD()); /** * Register a nonstatic class method with arbitrary parameters. @@ -240,42 +240,42 @@ public: * an LLSD::Array using LLSDArgsMapper and then convert each entry in turn * to the corresponding parameter type using LLSDParam. */ - template<typename Method, typename InstanceGetter> - typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> - >::type add(const std::string& name, - const std::string& desc, - Method f, - const InstanceGetter& getter, - const LLSD& params, - const LLSD& defaults=LLSD()); + template<typename Method, typename InstanceGetter, + typename = typename std::enable_if< + boost::function_types::is_member_function_pointer<Method>::value && + ! std::is_convertible<InstanceGetter, LLSD>::value + >::type> + void add(const std::string& name, const std::string& desc, Method f, + const InstanceGetter& getter, const LLSD& params, + const LLSD& defaults=LLSD()); //@} /// 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. + /// Call a registered callable with an explicitly-specified name. It is an + /// error if no such callable exists. It is an error if the @a event fails + /// to match the @a required prototype specified at add() time. void operator()(const std::string& name, const LLSD& event) const; /// Call a registered callable with an explicitly-specified name and /// return <tt>true</tt>. If no such callable exists, return - /// <tt>false</tt>. If the @a event fails to match the @a required - /// prototype specified at add() time, die with LL_ERRS. + /// <tt>false</tt>. It is an error if the @a event fails to match the @a + /// required prototype specified at add() time. bool try_call(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. + /// callable whose name is specified by that map @a key. It is an error if + /// no such callable exists. It is an error if the @a event fails to match + /// the @a required prototype specified at add() time. void operator()(const LLSD& event) const; /// Extract the @a key value from the incoming @a event, call the callable /// whose name is specified by that map @a key and return <tt>true</tt>. - /// If no such callable exists, return <tt>false</tt>. If the @a event - /// fails to match the @a required prototype specified at add() time, die - /// with LL_ERRS. + /// If no such callable exists, return <tt>false</tt>. It is an error if + /// the @a event fails to match the @a required prototype specified at + /// add() time. bool try_call(const LLSD& event) const; /// @name Iterate over defined names @@ -329,17 +329,16 @@ private: void addMethod(const std::string& name, const std::string& desc, const METHOD& method, const LLSD& required) { - CLASS* downcast = dynamic_cast<CLASS*>(this); - if (! downcast) - { - addFail(name, typeid(CLASS).name()); - } - else - { - add(name, desc, boost::bind(method, downcast, _1), required); - } + CLASS* downcast = static_cast<CLASS*>(this); + add(name, desc, boost::bind(method, downcast, _1), required); } - void addFail(const std::string& name, const std::string& classname) const; + std::string try_call_log(const std::string& key, const std::string& name, + const LLSD& event) const; + std::string try_call(const std::string& key, const std::string& name, + const LLSD& event) const; + // Implement "it is an error" semantics for attempted call operations: if + // the incoming event includes a "reply" key, log and send an error reply. + void callFail(const LLSD& event, const std::string& msg) const; std::string mDesc, mKey; DispatchMap mDispatch; @@ -427,7 +426,25 @@ struct LLEventDispatcher::invoker // Instead of grabbing the first item from argsrc and making an // LLSDParam of it, call getter() and pass that as the instance param. invoker<Function, next_iter_type, To>::apply - ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), boost::ref(getter()))); + ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), bindable(getter()))); + } + + template <typename T> + static inline + auto bindable(T&& value, + typename std::enable_if<std::is_pointer<T>::value, bool>::type=true) + { + // if passed a pointer, just return that pointer + return std::forward<T>(value); + } + + template <typename T> + static inline + auto bindable(T&& value, + typename std::enable_if<! std::is_pointer<T>::value, bool>::type=true) + { + // if passed a reference, wrap it for binding + return std::ref(std::forward<T>(value)); } }; @@ -446,9 +463,8 @@ struct LLEventDispatcher::invoker<Function,To,To> } }; -template<typename Function> -typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type -LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f) +template<typename Function, typename> +void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f) { // Construct an invoker_function, a callable accepting const args_source&. // Add to DispatchMap an ArrayParamsDispatchEntry that will handle the @@ -457,10 +473,9 @@ LLEventDispatcher::add(const std::string& name, const std::string& desc, Functio boost::function_types::function_arity<Function>::value); } -template<typename Method, typename InstanceGetter> -typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type -LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, - const InstanceGetter& getter) +template<typename Method, typename InstanceGetter, typename> +void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, + const InstanceGetter& getter) { // Subtract 1 from the compile-time arity because the getter takes care of // the first parameter. We only need (arity - 1) additional arguments. @@ -468,20 +483,18 @@ LLEventDispatcher::add(const std::string& name, const std::string& desc, Method boost::function_types::function_arity<Method>::value - 1); } -template<typename Function> -typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type -LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f, - const LLSD& params, const LLSD& defaults) +template<typename Function, typename> +void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f, + const LLSD& params, const LLSD& defaults) { // See comments for previous is_nonmember_callable_builtin add(). addMapParamsDispatchEntry(name, desc, make_invoker(f), params, defaults); } -template<typename Method, typename InstanceGetter> -typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type -LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, - const InstanceGetter& getter, - const LLSD& params, const LLSD& defaults) +template<typename Method, typename InstanceGetter, typename> +void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, + const InstanceGetter& getter, + const LLSD& params, const LLSD& defaults) { addMapParamsDispatchEntry(name, desc, make_invoker(f, getter), params, defaults); } @@ -524,17 +537,21 @@ LLEventDispatcher::make_invoker(Method f, const InstanceGetter& getter) * LLEventPump name and dispatch key, and add() its methods. Incoming events * will automatically be dispatched. */ -class LL_COMMON_API LLDispatchListener: public LLEventDispatcher +// Instead of containing an LLEventStream, LLDispatchListener derives from it. +// This allows an LLEventPumps::PumpFactory to return a pointer to an +// LLDispatchListener (subclass) instance, and still have ~LLEventPumps() +// properly clean it up. +class LL_COMMON_API LLDispatchListener: + public LLEventDispatcher, + public LLEventStream { public: LLDispatchListener(const std::string& pumpname, const std::string& key); - - std::string getPumpName() const { return mPump.getName(); } + virtual ~LLDispatchListener() {} private: bool process(const LLSD& event); - LLEventStream mPump; LLTempBoundListener mBoundListener; }; |