Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1494414
AppSensor.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
25 KB
Referenced Files
None
Subscribers
None
AppSensor.hpp
View Options
//===-- rosa/app/AppSensor.hpp ----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/app/AppSensor.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2020
///
/// \brief Specialization of \c rosa::Agent for *sensor* role of the the
/// *application interface*.
///
/// \see \c rosa::app::Application
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_APP_APPSENSOR_HPP
#define ROSA_APP_APPSENSOR_HPP
#include
"rosa/core/Agent.hpp"
#include
"rosa/app/AppAtoms.hpp"
#include
"rosa/app/AppExecutionPolicy.h"
#include
"rosa/app/AppTuple.hpp"
#include
"rosa/support/diagnostics.h"
/// Local helper macros to deal with built-in types.
///
///@{
/// Creates function name for member functions in \c rosa::app::AppSensor.
///
/// \param N name suffix to use
#define ASMASTERHANDLERNAME(N) handleMaster_##N
/// Defines member functions for handling messages from *master* in
/// \c rosa::app::AppSensor.
///
/// \see \c AppSensorMasterInputHandlers
///
/// \note No pre- and post-conditions are validated directly by these functions,
/// they rather rely on \c rosa::app::AppSensor::saveMasterInput to do
/// that.
///
/// \param T the type of input to handle
/// \param N name suffix for the function identifier
#define ASMASTERHANDLERDEFN(T, N) \
void ASMASTERHANDLERNAME(N)(atoms::Master, id_t MasterId, token_size_t Pos, \
T Value) noexcept { \
saveMasterInput(MasterId, Pos, Value); \
}
/// Convenience macro for \c ASMASTERHANDLERDEFN with identical arguments.
///
/// \see \c ASMASTERHANDLERDEFN
///
/// This macro can be used instead of \c ASMASTERHANDLERDEFN if the actual value
/// of \p T can be used as a part of a valid identifier.
///
/// \param T the type of input to handle
#define ASMASTERHANDLERDEF(T) ASMASTERHANDLERDEFN(T, T)
/// Results in a \c THISMEMBER reference to a member function defined by
/// \c ASMASTERHANDLERDEFN.
///
/// Used in the constructor of \c rosa::app::AppSensor to initialize super
/// class \c rosa::Agent with member function defined by \c ASMASTERHANDLERDEFN.
///
/// \see \c ASMASTERHANDLERDEFN, \c THISMEMBER
///
/// \param N name suffix for the function identifier
#define ASMASTERHANDLERREF(N) THISMEMBER(ASMASTERHANDLERNAME(N))
///@}
namespace
rosa
{
namespace
app
{
/// Specialization of \c rosa::Agent for *sensor* role of the *application
/// interface*.
///
/// \see \c rosa::app::Application
///
/// \invariant There is a compatible *execution policy* set; the actual value in
/// \c rosa::app::AppSensor::MasterInputNextPos is valid with respect to
/// the corresponding types.
///
/// \see Definition of \c rosa::app::AppSensor::inv on the class invariant
///
/// \note All member functions validate the class invariant as part of their
/// precondition. Moreover, non-const functions validate the invariant before
/// return as their postcondition.
class
AppSensor
:
public
Agent
{
/// Checks whether \p this object holds the class invariant.
///
/// \see Invariant of the class \c rosa::app::AppSensor
///
/// \return if \p this object holds the class invariant
bool
inv
(
void
)
const
noexcept
;
/// The \c rosa::app::AppExecutionPolicy that controls the execution of
/// \c this object.
std
::
unique_ptr
<
AppExecutionPolicy
>
ExecutionPolicy
;
public
:
/// The type of values produced by \p this object.
///
/// That is the types of values \p this object sends to its *master* in a
/// \c rosa::app::AppTuple.
///
/// \see \c rosa::app::AppSensor::master
const
Token
OutputType
;
/// The type of values \p this object processes from its *master*.
///
/// That is the types of values \p this object receives from its *master* in a
/// \c rosa::app::AppTuple.
///
/// \see \c rosa::app::AppSensor::master
const
Token
MasterInputType
;
private
:
/// Indicates which element of the master-input is expected from the *master*.
///
/// The *master* is supposed to send one \c rosa::app::AppTuple value
/// element by element in their order of definition. This member field tells
/// the element at which position should be received next.
///
/// \p this object is supposed to be triggered only when a complete
/// master-input has been received, that is the field should hold the value
/// `0`.
///
/// \see \c rosa::app::AppSensor::handleTrigger
/// \c rosa::app::AppSensor::saveMasterInput
token_size_t
MasterInputNextPos
;
/// Indicates whether the input value from the *master* has been changed since
/// the last trigger received from the system.
///
/// The flag is reset to \c false upon handling a trigger and then set to \c
/// true by \c rosa::app::AppSensor::saveMasterInput when storig a new
/// input value in \c rosa::app::AppSensor::MasterInputValue.
bool
MasterInputChanged
;
/// Stores the actual input value from *master*.
///
/// \note The type of the stored value matches the types indicated by \c
/// rosa::app::AppSensor::MasterInputType.
const
std
::
unique_ptr
<
AbstractTokenizedStorage
>
MasterInputValue
;
/// Alias for function objects used as trigger handler for
/// \c rosa::app::AppSensor.
///
/// \note The function used for \c H is to be \c noexcept.
///
/// \see \c AppSensorTriggerHandlers
using
H
=
std
::
function
<
void
(
void
)
>
;
/// \defgroup AppSensorTriggerHandlers Trigger handlers of
/// rosa::app::AppSensor
///
/// \brief Trigger handler functions of \c rosa::app::AppSensor
///
/// The actual data source functions and master-input processing function are
/// captured in lambda expressions that are in turn wrapped in \c
/// std::function objects. The lambda expression calls a processing function,
/// either to handle master-input or obtain the next sensory value from data
/// source. The next sensory value is sent it to *master* by calling \c
/// rosa::app::AppSensor::sendToMaster. Also, the flag \c
/// rosa::app::AppSensor::MasterInputChanged is reset when the current
/// value is passed to the master-input processing function. The function \c
/// rosa::app::AppSensor::handleTrigger needs only to call the proper
/// function object.
/// Processes master-input.
///
/// \ingroup AppSensorTriggerHandlers
///
/// The function is called upon the sensor is trigged by the system.
const
H
MFP
;
/// Produces the next sensory value during normal execution.
///
/// \ingroup AppSensorTriggerHandlers
///
/// The function is used during normal execution. During simulation, the
/// simulation environment sets \c rosa::app::AppSensor::SFP, which is
/// used instead of \c rosa::app::AppSensor::FP.
const
H
FP
;
/// Produces the next sensory value during simulation.
///
/// \ingroup AppSensorTriggerHandlers
///
/// The function is empty by default. The simulation environment sets it to be
/// used during simulation.
H
SFP
;
/// The *master* to send values to.
///
/// \note *Masters* are set dynamically, hence it is possible that a
/// \c rosa::app::AppSensor instance does not have any *master* at a
/// given moment.
Optional
<
AgentHandle
>
Master
;
/// Tells the unique identifier of the *master* of \p this object, if any
/// registered.
///
/// \return the unique identifier of the *master*
///
/// \pre A *master* is registered for \p this object: \code
/// Master
/// \endcode
id_t
masterId
(
void
)
const
noexcept
;
/// Wraps a master-input processing function into a trigger handler.
///
/// \see \c rosa::app::AppSensor::MFP and \c AppSensorTriggerHandlers
///
/// \tparam Ts types of elements of master-input processed by \p MF
/// \tparam S0 indices for accessing master-input values
///
/// \param MF function that processes master-input
///
/// \note The second argument provides indices statically as template
/// arguments \p S0..., so its actual value is ignored.
///
/// \note A master-input type of \c rosa::app::EmptyAppTuple indicates
/// that \p this object does not receive master-input, \p MF is never called
/// if \p Ts is empty.
///
/// \return trigger handler function based on \p MF
///
/// \pre Statically, the indices match the elements: \code
/// sizeof...(Ts) == sizeof...(S0)
/// \endcode Dynamically, \p Ts... match \c
/// rosa::app::AppSensor::MasterInputType: \code
/// MasterInputType == AppTuple<Ts...>::TT
/// \endcode
template
<
typename
...
Ts
,
size_t
...
S0
>
H
triggerHandlerFromProcessingFunction
(
std
::
function
<
void
(
std
::
pair
<
AppTuple
<
Ts
...
>
,
bool
>
)
>
&&
MF
,
Seq
<
S0
...
>
)
noexcept
;
/// Wraps a data source function into a trigger handler.
///
/// \see \c rosa::app::AppSensor::FP, \c
/// rosa::app::AppSensor::SFP, and \c AppSensorTriggerHandlers
///
/// \tparam T type of data provided by \p F
///
/// \param F function to generate value with
/// \param inSimulation if F is a data source for Simulation
///
/// \return trigger handler function based on \p F
///
/// \pre Statically, the type agument \p T is an instance of \c
/// rosa::app::AppTuple: \code
/// IsAppTuple<T>::Value
/// \endcode Dynamically, \p T matches \c
/// rosa::app::AppSensor::OutputType: \code
/// OutputType == T::TT
/// \endcode
template
<
typename
T
>
H
triggerHandlerFromDataSource
(
std
::
function
<
T
(
void
)
>
&&
F
,
bool
inSimulation
)
noexcept
;
public
:
/// Creates a new instance.
///
/// The constructor instantiates the base-class with functions to handle
/// messages as defined for the *application interface*.
///
/// \todo Enforce \p F and \p MF do not potentially throw exception.
///
/// \tparam MT type of master-input handled by \p MF
/// \tparam T type of data to operate on
///
/// \note Instantiation fails if any of the type arguments \p MT and \p T is
/// not an instance of \c rosa::app::AppTuple or \p T is \c
/// rosa::app::EmptyAppTuple.
///
/// \note If \p MT is \c rosa::app::EmptyAppTuple, the constructed
/// object does not receive master-input.
///
/// \param Kind kind of the new \c rosa::Unit instance
/// \param Id unique identifier of the new \c rosa::Unit instance
/// \param Name name of the new \c rosa::Unit instance
/// \param S \c rosa::MessagingSystem owning the new instance
/// \param MF function to process master-input values with
/// \param F function to generate the next value with during normal operation
///
/// \pre Statically, \p MT and \p T are instances of \c
/// rosa::app::AppTuple and \p T contains at least one element:\code
/// TypeListAllAppTuple<TypeList<MT, T>>::Value && T::Length > 0
/// \endcode
/// Dynamically, the instance is created as of kind
/// \c rosa::app::atoms::SensorKind:
/// \code
/// Kind == rosa::app::atoms::SensorKind
/// \endcode
///
/// \see \c rosa::app::AppTuple
template
<
typename
MT
,
typename
T
,
typename
=
std
::
enable_if_t
<
TypeListAllAppTuple
<
TypeList
<
MT
,
T
>>::
Value
&&
(
T
::
Length
>
0
)
>>
AppSensor
(
const
AtomValue
Kind
,
const
id_t
Id
,
const
std
::
string
&
Name
,
MessagingSystem
&
S
,
std
::
function
<
void
(
std
::
pair
<
MT
,
bool
>
)
>
&&
MF
,
std
::
function
<
T
(
void
)
>
&&
F
)
noexcept
;
/// Destroys \p this object.
~
AppSensor
(
void
)
noexcept
;
/// Returns the current execution policy of \p this object.
///
/// \see \c rosa::app::AppExecutionPolicy
///
/// \note The returned reference is valid only as long as \c
/// rosa::app::AppSensor::setExecutionPolicy() is not called and \p this
/// object is not destroyed.
///
/// \return \c rosa::app::AppSensor::ExecutionPolicy
const
AppExecutionPolicy
&
executionPolicy
(
void
)
const
noexcept
;
/// Sets the current execution policy of \p this object to \p EP.
///
/// \see \c rosa::app::AppExecutionPolicy
///
/// \note \p EP is set only if it can handle \p this object.
///
/// \param EP the new execution policy for \p this object
///
/// \return if \p EP was successfully set for \p this object.
bool
setExecutionPolicy
(
std
::
unique_ptr
<
AppExecutionPolicy
>
&&
EP
)
noexcept
;
/// The *master* of \p this object, if any.
///
/// \see \c rosa::app::AppSensor::registerMaster
///
/// \return the *master* registered for \p this object
Optional
<
AgentHandle
>
master
(
void
)
const
noexcept
;
/// Registers a *master* for \p this object.
///
/// The new *master* is registered by overwriting the reference to any
/// already registered *master*. One can clear the registered reference by
/// passing an *empty* \c rosa::Optional object as actual argument.
///
/// \note The role of the referred *master* is validated by checking its
/// *kind*.
///
/// \note Any call to \c rosa::app::AppSensor::registerMaster should be
/// paired with a corresponding call of \c
/// rosa::app::AppAgent::registerSlave, which validates that
/// input/output types of master and slave matches.
///
/// \param _Master the *master* to register
///
/// \pre \p Master is empty or of kind \c rosa::app::atoms::AgentKind:
/// \code
/// !_Master || unwrapAgent(*_Master).Kind == rosa::app::atoms::AgentKind
/// \endcode
void
registerMaster
(
const
Optional
<
AgentHandle
>
_Master
)
noexcept
;
/// Clears the simulation trigger handler of \p this object.
///
/// The function assigns \c rosa::app::AppSensor::SFP with \c nullptr.
void
clearSimulationDataSource
(
void
)
noexcept
;
/// Tells whether a simulation trigger handler is set for \p this object.
///
/// The function returns whether \c rosa::app::AppSensor::SFP is not
/// \c nullptr.
///
/// \return if a simulation trigger handler is set for \p this object.
bool
simulationDataSourceIsSet
(
void
)
const
noexcept
;
/// Registers a simulation data source for \p this object.
///
/// A new simulation trigger handler wrapping \p SF is stored in
/// \c rosa::app::AppSensor::SFP by overwriting any already registered
/// simulation data source.
///
/// \todo Enforce SF does not potentially throw exception.
///
/// \tparam Ts types of elements of values provided by \p SF
///
/// \param SF function to generate value with
///
/// \pre \p Ts... match \c rosa::app::AppSensor::OutputType: \code
/// OutputType == TypeToken<Ts...>::Value
/// \endcode
template
<
typename
...
Ts
>
void
registerSimulationDataSource
(
std
::
function
<
AppTuple
<
Ts
...
>
(
void
)
>
&&
SF
)
noexcept
;
private
:
/// Sends a value to the *master* of \p this object.
///
/// \p Value is getting sent to \c rosa::app::AppSensor::Master if it
/// contains a valid handle for a \c rosa::app::AppAgent. The function
/// does nothing otherwise.
///
/// The elements from \p Value are sent one by one in separate messages to the
/// *master*.
///
/// \tparam Ts types of the elements in \p Value
/// \tparam S0 indices for accessing elements of \p Value
///
/// \param Value value to send
///
/// \note The second argument provides indices statically as template
/// arguments \p S0..., so its actual value is ignored.
///
/// \pre Statically, the indices match the elements: \code
/// sizeof...(Ts) == sizeof...(S0)
/// \endcode Dynamically, \p Ts match \c
/// rosa::app::AppSensor::OutputType: \code
/// OutputType == TypeToken<Ts...>::Value
/// \endcode
template
<
typename
...
Ts
,
size_t
...
S0
>
void
sendToMaster
(
const
AppTuple
<
Ts
...
>
&
Value
,
Seq
<
S0
...
>
)
noexcept
;
/// Handles master-input and generates the next sensory value upon trigger
/// from the system.
///
/// Executes \c rosa::app::AppSensor::MFP for processing master-input
/// and data generating function \c rosa::app::AppSensor::FP or \c
/// rosa::app::AppSensor::SFP if set.
///
/// \note The only argument is a \c rosa::AtomConstant, hence its actual
/// value is ignored.
///
/// \pre Master-input is supposed to be completely received upon triggering:
/// \code
/// MasterInputNextPos == 0
/// \endcode
void
handleTrigger
(
atoms
::
Trigger
)
noexcept
;
/// Stores a new input value from the *master*.
///
/// The function stores \p Value at position \p Pos in \c
/// rosa::app::AppSensor::MasterInputValue and also sets the
/// flag \c rosa::app::AppSensor::MasterInputChanged. The function also
/// takes care of checking and updating \c
/// rosa::app::AppSensor::MasterInputNextPos: increments its value and
/// resets it to `0` when the last element is received.
///
/// \note Utilized by member functions of group \c
/// AppSensorMasterInputHandlers.
///
/// \tparam T type of input to store
///
/// \param Id unique identifier of the *master*
/// \param Pos position of the value in the \c rosa::app::AppTuple
/// \param Value the input value to store
///
/// \pre The *master* with \p Id is registered, \p Pos is the expected
/// position of master-input, and the input from the *master* at position \p
/// Pos is expected to be of type \p T: \code
/// Master && masterId() == Id && Pos == MasterInputNextPos &&
/// typeAtPositionOfToken(MasterInputType, Pos) == TypeNumberOf<T>::Value
/// \endcode
template
<
typename
T
>
void
saveMasterInput
(
id_t
Id
,
token_size_t
Pos
,
T
Value
)
noexcept
;
/// \defgroup AppSensorMasterInputHandlers Master-input handlers of
/// rosa::app::AppSensor
///
/// Definition of member functions handling messages from the *master* with
/// different types of input
///
/// A *slave* generally needs to be prepared to deal with values of any
/// built-in type to handle messages from its *master*. Each type requires a
/// separate message handler, which are implemented by these functions. The
/// functions instantiate \c rosa::app::AppSensor::saveMasterInput with
/// the proper template argument and pass the content of the message on for
/// processing.
///
/// \note The member functions in this group are defined by \c
/// ASMASTERHANDLERDEF.
///
/// \note Keep these definitions in sync with \c rosa::BuiltinTypes.
///
///@{
ASMASTERHANDLERDEF
(
AtomValue
)
ASMASTERHANDLERDEF
(
int16_t
)
ASMASTERHANDLERDEF
(
int32_t
)
ASMASTERHANDLERDEF
(
int64_t
)
ASMASTERHANDLERDEF
(
int8_t
)
ASMASTERHANDLERDEFN
(
long
double
,
long_double
)
ASMASTERHANDLERDEFN
(
std
::
string
,
std__string
)
ASMASTERHANDLERDEF
(
uint16_t
)
ASMASTERHANDLERDEF
(
uint32_t
)
ASMASTERHANDLERDEF
(
uint64_t
)
ASMASTERHANDLERDEF
(
uint8_t
)
ASMASTERHANDLERDEF
(
unit_t
)
ASMASTERHANDLERDEF
(
bool
)
ASMASTERHANDLERDEF
(
double
)
ASMASTERHANDLERDEF
(
float
)
/// @}
};
template
<
typename
...
Ts
,
size_t
...
S0
>
AppSensor
::
H
AppSensor
::
triggerHandlerFromProcessingFunction
(
std
::
function
<
void
(
std
::
pair
<
AppTuple
<
Ts
...
>
,
bool
>
)
>
&&
MF
,
Seq
<
S0
...
>
)
noexcept
{
using
MT
=
AppTuple
<
Ts
...
>
;
STATIC_ASSERT
(
sizeof
...(
Ts
)
==
sizeof
...(
S0
),
"inconsistent arguments"
);
ASSERT
(
MasterInputType
==
MT
::
TT
);
// NOTE: Clang 6 warns about unused lambda captures; we suppress that
// warning (those variables need to be captured).
ROSA_DISABLE_WARNING_PUSH
;
ROSA_DISABLE_WARNING_UNUSED_LAMBDA_CAPTURE
;
return
[
this
,
MF
](
void
)
noexcept
{
// Do not do anything for master-input type \c
// rosa::app::EmptyAppTuple.
if
constexpr
(
!
std
::
is_same
<
MT
,
EmptyAppTuple
>::
value
)
{
LOG_TRACE_STREAM
<<
"AppSensor "
<<
FullName
<<
" handles master-input."
<<
std
::
endl
;
// The assert must hold if \p this object was successfully constructed.
STATIC_ASSERT
(
(
true
&&
...
&&
(
static_cast
<
size_t
>
(
static_cast
<
token_size_t
>
(
S0
))
==
S0
)),
"Unexpected error"
);
const
auto
MasterInputArg
=
std
::
make_pair
(
// Get all elements of the tuple in a fold expression.
AppTuple
<
Ts
...
>
(
*
static_cast
<
const
Ts
*>
(
MasterInputValue
->
pointerTo
(
static_cast
<
token_size_t
>
(
S0
)))...),
MasterInputChanged
);
MasterInputChanged
=
false
;
MF
(
MasterInputArg
);
}
};
ROSA_DISABLE_WARNING_POP
;
}
template
<
typename
T
>
AppSensor
::
H
AppSensor
::
triggerHandlerFromDataSource
(
std
::
function
<
T
(
void
)
>
&&
F
,
bool
inSimulation
)
noexcept
{
STATIC_ASSERT
(
IsAppTuple
<
T
>::
Value
,
"not tuple type argument"
);
ASSERT
(
OutputType
==
T
::
TT
);
return
[
this
,
F
,
inSimulation
](
void
)
noexcept
{
// Get value and send it to master only if \p ExecutionPolicy allows it.
if
(
ExecutionPolicy
->
shouldProcess
({}))
{
LOG_TRACE_STREAM
<<
"AppSensor "
<<
Name
<<
" obtains next value."
<<
std
::
endl
;
sendToMaster
(
F
(),
seq_t
<
T
::
Length
>
());
}
else
{
LOG_TRACE_STREAM
<<
"AppSensor "
<<
Name
<<
" skips next value."
<<
std
::
endl
;
if
(
inSimulation
)
{
// But read input value in Simulation anyway as input values are
// provided for the highest execution frequency for simulation
(
void
)
F
();
}
}
};
}
template
<
typename
MT
,
typename
T
,
typename
>
AppSensor
::
AppSensor
(
const
AtomValue
Kind
,
const
id_t
Id
,
const
std
::
string
&
Name
,
MessagingSystem
&
S
,
std
::
function
<
void
(
std
::
pair
<
MT
,
bool
>
)
>
&&
MF
,
std
::
function
<
T
(
void
)
>
&&
F
)
noexcept
:
Agent
(
Kind
,
Id
,
Name
,
S
,
THISMEMBER
(
handleTrigger
),
ASMASTERHANDLERREF
(
AtomValue
),
ASMASTERHANDLERREF
(
int16_t
),
ASMASTERHANDLERREF
(
int32_t
),
ASMASTERHANDLERREF
(
int64_t
),
ASMASTERHANDLERREF
(
int8_t
),
ASMASTERHANDLERREF
(
long_double
),
ASMASTERHANDLERREF
(
std__string
),
ASMASTERHANDLERREF
(
uint16_t
),
ASMASTERHANDLERREF
(
uint32_t
),
ASMASTERHANDLERREF
(
uint64_t
),
ASMASTERHANDLERREF
(
uint8_t
),
ASMASTERHANDLERREF
(
unit_t
),
ASMASTERHANDLERREF
(
bool
),
ASMASTERHANDLERREF
(
double
),
ASMASTERHANDLERREF
(
float
)),
ExecutionPolicy
(
AppExecutionPolicy
::
decimation
(
1
)),
OutputType
(
T
::
TT
),
MasterInputType
(
MT
::
TT
),
MasterInputNextPos
(
0
),
MasterInputChanged
(
false
),
MasterInputValue
(
new
typename
TokenizedStorageForTypeList
<
typename
UnwrapAppTuple
<
MT
>::
Type
>::
Type
()),
MFP
(
triggerHandlerFromProcessingFunction
(
std
::
move
(
MF
),
seq_t
<
MT
::
Length
>
())),
FP
(
triggerHandlerFromDataSource
(
std
::
move
(
F
),
false
)),
SFP
(
nullptr
)
{
ASSERT
(
Kind
==
atoms
::
SensorKind
);
LOG_TRACE_STREAM
<<
"AppSensor "
<<
FullName
<<
" is created."
<<
std
::
endl
;
ASSERT
(
inv
());
}
template
<
typename
...
Ts
>
void
AppSensor
::
registerSimulationDataSource
(
std
::
function
<
AppTuple
<
Ts
...
>
(
void
)
>
&&
SF
)
noexcept
{
ASSERT
(
OutputType
==
TypeToken
<
Ts
...
>::
Value
);
SFP
=
triggerHandlerFromDataSource
(
std
::
move
(
SF
),
true
);
ASSERT
(
inv
());
}
template
<
typename
...
Ts
,
size_t
...
S0
>
void
AppSensor
::
sendToMaster
(
const
AppTuple
<
Ts
...
>
&
Value
,
Seq
<
S0
...
>
)
noexcept
{
STATIC_ASSERT
(
sizeof
...(
Ts
)
==
sizeof
...(
S0
),
"inconsistent arguments"
);
ASSERT
(
OutputType
==
TypeToken
<
Ts
...
>::
Value
);
// The assert must hold if \p this object was successfully constructed.
STATIC_ASSERT
((
true
&&
...
&&
(
static_cast
<
size_t
>
(
static_cast
<
token_size_t
>
(
S0
))
==
S0
)),
"Unexpected error"
);
// Create a static constant array for these indices to be available as lvalue
// references when creating messages below. \c S0... when used directly in a
// fold expression is a temporary value, which would result in \c
// rosa::Message instances being created with rvalue references. Further, all
// other values would to copied into a temporary variable for making them
/// available as rvalue references (they are constant lvalue references here).
static
constexpr
std
::
array
<
token_size_t
,
sizeof
...(
S0
)
>
Indices
{{
S0
...}};
LOG_TRACE_STREAM
<<
"AppSensor "
<<
FullName
<<
"("
<<
Id
<<
") sends to master("
<<
static_cast
<
bool
>
(
Master
&&
*
Master
)
<<
"): "
<<
Value
<<
std
::
endl
;
// There is a handle and the referred *master* is in a valid state.
if
(
Master
&&
*
Master
)
{
// Handle each element of the tuple in a fold expression.
(
Master
->
sendMessage
(
Message
::
create
(
atoms
::
Slave
::
Value
,
Id
,
Indices
[
S0
],
std
::
get
<
S0
>
(
Value
))),
...);
}
ASSERT
(
inv
());
}
template
<
typename
T
>
void
AppSensor
::
saveMasterInput
(
id_t
Id
,
token_size_t
Pos
,
T
Value
)
noexcept
{
ASSERT
(
Master
&&
masterId
()
==
Id
&&
Pos
==
MasterInputNextPos
&&
typeAtPositionOfToken
(
MasterInputType
,
Pos
)
==
TypeNumberOf
<
T
>::
Value
);
LOG_TRACE_STREAM
<<
"AppSensor "
<<
FullName
<<
"("
<<
Id
<<
") saves value from master: ("
<<
static_cast
<
size_t
>
(
Pos
)
<<
") "
<<
PRINTABLE
(
Value
)
<<
std
::
endl
;
// Save value.
*
static_cast
<
T
*>
(
MasterInputValue
->
pointerTo
(
Pos
))
=
Value
;
// Update position of next value.
if
(
++
MasterInputNextPos
==
lengthOfToken
(
MasterInputType
))
{
MasterInputNextPos
=
0
;
}
// Set flag.
MasterInputChanged
=
true
;
}
}
// End namespace app
}
// End namespace rosa
#undef ASMASTERHANDLEREF
#undef ASMASTERHANDLEDEF
#undef ASMASTERHANDLEDEFN
#undef ASMASTERHANDLENAME
#endif
// ROSA_APP_APPSENSOR_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Mar 1, 6:42 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
287517
Default Alt Text
AppSensor.hpp (25 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment