Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386240
Invoker.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
8 KB
Referenced Files
None
Subscribers
None
Invoker.hpp
View Options
//===-- 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
(
seq_t
<
sizeof
...(
Ts
)
+
1
>
(),
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
{
ASSERT
(
sizeof
...(
S
)
==
std
::
tuple_size
<
args_t
>::
value
);
// Sanity check.
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-c++
Expires
Wed, Jul 2, 12:31 AM (4 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157100
Default Alt Text
Invoker.hpp (8 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment