Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386326
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
8 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/rosa/core/Invoker.hpp b/include/rosa/core/Invoker.hpp
index 9fa294f..0c6a57e 100644
--- a/include/rosa/core/Invoker.hpp
+++ b/include/rosa/core/Invoker.hpp
@@ -1,259 +1,259 @@
//===-- rosa/core/Invoker.hpp -----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/core/Invoker.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Facilities for providing actual arguments for functions as
/// \c rosa::Messageobjects.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_CORE_INVOKER_HPP
#define ROSA_CORE_INVOKER_HPP
#include "rosa/core/MessageMatcher.hpp"
#include "rosa/support/log.h"
#include "rosa/support/sequence.hpp"
#include <functional>
#include <memory>
namespace rosa {
/// Wraps a function and provides a simple interface to invoke the stored
/// function by passing actual arguments as a \c rosa::Message object.
///
/// \note A \c rosa::Invoker instance is supposed to be owned by a
/// \c rosa::MessageHandler instance, and not being used directly from user
/// code.
class Invoker {
protected:
/// Creates an instance.
///
/// \note Protected constructor restricts instantiation to derived classes.
Invoker(void) noexcept;
public:
/// Destroys \p this object.
virtual ~Invoker(void);
/// Possible results of an invocation.
enum class Result {
NoMatch, ///< The wrapped function could not be invoked
Invoked ///< The wrapped function has been invoked
};
/// Type alias for a smart-pointer for \c rosa::Invoker.
using invoker_t = std::unique_ptr<const Invoker>;
/// Type alias for \c rosa::Invoker::Result.
using result_t = Result;
/// Tells if a \c rosa::Message object can be used to invoke the function
/// wrapped in \p this object.
///
/// \param Msg \c rosa::Message to check
///
/// \return whether \p Msg can be used to invoke the wrapped function
virtual bool match(const Message &Msg) const noexcept = 0;
/// Tries to invoke the wrapped function with a \c rosa::Message object.
///
/// The wrapped function is invoked if the actual \c rosa::Message object can
/// be used to invoke it.
///
/// \param Msg \c rosa::Message to try to invoke the wrapped function with
///
/// \return whether the wrapped function could be invoked with \p Msg
virtual result_t operator()(const Message &Msg) const noexcept = 0;
/// Instantiates an implementation of \c rosa::Invoker with the given
/// function.
///
/// \note As there is no empty \c rosa::Message, no \c rosa::Invoker wraps a
/// function without any argument.
///
/// \todo Enforce F does not potentially throw exception.
///
/// \tparam T type of the first mandatory argument
/// \tparam Ts types of any further arguments
///
/// \param F function to wrap
///
/// \return new \c rosa::Invoker::invoker_t object created from the given
/// function
template <typename T, typename... Ts>
static invoker_t wrap(std::function<void(T, Ts...)> &&F) noexcept;
/// Convenience template alias for casting callable stuff to function objects
/// for wrapping.
///
/// \tparam Ts types of arguments
///
/// \todo Should make it possible to avoid using an explicit conversion for
/// the arguments of wrap.
template <typename... Ts> using F = std::function<void(Ts...)>;
/// Convenience template for preparing non-static member functions into
/// function objects for wrapping.
///
/// \tparam C type whose non-static member the function is
/// \tparam Ts types of arguments
///
/// \see \c THISMEMBER
template <typename C, typename... Ts>
static inline F<Ts...> M(C *O, void (C::*Fun)(Ts...) noexcept) noexcept;
};
/// Convenience preprocessor macro for the typical use of \c rosa::Invoker::M.
/// It can be used inside a class to turn a non-static member function into a
/// function object capturing this pointer, so using the actual object when
/// handling a \c rosa::Message.
///
/// \param FUN the non-static member function to wrap
///
/// \note Inside the class \c MyClass, use\code
/// THISMEMBER(fun)
/// \endcode instead of\code
/// Invoker::M(this, &MyClass::fun)
/// \endcode
#define THISMEMBER(FUN) \
Invoker::M(this, &std::decay<decltype(*this)>::type::FUN)
/// Nested namespace with implementation of \c rosa::Invoker and helper
/// templates, consider it private.
namespace {
/// \defgroup InvokerImpl Implementation for rosa::Invoker
///
/// Implements the \c rosa::Invoker interface for functions with different
/// signatures.
///
///@{
/// Declaration of \c rosa::InvokerImpl implementing \c rosa::Invoker.
///
/// \tparam Fun function to wrap
template <typename Fun> class InvokerImpl;
/// Implementation of \c rosa::InvokerImpl for \c std::function.
///
/// \tparam T type of the first mandatory argument
/// \tparam Ts types of further arguments
///
/// \note As there is no empty \c rosa::Message, no \c rosa::Invoker wraps a
/// function without any argument, i.e., no
/// \c std::function<void(void)>.
template <typename T, typename... Ts>
class InvokerImpl<std::function<void(T, Ts...)>> final
: public Invoker {
/// Type alias for the stored function.
using function_t = std::function<void(T, Ts...)>;
/// Type alias for correctly typed argument-tuples as obtained from
/// \c rosa::Message.
using args_t = std::tuple<const T &, const Ts &...>;
/// Alias for \c rosa::MessageMatcher for the arguments of the stored
/// function.
using Matcher = MsgMatcher<T, Ts...>;
/// The wrapped function.
const function_t F;
/// Invokes \c InvokerImpl::F by unpacking arguments from a \c std::tuple with
/// the help of the actual template arguments.
///
/// \tparam S sequence of numbers indexing \c std::tuple for arguments
///
/// \param Args arguments to invoke \c InvokerImpl::F with
///
/// \pre the length of \p S and size of \p Args are matching:\code
/// sizeof...(S) == std::tuple_size<args_t>::value
/// \endcode
template <size_t... S>
inline void invokeFunction(Seq<S...>, const args_t &Args) const noexcept;
public:
/// Creates an instance.
///
/// \param F function to wrap
///
/// \pre \p F is valid:\code
/// bool(F)
/// \endcode
InvokerImpl(function_t &&F) noexcept : F(F) {
ASSERT(bool(F)); // Sanity check.
}
/// Destroys \p this object.
~InvokerImpl(void) = default;
/// Tells if a \c rosa::Message object can be used to invoke the function
/// wrapped in \p this object.
///
/// \param Msg \c rosa::Message to check
///
/// \return whether \p Msg can be used to invoke the wrapped function
bool match(const Message &Msg) const noexcept override {
return Matcher::doesStronglyMatch(Msg);
- };
+ }
/// Tries to invoke the wrapped function with a \c rosa::Message object.
///
/// The wrapped function is invoked if the actual \c rosa::Message object can
/// be used to invoke it.
///
/// \param Msg \c rosa::Message to try to invoke the wrapped function with
///
/// \return whether the wrapped function could be invoked with \p Msg
result_t operator()(const Message &Msg) const noexcept override {
if (match(Msg)) {
LOG_TRACE("Invoking with matching arguments");
invokeFunction(typename GenSeq<sizeof...(Ts) + 1>::Type(),
Matcher::extractedValues(Msg));
return result_t::Invoked;
} else {
LOG_TRACE("Tried to invoke with non-matching arguments");
return result_t::NoMatch;
}
}
};
template <typename T, typename... Ts>
template <size_t... S>
void InvokerImpl<std::function<void(T, Ts...)>>::invokeFunction(
Seq<S...>, const args_t &Args) const noexcept {
STATIC_ASSERT(sizeof...(S) == std::tuple_size<args_t>::value,
"wrong number of type parameters");
F(std::get<S>(Args)...);
}
///@}
} // End namespace
template <typename T, typename... Ts>
Invoker::invoker_t
Invoker::wrap(std::function<void(T, Ts...)> &&F) noexcept {
return std::unique_ptr<Invoker>(
new InvokerImpl<std::function<void(T, Ts...)>>(std::move(F)));
}
template <typename C, typename... Ts>
Invoker::F<Ts...> Invoker::M(C *O, void (C::*Fun)(Ts...) noexcept) noexcept {
return [ O, Fun ](Ts... Vs) noexcept->void { (O->*Fun)(Vs...); };
}
} // End namespace rosa
#endif // ROSA_CORE_INVOKER_HPP
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 1:43 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157173
Default Alt Text
(8 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment