Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F5298579
Invoker.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
4 KB
Referenced Files
None
Subscribers
None
Invoker.hpp
View Options
/*******************************************************************************
*
* 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
<functional>
#include
<memory>
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 a smart-pointer for Invoker.
using
invoker_t
=
std
::
unique_ptr
<
const
Invoker
>
;
// 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
<
typename
T
,
typename
...
Ts
>
static
invoker_t
wrap
(
std
::
function
<
void
(
T
,
Ts
...)
noexcept
>
&&
F
)
noexcept
;
// Convenience template alias for casting callable stuff to function objects
// for wrapping.
// FIXME: Should make it possible to avoid using an explicit conversion for
// the arguments of wrap.
template
<
typename
...
Ts
>
using
F
=
std
::
function
<
void
(
Ts
...)
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
<
typename
Fun
>
class
InvokerImpl
;
// Empty struct just to store a sequence of numbers in compile time as template
// arguments.
template
<
size_t
...
>
struct
Seq
{};
// Sequence generator, the general case when counting down by extending the
// sequence.
template
<
size_t
N
,
size_t
...
S
>
struct
GenSeq
:
GenSeq
<
N
-
1
,
N
-
1
,
S
...
>
{};
// Sequence generator, the terminal case when storing the generated sequence
// into Seq.
template
<
size_t
...
S
>
struct
GenSeq
<
0
,
S
...
>
{
using
Type
=
Seq
<
S
...
>
;
};
// Specialization of InvokerImpl template for std::function.
// NOTE: No std::function<void(void) noexcept>.
template
<
typename
T
,
typename
...
Ts
>
class
InvokerImpl
<
std
::
function
<
void
(
T
,
Ts
...)
noexcept
>>
final
:
public
Invoker
{
// Type alias for the stored function.
using
function_t
=
std
::
function
<
void
(
T
,
Ts
...)
noexcept
>
;
// Type alias for correctly typed argument-tuples as obtained from Messages.
using
args_t
=
std
::
tuple
<
const
T
&
,
const
Ts
&
...
>
;
// Alias for MessageMatcher for the arguments of the stored function.
using
Matcher
=
MsgMatcher
<
T
,
Ts
...
>
;
// 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<args_t>::value
template
<
size_t
...
S
>
inline
void
invokeFunction
(
Seq
<
S
...
>
,
const
args_t
&
Args
)
const
noexcept
;
public
:
// Ctor.
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
{
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
{
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
...)
noexcept
>>::
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
...)
noexcept
>
&&
F
)
noexcept
{
return
std
::
unique_ptr
<
Invoker
>
(
new
InvokerImpl
<
std
::
function
<
void
(
T
,
Ts
...)
noexcept
>>
(
std
::
move
(
F
)));
}
}
// End namespace rosa
#endif
// ROSA_CORE_INVOKER_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Apr 12, 11:38 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
300834
Default Alt Text
Invoker.hpp (4 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment