Page MenuHomePhorge

MessageHandler.hpp
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

MessageHandler.hpp

//===-- rosa/core/MessageHandler.hpp ----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/core/MessageHandler.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Facility for combining \c rosa::Invoker instances and applying
/// \c rosa::Message intances to them.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_CORE_MESSAGEHANDLER_HPP
#define ROSA_CORE_MESSAGEHANDLER_HPP
#include "rosa/core/Invoker.hpp"
#include "rosa/support/log.h"
#include <vector>
namespace rosa {
/// Handles \c rosa::Message instances.
///
/// A \c rosa::MessageHandler stores \c rosa::Invoker instances and tries to
/// apply \c rosa::Message objects to them in the order of definition.The first
/// matching \c rosa::Invoker instance is invoked with the \c rosa::Message
/// object, after which handling of that \c rosa::Message object is completed.
///
/// For example, consider the following snippet: \code
/// rosa::MessageHandler {
/// rosa::Invoker::F<uint8_t>([](uint8_t) { /* ... */ }),
/// rosa::Invoker::F<uint8_t>([](uint8_t) { /* Never invoked */ })
/// };
/// \endcode
/// Applying a \c rosa::Message with \c rosa::TypeList<uint8_t> invokes the
/// first function, and the second function would never be invoked because any
/// matching \c rosa::Message object had already been handled by the first one.
class MessageHandler {
/// Type alias to bring \c rosa::Invoker::invoker_t to the local scope.
using invoker_t = Invoker::invoker_t;
/// Type alias for a \c std::vector storing \c rosa::Invoker instances.
using invokers_t = std::vector<invoker_t>;
/// Stores \c rosa::Invoker instances.
const invokers_t Invokers;
/// Creates a container with \c rosa::Invoker instances from functions.
///
/// \tparam Fun type of the mandatory first function
/// \tparam Funs types of further functions
///
/// \param F the mandatory first function
/// \param Fs optional further functions
///
/// \return \c rosa::MessageHandler::invokers_t object storing
/// \c rosa::Invoker instances created from the \p F and \p Fs...
template <typename Fun, typename... Funs>
static inline invokers_t createInvokers(Fun &&F, Funs &&... Fs) noexcept;
/// Updates an \c rosa::MessageHandler::invokers_t object with a new
/// \c rosa::Invoker instance and handles further functions recursively.
///
/// \tparam Fun type of the first function
/// \tparam Funs types of further functions
///
/// \param I \c rosa::MessageHandler::invokers_t to update
/// \param Pos index at which to store the new \c rosa::Invoker instance
/// \param F function to wrap and store into \p I at index \p Pos
/// \param Fs further functions to handle later
///
/// \pre \p Pos is a valid index:\code
/// Pos < I.size()
/// \endcode
template <typename Fun, typename... Funs>
static inline void wrapFun(invokers_t &I, const size_t Pos, Fun &&F,
Funs &&... Fs) noexcept;
/// Terminal case for the template \c rosa::MessageHandler::wrapFun.
///
/// \param I \c rosa::MessageHandler::invokers_t which is now complete
/// \param Pos size of \p I
///
/// \pre \p Pos is the size of \p I:\code
/// Pos == I.size();
/// \endcode
static inline void wrapFun(invokers_t &I, const size_t Pos) noexcept;
public:
/// Creates an instance.
///
/// The constructor stores the given functions into the new
/// \c rosa::MessageHandler instance.
///
/// \tparam Fun type of the mandatory first function
/// \tparam Funs types of further functions
///
/// \param F the first function to store
/// \param Fs optional further functions to store
template <typename Fun, typename... Funs>
MessageHandler(Fun &&F, Funs &&... Fs) noexcept;
/// Destroys \p this object.
virtual ~MessageHandler(void);
/// Tells if a \c rosa::Message object can be handled by \p this object.
///
/// \param Msg \c rosa::Message to check
///
/// \return whether \p this object stores a \c rosa::Invoker instance that can
/// handle \p Msg
bool canHandle(const Message &Msg) const noexcept;
/// Applies a \c rosa::Message object to the first stored \c rosa::Invoker
/// that can handle it, and tells if there was any.
///
/// \note This operator finds the first applicable \c rosa::Invoker and
/// invokes it with the given \c rosa::Message object, while the member
/// function \c rosa::MessageHandler::canHandle only checks if there is any
/// \c rosa::Invoker that can be invoked with a given \c rosa::Message object.
///
/// \param Msg \c rosa::Message to use in invoking a matching \c rosa::Invoker
///
/// \return whether there was a matching \c rosa::Invoker found and invoked
/// with \p Msg
bool operator()(const Message &Msg) const noexcept;
};
template <typename Fun, typename... Funs>
MessageHandler::MessageHandler(Fun &&F, Funs &&... Fs) noexcept
: Invokers(createInvokers(std::move(F), std::move(Fs)...)) {
LOG_TRACE("MessageHandler is created");
}
template <typename Fun, typename... Funs>
MessageHandler::invokers_t
MessageHandler::createInvokers(Fun &&F, Funs &&... Fs) noexcept {
// Create a container with the required size and get all the functions
// wrapped.
invokers_t I(1 + sizeof...(Funs));
wrapFun(I, 0, std::move(F), std::move(Fs)...);
return I;
}
template <typename Fun, typename... Funs>
void MessageHandler::wrapFun(invokers_t &I, const size_t Pos, Fun &&F,
Funs &&... Fs) noexcept {
ASSERT(Pos < I.size()); // Sanity check.
// Wrap the current function and continue with the rest.
I[Pos] = Invoker::wrap(std::move(F));
wrapFun(I, Pos + 1, std::move(Fs)...);
}
void MessageHandler::wrapFun(invokers_t &I, const size_t Pos) noexcept {
ASSERT(Pos == I.size()); // Sanity check.
// Nothing to do here.
}
} // End namespace rosa
#endif // ROSA_CORE_MESSAGEHANDLER_HPP

File Metadata

Mime Type
text/x-c++
Expires
Sun, Mar 1, 6:52 PM (18 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
280877
Default Alt Text
MessageHandler.hpp (5 KB)

Event Timeline