Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386246
DeluxeContext.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
12 KB
Referenced Files
None
Subscribers
None
DeluxeContext.hpp
View Options
//===-- rosa/deluxe/DeluxeContext.hpp ---------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/deluxe/DeluxeContext.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Public interface for the *deluxe interface* for working with agent
/// systems.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_DELUXE_DELUXECONTEXT_HPP
#define ROSA_DELUXE_DELUXECONTEXT_HPP
#include
"rosa/deluxe/DeluxeSystem.hpp"
#include
"rosa/support/types.hpp"
#include
<iterator>
#include
<memory>
#include
<set>
/// Local helper macro to log and return a
/// \c rosa::deluxe::DeluxeContext::ErrorCode value.
///
/// Creates a debug message with the stringified value and returns the value.
///
/// \param Err \c rosa::deluxe::DeluxeContext::ErrorCode value to log and
/// return
#define DCRETERROR(Err) \
{ \
LOG_DEBUG(#Err); \
return Err; \
}
namespace
rosa
{
namespace
deluxe
{
/// Defines the *deluxe interface*.
class
DeluxeContext
{
/// A system owned by \p this object.
///
/// \note The reference is kept in a \c std::shared_ptr because of the member
/// function \c rosa::deluxe::DeluxeContext::getSystem.
std
::
shared_ptr
<
DeluxeSystem
>
System
;
/// References to all *sensors* and *agents* created by \p this object.
std
::
set
<
AgentHandle
>
DeluxeUnits
;
public
:
/// Errors that may be resulted by some of the member functions of the class.
enum
struct
ErrorCode
{
NoError
,
TypeMismatch
,
NotSensor
,
NotAgent
,
WrongPosition
,
AlreadyHasSlave
,
AlreadyHasMaster
,
AlreadyHasValueStream
};
/// Returns a new instance of \c rosa::deluxe::DeluxeContext.
///
/// \param Name name of the underlying \c rosa::DeluxeSystem
///
/// \return \c std::unique_ptr for the new instance of
/// \c rosa::deluxe::DeluxeContext with a new, empty \c rosa::DeluxeSystem
static
std
::
unique_ptr
<
DeluxeContext
>
create
(
const
std
::
string
&
Name
)
noexcept
;
private
:
/// Creates a new instance.
///
/// \note Private constructor restricts instantiation to member functions of
/// the class.
///
/// \param Name name of the underlying \c rosa::MessagingSystem
DeluxeContext
(
const
std
::
string
&
Name
)
noexcept
;
public
:
/// Destroys \p this object.
~
DeluxeContext
(
void
)
noexcept
;
/// Returns a reference for the underlying \c rosa::MessagingSystem.
///
/// \note One cannot do much with a \c rosa::MessagingSystem currently, this
/// is for future use.
///
/// \return reference for the underlying \c rosa::MessagingSystem.
std
::
weak_ptr
<
MessagingSystem
>
getSystem
(
void
)
const
noexcept
;
/// Creates a new *sensor* in the context of \p this object.
///
/// \tparam T type of data the new *sensor* operates on
///
/// \todo The current implementation is an intermediate state, handles
/// built-in types and std::tuple, but the latter with with one element only.
/// Fix it when merging with DeluxeTuple.
///
/// \param Name name of the new *sensor*
/// \param F function for the new *sensor* to generate the next value with
/// during normal operation
///
/// \note \p F is not used during simulation, in which case
/// \c rosa::deluxe::DeluxeContext::registerSensorValues is used to register
/// an alternative simulation data source with
/// \c rosa::deluxe::DeluxeSensor::registerSimulationDataSource. One may
/// safely keep relying on the default value of \p F as long as only
/// simulation of the system is to be done.
///
/// \return \c rosa::AgentHandle for the new *sensor*
template
<
typename
T
>
AgentHandle
createSensor
(
const
std
::
string
&
Name
,
DeluxeSensor
::
D
<
T
>
&&
F
=
[](
void
)
{
return
T
();
})
noexcept
;
/// Creates a new *agent* in the context of \p this object.
///
/// \tparam T type of data the new *agent* outputs
/// \tparam As types of inputs the new *agent* takes
///
/// \param Name name of the new *agent*
/// \param F function for the new *agent* to process input values and
/// generate output with
///
/// \return \c rosa::AgentHandle for the new *agent*
template
<
typename
T
,
typename
...
As
>
AgentHandle
createAgent
(
const
std
::
string
&
Name
,
DeluxeAgent
::
D
<
T
,
As
...
>
&&
F
)
noexcept
;
/// Connectes a *sensor* to an *agent* in the context of \p this object.
///
/// \param Agent the *agent* to connect to
/// \param Pos the index of slot of \p Agent to connect \p Sensor to
/// \param Sensor the *sensor* to connect
/// \param Description optional textual description of the connection
///
/// \return how successfull connecting \p Sensor to \p Agent at slot index
/// \p Pos was
///
/// \note The function may return the following
/// \c rosa::deluxe::DeluxeContext::ErrorCode values:
/// `ErrorCode` | Comment
/// ----------- | -------
/// `NoError` | Success
/// `NotAgent` | Referred \p Agent is not \c rosa::deluxe::DeluxeAgent
/// `NotSensor` | Referred \p Sensor is not \c rosa::deluxe::DeluxeSensor
/// `WrongPosition` | \p Pos is not a valid input position of \p Agent
/// `TypeMismatch` | Expected input type at position \p Pos of \p Agent is other than the output type of \p Sensor
/// `AlreadyHasSlave` | \p Agent at position \p Pos already has a *slave* registered
/// `AlreadyHasMaster` | \p Sensor already has a *master* registered
ErrorCode
connectSensor
(
AgentHandle
Agent
,
const
size_t
Pos
,
AgentHandle
Sensor
,
const
std
::
string
&
Description
=
""
)
noexcept
;
/// Connectes two *agents* in the context of \p this object.
///
/// \param Master the *agent* to connect to
/// \param Pos the index of slot of \p Master to connect \p Slave to
/// \param Slave the *agent* to connect
/// \param Description optional textual description of the connection
///
/// \return how succesfull connecting \p Slave to \p Master at slot index
/// \p Pos was
///
/// \note The function may return the following
/// \c rosa::deluxe::DeluxeContext::ErrorCode values:
/// `ErrorCode` | Comment
/// ----------- | -------
/// `NoError` | Success
/// `NotAgent` | Referred \p Master or \p Slave is not \c rosa::deluxe::DeluxeAgent
/// `WrongPosition` | \p Pos is not a valid input position of \p Master
/// `TypeMismatch` | Expected input type at position \p Pos of \p Master is other than the output type of \p Slave
/// `AlreadyHasSlave` | \p Master at position \p Pos already has a *slave* registered
/// `AlreadyHasMaster` | \p Slave already has a *master* registered
ErrorCode
connectAgents
(
AgentHandle
Master
,
const
size_t
Pos
,
AgentHandle
Slave
,
const
std
::
string
&
Description
=
""
)
noexcept
;
/// Initializes \c this object and others managed by \p this object for
/// setting up and performing simulation.
///
/// \see \c rosa::deluxe::DeluxeContext::registerSensorValues,
/// \c rosa::deluxe::DeluxeContext::simulate
///
/// Need to clear simulation data sources from all the *sensors*.
void
initializeSimulation
(
void
)
noexcept
;
/// Registers a stream providing values for a *sensor* during simulation.
///
/// \tparam Iterator type of iterator providing values for \p Sensor
/// \tparam T type of values \p Sensor is operating on, always use default!
///
/// \param Sensor the *sensor* to register values for
/// \param Start provides values for \p Sensor
/// \param End denotes the end of stream of values
/// \param Default value to be used when input stream is depleted during
/// simulation
///
/// \return how successful registering \p Source for \p Sensor
///
/// \note The function may return the following
/// \c rosa::deluxe::DeluxeContext::ErrorCode values:
/// `ErrorCode` | Comment
/// ----------- | -------
/// `NoError` | Success
/// `TypeMismatch` | \p Sensor generates values of a type other than \p T
/// `NotSensor` | Referred \p Sensor is not \c rosa::deluxe::DeluxeSensor
/// `AlreadyHasValueStream` | \p Sensor already has simulation data source set
template
<
typename
Iterator
,
typename
T
=
typename
Iterator
::
value_type
>
ErrorCode
registerSensorValues
(
AgentHandle
Sensor
,
Iterator
&&
Start
,
const
Iterator
&
End
,
T
Default
=
{})
noexcept
;
/// Performs the system contained by \p this object.
///
/// The function performs \p NumCycles cycle of simulation. In each cycle,
/// all the *agents* and *sensors* registered in
/// \c rosa::deluxe::DeluxeContext::DeluxeUnits are trigged for execution.
///
/// \param NumCycles number of cycles to perform
///
/// \pre All the *sensors* in the system contained by \p this object generate
/// their output from simulation data sources.
void
simulate
(
const
size_t
NumCycles
)
const
noexcept
;
};
template
<
typename
T
>
AgentHandle
DeluxeContext
::
createSensor
(
const
std
::
string
&
Name
,
DeluxeSensor
::
D
<
T
>
&&
F
)
noexcept
{
AgentHandle
H
=
System
->
createSensor
<
T
>
(
Name
,
std
::
move
(
F
));
DeluxeUnits
.
emplace
(
H
);
return
H
;
}
template
<
typename
T
,
typename
...
As
>
AgentHandle
DeluxeContext
::
createAgent
(
const
std
::
string
&
Name
,
DeluxeAgent
::
D
<
T
,
As
...
>
&&
F
)
noexcept
{
AgentHandle
H
=
System
->
createAgent
(
Name
,
std
::
move
(
F
));
DeluxeUnits
.
emplace
(
H
);
return
H
;
}
/// Anonymous namespace for helper facilities, consider it private.
namespace
{
/// \todo Document...
template
<
typename
T
>
struct
UnwrapSensorType
{
using
Type
=
T
;
};
template
<
typename
...
Ts
>
struct
UnwrapSensorType
<
std
::
tuple
<
Ts
...
>>
{
using
Type
=
typename
std
::
tuple_element
<
0
,
std
::
tuple
<
Ts
...
>>::
type
;
};
}
// End namespace
template
<
typename
Iterator
,
typename
T
>
DeluxeContext
::
ErrorCode
DeluxeContext
::
registerSensorValues
(
AgentHandle
Sensor
,
Iterator
&&
Start
,
const
Iterator
&
End
,
T
Default
)
noexcept
{
// Get the type of values provided by \p Iterator.
STATIC_ASSERT
((
std
::
is_same
<
T
,
typename
Iterator
::
value_type
>::
value
),
"type mismatch"
);
constexpr
bool
isBuiltin
=
TypeListContains
<
BuiltinTypes
,
T
>::
Value
;
if
constexpr
(
!
isBuiltin
)
{
// T must be a std::tuple.
STATIC_ASSERT
(
std
::
tuple_size
<
T
>::
value
==
1
,
"Wrong tuple type"
);
STATIC_ASSERT
(
(
TypeListContains
<
BuiltinTypes
,
typename
std
::
tuple_element
<
0
,
T
>::
type
>::
Value
),
"Wrong element type in tuple"
);
}
using
TT
=
typename
UnwrapSensorType
<
T
>::
Type
;
// Make sure preconditions are met.
if
(
!
System
->
isDeluxeSensor
(
Sensor
))
{
DCRETERROR
(
ErrorCode
::
NotSensor
);
}
auto
S
=
System
->
getDeluxeSensor
(
Sensor
);
ASSERT
(
S
);
// Sanity check.
if
(
S
->
OutputType
!=
TypeNumberOf
<
TT
>::
Value
)
{
DCRETERROR
(
ErrorCode
::
TypeMismatch
);
}
else
if
(
S
->
simulationDataSourceIsSet
())
{
DCRETERROR
(
ErrorCode
::
AlreadyHasValueStream
);
}
// Register input stream.
// \note Need to capture parameters by value so having local copies.
S
->
registerSimulationDataSource
(
DeluxeSensor
::
D
<
TT
>
([
=
](
void
)
mutable
noexcept
{
if
(
Start
!=
End
)
{
TT
Value
;
if
constexpr
(
isBuiltin
)
{
Value
=
*
Start
;
}
else
{
Value
=
std
::
get
<
0
>
(
*
Start
);
}
++
Start
;
LOG_TRACE_STREAM
<<
"Reading next value for sensor '"
<<
S
->
FullName
<<
"': "
<<
Value
<<
'\n'
;
return
Value
;
}
else
{
TT
Value
;
if
constexpr
(
isBuiltin
)
{
Value
=
Default
;
}
else
{
Value
=
std
::
get
<
0
>
(
Default
);
}
LOG_TRACE_STREAM
<<
"Providing default value for sensor '"
<<
S
->
FullName
<<
"': "
<<
Value
<<
'\n'
;
return
Value
;
}
}));
return
ErrorCode
::
NoError
;
}
}
// End namespace deluxe
}
// End namespace rosa
// Undef local macro if not used in the corresponding implementation.
#ifndef ROSA_LIB_DELUXE_DELUXECONTEXT_CPP
#undef DCRETERROR
#endif
#endif
// ROSA_DELUXE_DELUXECONTEXT_HPP
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Wed, Jul 2, 12:53 AM (5 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157105
Default Alt Text
DeluxeContext.hpp (12 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment