Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F10550883
DeluxeSensor.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
10 KB
Referenced Files
None
Subscribers
None
DeluxeSensor.hpp
View Options
//===-- rosa/deluxe/DeluxeSensor.hpp ----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/deluxe/DeluxeSensor.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Specialization of \c rosa::Agent for *sensor* role of the the *deluxe
/// interface*.
///
/// \see \c rosa::deluxe::DeluxeContext
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_DELUXE_DELUXESENSOR_HPP
#define ROSA_DELUXE_DELUXESENSOR_HPP
#include
"rosa/core/Agent.hpp"
#include
"rosa/deluxe/DeluxeAtoms.hpp"
#include
"rosa/deluxe/DeluxeExecutionPolicy.h"
namespace
rosa
{
namespace
deluxe
{
/// Specialization of \c rosa::Agent for *sensor* role of the *deluxe
/// interface*.
///
/// \see \c rosa::deluxe::DeluxeContext
///
/// \invariant There is a compatible *execution policy* set
///
/// \see Definition of \c rosa::deluxe::DeluxeSensor::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
DeluxeSensor
:
public
Agent
{
/// Checks whether \p this object holds the class invariant.
///
/// \see Invariant of the class \c rosa::deluxe::DeluxeSensor
///
/// \return if \p this object holds the class invariant
bool
inv
(
void
)
const
noexcept
;
/// The \c rosa::deluxe::DeluxeExecutionPolicy that controls the execution of
/// \c this object.
std
::
unique_ptr
<
DeluxeExecutionPolicy
>
ExecutionPolicy
;
public
:
/// Template alias for function objects used as data source for
/// \c rosa::deluxe::DeluxeSensor.
///
/// \note The function used for \c D is to be \c noexcept.
///
/// \tparam T type of data provided by the function
template
<
typename
T
>
using
D
=
std
::
function
<
T
(
void
)
>
;
/// The type of values produced by \p this object.
///
/// That is the type of values \p this object sends to its *master*.
///
/// \see \c rosa::deluxe::DeluxeSensor::master
const
TypeNumber
OutputType
;
private
:
/// Alias for function objects used as trigger handler for
/// \c rosa::deluxe::DeluxeSensor.
///
/// \note The function used for \c H is to be \c noexcept.
///
/// \see \c DeluxeSensorTriggerHandlers
using
H
=
std
::
function
<
void
(
void
)
>
;
/// \defgroup DeluxeSensorTriggerHandlers Trigger handlers of rosa::deluxe::DeluxeSensor
///
/// \brief Trigger handler functions of \c rosa::deluxe::DeluxeSensor
///
/// The actual data source functions are captured in a lambda expression that
/// is in turn wrapped in a \c std::function object. The lambda expression
/// calls the data source function to obtain the next sensory value and sends
/// it to *master* by calling \c rosa::deluxe::DeluxeSensor::sendToMaster. The
/// function \c rosa::deluxe::DeluxeSensor::handleTrigger needs only to call
/// the proper function object.
/// Handles trigger during normal execution.
///
/// \ingroup DeluxeSensorTriggerHandlers
///
/// The function is used during normal execution. During simulation, the
/// simulation environment sets \c rosa::deluxe::DeluxeSensor::SFP, which is
/// used instead of \c rosa::deluxe::DeluxeSensor::FP.
const
H
FP
;
/// Handles trigger during simulation.
///
/// \ingroup DeluxeSensorTriggerHandlers
///
/// 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::deluxe::DeluxeSensor instance does not have any *master* at a
/// given moment.
Optional
<
AgentHandle
>
Master
;
/// Wraps a data source function into a trigger handler.
///
/// \see \c DeluxeSensorTriggerHandlers
///
/// \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
///
/// \pre \p T matches \c rosa::deluxe::DeluxeSensor::OutputType: \code
/// OutputType == TypeNumberOf<T>::Value
/// \endcode
template
<
typename
T
>
H
triggerHandlerFromDataSource
(
D
<
T
>
&&
F
,
bool
inSimulation
)
noexcept
;
public
:
/// Creates a new instance.
///
/// The constructor instantiates the base-class with functions to handle
/// messages as defined for the *deluxe interface*.
///
/// \todo Enforce F does not potentially throw exception.
///
/// \tparam T type of data to operate on
///
/// \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 F function to generate the next value with during normal operation
///
/// \pre Statically, \p T is a built-in type:\code
/// TypeListContains<BuiltinTypes, T>::Value
/// \endcode
/// Dynamically, the instance is created as of kind
/// \c rosa::deluxe::atoms::SensorKind:
/// \code
/// Kind == rosa::deluxe::atoms::SensorKind
/// \endcode
template
<
typename
T
,
typename
=
std
::
enable_if_t
<
TypeListContains
<
BuiltinTypes
,
T
>::
Value
>>
DeluxeSensor
(
const
AtomValue
Kind
,
const
id_t
Id
,
const
std
::
string
&
Name
,
MessagingSystem
&
S
,
D
<
T
>
&&
F
)
noexcept
;
/// Destroys \p this object.
~
DeluxeSensor
(
void
)
noexcept
;
/// Returns the current execution policy of \p this object.
///
/// \see \c rosa::deluxe::DeluxeExecutionPolicy
///
/// \note The returned reference is valid only as long as \c
/// rosa::deluxe::DeluxeSensor::setExecutionPolicy() is not called and \p this
/// object is not destroyed.
///
/// \return \c rosa::deluxe::DeluxeSensor::ExecutionPolicy
const
DeluxeExecutionPolicy
&
executionPolicy
(
void
)
const
noexcept
;
/// Sets the current execution policy of \p this object to \p EP.
///
/// \see \c rosa::deluxe::DeluxeExecutionPolicy
///
/// \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
<
DeluxeExecutionPolicy
>
&&
EP
)
noexcept
;
/// The *master* of \p this object, if any.
///
/// \see \c rosa::deluxe::DeluxeSensor::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*.
///
/// \param _Master the *master* to register
///
/// \pre \p Master is empty or of kind \c rosa::deluxe::atoms::AgentKind:
/// \code
/// !_Master || unwrapAgent(*_Master).Kind == rosa::deluxe::atoms::AgentKind
/// \endcode
void
registerMaster
(
const
Optional
<
AgentHandle
>
_Master
)
noexcept
;
/// Clears the simulation trigger handler of \p this object.
///
/// The function assigns \c rosa::deluxe::DeluxeSensor::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::deluxe::DeluxeSensor::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::deluxe::DeluxeSensor::SFP by overwriting any already registered
/// simulation data source.
///
/// \todo Enforce SF does not potentially throw exception.
///
/// \tparam T type of data provided by \p SF
///
/// \param SF function to generate value with
///
/// \pre \p T matches \c rosa::deluxe::DeluxeSensor::OutputType: \code
/// OutputType == TypeNumberOf<T>::Value
/// \endcode
template
<
typename
T
>
void
registerSimulationDataSource
(
D
<
T
>
&&
SF
)
noexcept
;
private
:
/// Sends a value to the *master* of \p this object.
///
/// \p Value is getting sent to \c rosa::deluxe::DeluxeSensor::Master if it
/// contains a valid handle for a \c rosa::deluxe::DeluxeAgent. The function
/// does nothing otherwise.
///
/// \tparam T type of the value to send
///
/// \param Value value to send
///
/// \pre \p T matches \c rosa::deluxe::DeluxeSensor::OutputType: \code
/// OutputType == TypeNumberOf<T>::Value
/// \endcode
template
<
typename
T
>
void
sendToMaster
(
const
T
&
Value
)
noexcept
;
/// Generates the next sensory value upon trigger from the system.
///
/// Executes \c rosa::deluxe::DeluxeSensor::FP or
/// \c rosa::deluxe::DeluxeSensor::SFP if set.
///
/// \note The only argument is a \c rosa::AtomConstant, hence its actual
/// value is ignored.
void
handleTrigger
(
atoms
::
Trigger
)
noexcept
;
};
template
<
typename
T
>
DeluxeSensor
::
H
DeluxeSensor
::
triggerHandlerFromDataSource
(
D
<
T
>
&&
F
,
bool
inSimulation
)
noexcept
{
ASSERT
(
OutputType
==
TypeNumberOf
<
T
>::
Value
);
return
[
this
,
F
,
inSimulation
](
void
)
noexcept
{
// Get value and send it to master only if \p ExecutionPolicy allows it.
if
(
ExecutionPolicy
->
shouldProcess
({}))
{
sendToMaster
(
F
());
}
else
if
(
inSimulation
)
{
// But read input value in Simulation anyway as input values are provided
// for the highest execution frequency for simulation
F
();
}
};
}
template
<
typename
T
,
typename
>
DeluxeSensor
::
DeluxeSensor
(
const
AtomValue
Kind
,
const
id_t
Id
,
const
std
::
string
&
Name
,
MessagingSystem
&
S
,
D
<
T
>
&&
F
)
noexcept
:
Agent
(
Kind
,
Id
,
Name
,
S
,
THISMEMBER
(
handleTrigger
)),
ExecutionPolicy
(
DeluxeExecutionPolicy
::
decimation
(
1
)),
OutputType
(
TypeNumberOf
<
T
>::
Value
),
FP
(
triggerHandlerFromDataSource
(
std
::
move
(
F
),
false
)),
SFP
(
nullptr
)
{
ASSERT
(
Kind
==
atoms
::
SensorKind
);
LOG_TRACE
(
"DeluxeSensor is created."
);
ASSERT
(
inv
());
}
template
<
typename
T
>
void
DeluxeSensor
::
registerSimulationDataSource
(
D
<
T
>
&&
SF
)
noexcept
{
ASSERT
(
inv
()
&&
OutputType
==
TypeNumberOf
<
T
>::
Value
);
SFP
=
triggerHandlerFromDataSource
(
std
::
move
(
SF
),
true
);
ASSERT
(
inv
());
}
template
<
typename
T
>
void
DeluxeSensor
::
sendToMaster
(
const
T
&
Value
)
noexcept
{
ASSERT
(
inv
()
&&
OutputType
==
TypeNumberOf
<
T
>::
Value
);
// There is a handle and the referred *master* is in a valid state.
if
(
Master
&&
*
Master
)
{
Master
->
sendMessage
(
Message
::
create
(
atoms
::
Slave
::
Value
,
Id
,
Value
));
}
ASSERT
(
inv
());
}
}
// End namespace deluxe
}
// End namespace rosa
#endif
// ROSA_DELUXE_DELUXESENSOR_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, May 31, 12:06 AM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
306363
Default Alt Text
DeluxeSensor.hpp (10 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment