Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F27033332
Invoker.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Authored By
Unknown
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
(
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
{
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
Tue, Oct 27, 4:07 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
407125
Default Alt Text
Invoker.hpp (8 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline