diff --git a/include/rosa/core/Invoker.hpp b/include/rosa/core/Invoker.hpp index b909915..136e998 100644 --- a/include/rosa/core/Invoker.hpp +++ b/include/rosa/core/Invoker.hpp @@ -1,162 +1,150 @@ /******************************************************************************* * * File: Invoker.hpp * * Contents: Definition of Invoker interface and its implementation. * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * ******************************************************************************/ #ifndef ROSA_CORE_INVOKER_HPP #define ROSA_CORE_INVOKER_HPP #include "rosa/core/MessageMatcher.hpp" #include "rosa/support/log.h" #include #include namespace rosa { // Wraps a function and provides a simple interface to invoke the stored // function by passing actual arguments as a Message. // NOTE: Invoker instances are supposed to be owned by Message handlers, and // not being used directly from user code. class Invoker { protected: // Protected ctor, only subclasses can instantiate. Invoker(void) noexcept; public: // Dtor. virtual ~Invoker(void); // Enumeration of possible results of an invocation. enum class Result { NoMatch, Invoked }; // Type alias for Result. using result_t = Result; // Tells if Msg can be used to invoke F. virtual bool match(const Message &Msg) const noexcept = 0; // Invokes F with Msg if Msg can be used to invoke F. virtual result_t operator()(const Message &Msg) const noexcept = 0; // Instantiates an implementation of Invoker with the given function. // NOTE: As there is no empty Message, no Invoker wraps a function without an // argument. template static std::unique_ptr wrap(std::function &&F) noexcept; }; // Nested namespace with Invoker implementation and helper templates, consider // it private. namespace { // Implementation of the Invoker interface, for functions with different // signature. // NOTE: As there is no empty Message, no Invoker wraps a function without an // argument. template class InvokerImpl; // Empty struct just to store a sequence of numbers in compile time as template // arguments. template struct Seq {}; // Sequence generator, the general case when counting down by extending the // sequence. template struct GenSeq : GenSeq {}; // Sequence generator, the terminal case when storing the generated sequence // into Seq. template struct GenSeq<0, S...> { using Type = Seq; }; // Specialization of InvokerImpl template for std::function. // NOTE: No std::function. template class InvokerImpl> final : public Invoker { // Type alias for the stored function. using function_t = std::function; // Type alias for correctly typed argument-tuples as obtained from Messages. using args_t = std::tuple; // Alias for MessageMatcher for the arguments of the stored function. using Matcher = MsgMatcher; // The wrapped function. const function_t F; // Helper function invoking F by unpacking Args with the help of actual // template arguments. // PRE: sizeof...(S) == std::tuple_size::value template inline void invokeFunction(Seq, const args_t &Args) const noexcept; public: // Ctor. - InvokerImpl(function_t &&F) noexcept; + InvokerImpl(function_t &&F) noexcept : F(F) { + ASSERT(bool(F)); // Sanity check. + } // Dtor. ~InvokerImpl(void) = default; // Tells if Msg can be used to invoke F. - bool match(const Message &Msg) const noexcept override; + bool match(const Message &Msg) const noexcept override { + return Matcher::doesStronglyMatch(Msg); + }; // Invokes F with Msg if Msg can be used to invoke F. - result_t operator()(const Message &Msg) const noexcept override; + result_t operator()(const Message &Msg) const noexcept override { + if (match(Msg)) { + LOG_TRACE("Invoking with matching arguments"); + invokeFunction(typename GenSeq::Type(), + Matcher::extractedValues(Msg)); + return result_t::Invoked; + } else { + LOG_TRACE("Tried to invoke with non-matching arguments"); + return result_t::NoMatch; + } + } }; -template -InvokerImpl>::InvokerImpl( - function_t &&F) noexcept : F(F) { - ASSERT(bool(F)); // Sanity check. -} - template template void InvokerImpl>::invokeFunction( Seq, const args_t &Args) const noexcept { ASSERT(sizeof...(S) == std::tuple_size::value); // Sanity check. F(std::get(Args)...); } -template -bool InvokerImpl>::match( - const Message &Msg) const noexcept { - return Matcher::doesStronglyMatch(Msg); -}; - -template -typename Invoker::result_t InvokerImpl>:: -operator()(const Message &Msg) const noexcept { - if (match(Msg)) { - LOG_TRACE("Invoking with matching arguments"); - invokeFunction(typename GenSeq::Type(), - Matcher::extractedValues(Msg)); - return result_t::Invoked; - } else { - LOG_TRACE("Tried to invoke with non-matching arguments"); - return result_t::NoMatch; - } -} - } // End namespace template std::unique_ptr Invoker::wrap(std::function &&F) noexcept { return std::unique_ptr( new InvokerImpl>(std::move(F))); } } // End namespace rosa #endif // ROSA_CORE_INVOKER_HPP