Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386470
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
27 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/deluxe-interface/deluxe-interface.cpp
index 896f555..43222e4 100755
--- a/examples/deluxe-interface/deluxe-interface.cpp
+++ b/examples/deluxe-interface/deluxe-interface.cpp
@@ -1,191 +1,191 @@
//===-- examples/deluxe-interface/deluxe-interface.cpp ----------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/deluxe-interface/deluxe-interface.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related
/// classes.
//===----------------------------------------------------------------------===//
#include "rosa/config/version.h"
#include "rosa/deluxe/DeluxeContext.hpp"
#include <algorithm>
#include <cmath>
#include <vector>
using namespace rosa;
using namespace rosa::deluxe;
using namespace rosa::terminal;
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 16;
/// Helper function creating a deluxe agent for logging and forwarding values.
///
/// Received values are dumped to \c LOG_INFO_STREAM and then returned as
/// result.
///
/// \tparam T type of values to handle
///
/// \param C the deluxe context to create the agent in
/// \param Name name of the new agent
///
/// \return handle for the new agent
template <typename T>
AgentHandle createLowLevelAgent(std::unique_ptr<DeluxeContext> &C,
const std::string &Name) {
using handler = DeluxeAgent::D<T, T>;
using result = Optional<T>;
return C->createAgent(
Name, handler([&, Name](std::pair<T, bool> I) -> result {
LOG_INFO_STREAM << "\n******\n"
<< Name << " " << (I.second ? "<New>" : "<Old>")
<< " value: " << I.first << "\n******\n";
return {I.first};
}));
}
int main(void) {
LOG_INFO_STREAM << '\n'
<< library_string() << " -- " << Color::Red
<< "deluxe-interface example" << Color::Default << '\n';
std::unique_ptr<DeluxeContext> C = DeluxeContext::create("Deluxe");
//
// Create deluxe sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
AgentHandle IntSensor = C->createSensor<int32_t>("IntSensor");
AgentHandle FloatSensor = C->createSensor<float>("FloatSensor");
// Check and set execution policy for sensors.
LOG_INFO("Execution policies for sensors.");
- LOG_INFO(C->getExecutionPolicy(IntSensor)->dump());
+ LOG_INFO(std::to_string(*C->getExecutionPolicy(IntSensor)));
C->setExecutionPolicy(IntSensor, DeluxeExecutionPolicy::decimation(2));
C->setExecutionPolicy(FloatSensor, DeluxeExecutionPolicy::decimation(2));
- LOG_INFO(C->getExecutionPolicy(IntSensor)->dump());
+ LOG_INFO(std::to_string(*C->getExecutionPolicy(IntSensor)));
//
// Create low-level deluxe agents with \c createLowLevelAgent.
//
LOG_INFO("Creating low-level agents.");
AgentHandle IntAgent = createLowLevelAgent<int32_t>(C, "IntAgent");
AgentHandle FloatAgent = createLowLevelAgent<float>(C, "FloatAgent");
// Set execution policies for low-level agents.
LOG_INFO("Setting Execution policies for low-level agents.");
C->setExecutionPolicy(IntAgent, DeluxeExecutionPolicy::awaitAll({0}));
C->setExecutionPolicy(FloatAgent, DeluxeExecutionPolicy::awaitAll({0}));
//
// Connect sensors to low-level agents.
//
LOG_INFO("Connect sensors to their corresponding low-level agents.");
C->connectSensor(IntAgent, 0, IntSensor, "Int Sensor Channel");
C->connectSensor(FloatAgent, 0, FloatSensor, "Float Sensor Channel");
//
// Create a high-level deluxe agent.
//
LOG_INFO("Create high-level agent.");
// The new agent logs its input values and results in the the sum of them.
AgentHandle SumAgent = C->createAgent(
"Sum Agent", DeluxeAgent::D<double, int32_t, float>(
[](std::pair<int32_t, bool> I1,
std::pair<float, bool> I2) -> Optional<double> {
LOG_INFO_STREAM
<< "\n*******\nSum Agent triggered with values:\n"
<< (I1.second ? "<New>" : "<Old>")
<< " int value: " << I1.first << "\n"
<< (I2.second ? "<New>" : "<Old>")
<< " float value: " << I2.first << "\n******\n";
return {I1.first + I2.first};
}));
//
// Connect low-level agents to the high-level agent.
//
LOG_INFO("Connect low-level agents to the high-level agent.");
C->connectAgents(SumAgent, 0, IntAgent, "Int Agent Channel");
C->connectAgents(SumAgent, 1, FloatAgent, "Float Agent Channel");
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a log stream.
//
LOG_INFO("Create a logger agent.");
// The agent logs each new input value and produces nothing.
AgentHandle LoggerAgent =
C->createAgent("Logger Agent",
DeluxeAgent::D<unit_t, double>(
[](std::pair<double, bool> Sum) -> Optional<unit_t> {
if (Sum.second) {
LOG_INFO_STREAM << "Result: " << Sum.first << "\n";
}
return {};
}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO("Connect the high-level agent to the logger agent.");
C->connectAgents(LoggerAgent, 0, SumAgent, "Sum Agent Channel");
//
// Do simulation.
//
LOG_INFO("Setting up and performing simulation.");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
//
// Create some vectors and register them for their corresponding sensors.
//
std::vector<int32_t> IntValues(NumberOfSimulationCycles);
std::generate(IntValues.begin(), IntValues.end(),
[i = 0](void) mutable { return ++i; });
C->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end());
std::vector<float> FloatValues(NumberOfSimulationCycles);
std::generate(FloatValues.begin(), FloatValues.end(),
[f = 0.5f](void) mutable {
f += 0.3f;
return std::floor(f) + 0.5f;
});
C->registerSensorValues(FloatSensor, FloatValues.begin(), FloatValues.end());
//
// Simulate.
//
C->simulate(NumberOfSimulationCycles);
return 0;
}
diff --git a/include/rosa/deluxe/DeluxeExecutionPolicy.h b/include/rosa/deluxe/DeluxeExecutionPolicy.h
index ffbe353..6daa713 100644
--- a/include/rosa/deluxe/DeluxeExecutionPolicy.h
+++ b/include/rosa/deluxe/DeluxeExecutionPolicy.h
@@ -1,175 +1,195 @@
//===-- rosa/deluxe/DeluxeExecutionPolicy.h ---------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/deluxe/DeluxeExecutionPolicy.h
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Public interface of *execution policies* in the *deluxe interface*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H
#define ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H
#include "rosa/core/AgentHandle.hpp"
#include <memory>
+#include <ostream>
#include <set>
#include <vector>
namespace rosa {
namespace deluxe {
// Forward declaration of DeluxeSystem. Do not include the corresponding header
// in this file because of cyclic dependency.
class DeluxeSystem;
/// *Execution policy* that controls how *agents* and *sensors* call their
/// processing functions.
///
/// An *execution policy* can be applied to a deluxe *unit* only if \c
/// deluxe::rosa::DeluxeExecutionPolicy::canHandle() allows it. Each deluxe
/// *unit* must have a compatible *execution policy* associated to it, and the
/// *unit* queries \c rosa::deluxe::DeluxeExecutionPolicy::doExecute() on each
/// triggering and calls its processing funtion only if it is allowed by the
/// *execution policy*.
///
/// \see rosa::deluxe::DeluxeExecutionPolicy::decimation()
/// \see rosa::deluxe::DeluxeExecutionPolicy::awaitAll()
/// \see rosa::deluxe::DeluxeExecutionPolicy::awaitAny()
///
/// \todo Extend the interface with query functions about what kind of
/// execution policy is behind the interface. This can be done in relation
/// to the existing factory functions; for example, if the actual object is
/// decimation and with what rate.
class DeluxeExecutionPolicy {
protected:
/// Protected constructor, only implementations can instantiate the class.
DeluxeExecutionPolicy(void) noexcept = default;
private:
/// No instance can be copy-constructed, move-constructed, copied, and moved.
///
///@{
DeluxeExecutionPolicy(const DeluxeExecutionPolicy &) = delete;
DeluxeExecutionPolicy(DeluxeExecutionPolicy &&) = delete;
DeluxeExecutionPolicy &operator=(const DeluxeExecutionPolicy &) = delete;
DeluxeExecutionPolicy &operator=(DeluxeExecutionPolicy &&) = delete;
///@}
public:
/// Virtual destructor for subclasses.
virtual ~DeluxeExecutionPolicy(void) noexcept = default;
/// Creates an *execution policy* that allows execution with decimation of
/// triggering.
///
//// *Decimation* can handle both *agents* and *sensors*.
/// Processing functions are executed only on every \p D <sup>th</sup>
/// triggering. In the case of *sensors* in simulation, the simulation data
/// source is read on each triggering as it provides values with respect to
/// the highest execution frequency, but output is generated by the *sensor*
/// only on every \p D <sup>th</sup> triggering.
///
/// \note A rate of \c 0 is allowed as actual argument and is treated as rate
/// \c 1 (i.e., execute processing functions on each triggering).
///
/// \param D the rate of *decimation*
///
/// \return an *execution policy* implementing *decimation* with rate \p D
static std::unique_ptr<DeluxeExecutionPolicy> decimation(const size_t D);
/// Creates an *execution policy* that allows execution only if all defined
/// *slave* positions has new input.
///
/// *Await all* can handle only *agents* and only if the particular *agent*
/// has at least as many *slave* positions as the largest position defined in
/// \p S. Processing functions are executed only if new input has been
/// received for all defined *slave* positions.
///
/// \param S set of *slave* positions to await input from
///
/// \return an *execution policy* implementing *awaiting all* input from set
/// \p S
static std::unique_ptr<DeluxeExecutionPolicy>
awaitAll(const std::set<size_t> &S);
/// Creates an *execution policy* that allows execution if any of the defined
/// *slave* positions has new input.
///
/// *Await any* can handle only *agents* and only if the particular *agent*
/// has at least as many *slave* positions as the largest position defined in
/// \p S. Processing functions are executed if new input has been received for
/// any of the defined *slave* positions.
///
/// \param S set of *slave* positions to await input from
///
/// \return an *execution policy* implementing *awaiting any* input from set
/// \p S
static std::unique_ptr<DeluxeExecutionPolicy>
awaitAny(const std::set<size_t> &S);
/// Tells if \p this object can handle the deluxe *unit* referred by \p H.
///
/// The *execution policy* implemented by \p this object is applicable to the
/// given deluxe *unit* referred by \p H only if the function returns \c true.
///
/// \param H reference to the *unit* to check
/// \param S the system owning the *unit* referred by \p H
///
/// \return if \p this object can handle the *unit* referred by \p H
virtual bool canHandle(const AgentHandle H, const DeluxeSystem &S) const
noexcept = 0;
/// Tells if processing function should be executed on the current triggering.
///
/// The function is to be called on each triggering of the deluxe *unit*.
/// Decision about execution of processing function is done by \p this object
/// according to the implemented *execution policy*.
///
/// \param InputChanged flags indicating whether new input has been received
/// at *slave* positions
///
/// \return if to execute processing function
virtual bool doExecute(const std::vector<bool> &InputChanged) noexcept = 0;
/// Dumps \p this object into textual representation.
///
/// \return textual representation of \p this object
virtual std::string dump(void) const noexcept = 0;
protected:
/// Tells whether the *unit* referred by \p H is a \c
/// rosa::deluxe::DeluxeAgent.
///
/// \param H reference to the *unit* to check
/// \param S the system owning the *unit* referred by \p H
///
/// \return if the *unit* referred by \p H is a \c rosa::deluxe::DeluxeAgent
bool isDeluxeAgent(const AgentHandle H, const DeluxeSystem &S) const noexcept;
/// Tells the number of inputs handled by the *unit* referred by \p H.
///
/// If \p H refers to a \c rosa::deluxe::DeluxeAgent, the function returns the
/// number of inputs (i.e., *slave* positions) of the *agent*. Otherwise, the
/// function returns \c 0.
///
/// \param H reference to the *unit* to check
/// \param S the system owning the *unit* referred by \p H
///
/// \return the number of inputs handled by the *unit* referred by \p H
size_t numberOfDeluxeAgentInputs(const AgentHandle H,
const DeluxeSystem &S) const noexcept;
};
} // End namespace deluxe
} // End namespace rosa
+namespace std {
+
+/// Converts a \c rosa::deluxe::DeluxeExecutionPolicy into \c std::string.
+///
+/// \param EP \c rosa::deluxe::DeluxeExecutionPolicy to convert
+///
+/// \return \c std::string representing \p EP
+string to_string(const rosa::deluxe::DeluxeExecutionPolicy &EP);
+
+/// Dumps a \c rosa::deluxe::DeluxeExecutionPolicy to a given \c std::ostream.
+///
+/// \param [in,out] OS output stream to dump to
+/// \param EP \c rosa::deluxe::DeluxeExecutionPolicy to dump
+///
+/// \return \p OS after dumping \p EP to it
+ostream &operator<<(ostream &OS, const rosa::deluxe::DeluxeExecutionPolicy &EP);
+
+} // End namespace std
+
#endif // ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H
diff --git a/lib/deluxe/DeluxeAgent.cpp b/lib/deluxe/DeluxeAgent.cpp
index 3728913..0096b02 100755
--- a/lib/deluxe/DeluxeAgent.cpp
+++ b/lib/deluxe/DeluxeAgent.cpp
@@ -1,233 +1,238 @@
//===-- deluxe/DeluxeAgent.cpp ----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file deluxe/DeluxeAgent.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Implementation of rosa/deluxe/DeluxeAgent.hpp.
///
//===----------------------------------------------------------------------===//
#include "rosa/deluxe/DeluxeAgent.hpp"
#include "rosa/deluxe/DeluxeSystem.hpp"
#include <algorithm>
namespace rosa {
namespace deluxe {
bool DeluxeAgent::inv(void) const noexcept {
// Check execution policy.
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const DeluxeSystem &DS = static_cast<DeluxeSystem &>(Unit::system());
if (!ExecutionPolicy || !ExecutionPolicy->canHandle(Self, DS)) {
return false;
}
// Check container sizes.
if (!(InputTypes.size() == NumberOfInputs &&
InputChanged.size() == NumberOfInputs &&
InputValues->size() == NumberOfInputs &&
Slaves.size() == NumberOfInputs)) {
return false;
}
// Check *slave* types and validate *slave* registrations and reverse lookup
// information.
std::map<id_t, size_t> RefIds; // Build up a reference of SlaveIds in this.
for (size_t I = 0; I < NumberOfInputs; ++I) {
// First, validate input types at position \c I.
const TypeNumber T = InputTypes[I];
if (InputValues->typeAt(I) != T) {
return false;
}
// Check the registered *slave* at position \c I.
const auto &Slave = Slaves[I];
// If \c Slave is empty, nothing to check.
if (!Slave)
continue;
// \c Slave is not empty here.
// Check the `OutputType` of the registered *slave*.
const auto &A = unwrapAgent(*Slave);
if (!((A.Kind == atoms::SensorKind &&
static_cast<const DeluxeSensor &>(A).OutputType == T) ||
(A.Kind == atoms::AgentKind &&
static_cast<const DeluxeAgent &>(A).OutputType == T))) {
return false;
}
// Validate that the *slave* is not registered more than once.
if (std::any_of(
Slaves.begin() + I + 1, Slaves.end(),
[&Slave](const Optional<AgentHandle> &O) { return O && *Slave == *O; })) {
return false;
}
// Build the content of \c RefIds.
RefIds.emplace(A.Id, I);
}
// Validate *slave* reverse lookup information against our reference.
if (RefIds != SlaveIds) {
return false;
}
// All checks were successful, the invariant is held.
return true;
}
DeluxeAgent::~DeluxeAgent(void) noexcept {
ASSERT(inv());
LOG_TRACE("Destroying DeluxeAgent...");
// Make sure \p this object is not a registered *slave*.
if (Master) {
ASSERT(unwrapAgent(*Master).Kind == atoms::AgentKind); // Sanity check.
DeluxeAgent &M = static_cast<DeluxeAgent&>(unwrapAgent(*Master));
ASSERT(M.positionOfSlave(self()) != M.NumberOfInputs); // Sanity check.
M.registerSlave(M.positionOfSlave(self()), {});
Master = {};
}
// Also, make sure \p this object is no acting *master*.
for (size_t Pos = 0; Pos < NumberOfInputs; ++Pos) {
registerSlave(Pos, {});
}
// Now there is no connection with other entities, safe to destroy.
}
const DeluxeExecutionPolicy &DeluxeAgent::executionPolicy(void) const noexcept {
ASSERT(inv());
return *ExecutionPolicy;
}
bool DeluxeAgent::setExecutionPolicy(
std::unique_ptr<DeluxeExecutionPolicy> &&EP) noexcept {
ASSERT(inv());
+ LOG_TRACE_STREAM << "DeluxeAgent " << FullName << " setting execution policy "
+ << *EP << std::endl;
bool Success = false;
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const DeluxeSystem &DS = static_cast<DeluxeSystem &>(Unit::system());
if (EP && EP->canHandle(self(), DS)) {
ExecutionPolicy.swap(EP);
Success = true;
+ } else {
+ LOG_TRACE_STREAM << "Execution policy " << *EP
+ << " cannot handle DeluxeAgent " << FullName << std::endl;
}
ASSERT(inv());
return Success;
}
Optional<AgentHandle> DeluxeAgent::master(void) const noexcept {
ASSERT(inv());
return Master;
}
void DeluxeAgent::registerMaster(const Optional<AgentHandle> _Master) noexcept {
ASSERT(inv() && (!_Master || unwrapAgent(*_Master).Kind == atoms::AgentKind));
Master = _Master;
ASSERT(inv());
}
TypeNumber DeluxeAgent::inputType(const size_t Pos) const noexcept {
ASSERT(inv() && Pos < NumberOfInputs);
return InputTypes[Pos];
}
Optional<AgentHandle> DeluxeAgent::slave(const size_t Pos) const noexcept {
ASSERT(inv() && Pos < NumberOfInputs);
return Slaves[Pos];
}
void DeluxeAgent::registerSlave(const size_t Pos,
const Optional<AgentHandle> Slave) noexcept {
ASSERT(inv() && Pos < NumberOfInputs &&
(!Slave ||
(unwrapAgent(*Slave).Kind == atoms::SensorKind &&
static_cast<const DeluxeSensor &>(unwrapAgent(*Slave)).OutputType ==
InputTypes[Pos]) ||
(unwrapAgent(*Slave).Kind == atoms::AgentKind &&
static_cast<const DeluxeAgent &>(unwrapAgent(*Slave)).OutputType ==
InputTypes[Pos])));
// If registering an actual *slave*, not just clearing the slot, make sure
// the same *slave* is not registered to another slot.
if (Slave) {
auto It = SlaveIds.find(unwrapAgent(*Slave).Id);
if (It != SlaveIds.end()) {
Slaves[It->second] = {};//Optional<AgentHandle>();
SlaveIds.erase(It);
}
}
// Obtain the place whose content is to be replaced with \p Slave
auto &OldSlave = Slaves[Pos];
// If there is already a *slave* registered at \p Pos, clear reverse lookup
// information for it, and make sure it no longer has \p this object as
// *master*.
if (OldSlave) {
auto &A = unwrapAgent(*OldSlave);
ASSERT(SlaveIds.find(A.Id) != SlaveIds.end()); // Sanity check.
SlaveIds.erase(A.Id);
if (A.Kind == atoms::AgentKind) {
static_cast<DeluxeAgent &>(A).registerMaster({});
} else {
ASSERT(A.Kind == atoms::SensorKind); // Sanity check.
static_cast<DeluxeSensor &>(A).registerMaster({});
}
}
// Register \p Slave at \p Pos.
OldSlave = Slave;
// If registering an actual *slave*, not just clearing the slot, register
// reverse lookup information for the new *slave*.
if (Slave) {
SlaveIds.emplace(unwrapAgent(*Slave).Id, Pos);
}
ASSERT(inv());
}
size_t DeluxeAgent::positionOfSlave(const AgentHandle Slave) const noexcept {
ASSERT(inv());
bool Found = false;
size_t Pos = 0;
while (!Found && Pos < NumberOfInputs) {
auto &ExistingSlave = Slaves[Pos];
if (ExistingSlave && *ExistingSlave == Slave) {
Found = true;
} else {
++Pos;
}
}
ASSERT(Found || Pos == NumberOfInputs); // Sanity check.
return Pos;
}
void DeluxeAgent::handleTrigger(atoms::Trigger) noexcept {
ASSERT(inv());
FP();
ASSERT(inv());
}
} // End namespace deluxe
} // End namespace rosa
diff --git a/lib/deluxe/DeluxeExecutionPolicy.cpp b/lib/deluxe/DeluxeExecutionPolicy.cpp
index ee59bcd..bbea1ea 100644
--- a/lib/deluxe/DeluxeExecutionPolicy.cpp
+++ b/lib/deluxe/DeluxeExecutionPolicy.cpp
@@ -1,53 +1,67 @@
//===-- deluxe/DeluxeExecutionPolicy.cpp ------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file deluxe/DeluxeExecutionPolicy.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Implementation for rosa/deluxe/DeluxeExecutionPolicy.h.
///
//===----------------------------------------------------------------------===//
#include "rosa/deluxe/DeluxeExecutionPolicy.h"
#include "rosa/deluxe/DeluxeSystem.hpp"
#include "executionpolicies/Decimation.h"
#include "executionpolicies/AwaitAll.h"
#include "executionpolicies/AwaitAny.h"
namespace rosa {
namespace deluxe {
std::unique_ptr<DeluxeExecutionPolicy>
DeluxeExecutionPolicy::decimation(const size_t D) {
return std::unique_ptr<DeluxeExecutionPolicy>(new Decimation(D));
}
std::unique_ptr<DeluxeExecutionPolicy>
DeluxeExecutionPolicy::awaitAll(const std::set<size_t> &S) {
return std::unique_ptr<DeluxeExecutionPolicy>(new AwaitAll(S));
}
std::unique_ptr<DeluxeExecutionPolicy>
DeluxeExecutionPolicy::awaitAny(const std::set<size_t> &S) {
return std::unique_ptr<DeluxeExecutionPolicy>(new AwaitAny(S));
}
bool DeluxeExecutionPolicy::isDeluxeAgent(const AgentHandle H, const DeluxeSystem &S) const noexcept {
return S.isDeluxeAgent(H);
}
size_t DeluxeExecutionPolicy::numberOfDeluxeAgentInputs(
const AgentHandle H, const DeluxeSystem &S) const noexcept {
auto A = S.getDeluxeAgent(H);
return A ? A->NumberOfInputs : 0;
}
} // End namespace deluxe
} // End namespace rosa
+
+namespace std {
+
+string to_string(const rosa::deluxe::DeluxeExecutionPolicy &EP) {
+ return EP.dump();
+}
+
+ostream &operator<<(ostream &OS,
+ const rosa::deluxe::DeluxeExecutionPolicy &EP) {
+ OS << to_string(EP);
+ return OS;
+}
+
+} // End namespace std
diff --git a/lib/deluxe/DeluxeSensor.cpp b/lib/deluxe/DeluxeSensor.cpp
index 0175cd5..c5269f7 100755
--- a/lib/deluxe/DeluxeSensor.cpp
+++ b/lib/deluxe/DeluxeSensor.cpp
@@ -1,108 +1,113 @@
//===-- deluxe/DeluxeSensor.cpp ---------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file deluxe/DeluxeSensor.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Implementation of rosa/deluxe/DeluxeSensor.hpp.
///
//===----------------------------------------------------------------------===//
#include "rosa/deluxe/DeluxeSensor.hpp"
#include "rosa/deluxe/DeluxeSystem.hpp"
namespace rosa {
namespace deluxe {
bool DeluxeSensor::inv(void) const noexcept {
// Check execution policy.
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const DeluxeSystem &DS = static_cast<DeluxeSystem &>(Unit::system());
if (!ExecutionPolicy || !ExecutionPolicy->canHandle(Self, DS)) {
return false;
}
// All checks were successful, the invariant is held.
return true;
}
DeluxeSensor::~DeluxeSensor(void) noexcept {
ASSERT(inv());
LOG_TRACE("Destroying DeluxeSensor...");
// Make sure \p this object is not a registered *slave*.
if (Master) {
ASSERT(unwrapAgent(*Master).Kind == atoms::AgentKind); // Sanity check.
DeluxeAgent &M = static_cast<DeluxeAgent&>(unwrapAgent(*Master));
ASSERT(M.positionOfSlave(self()) != M.NumberOfInputs); // Sanity check.
M.registerSlave(M.positionOfSlave(self()), {});
Master = {};
}
}
const DeluxeExecutionPolicy &DeluxeSensor::executionPolicy(void) const
noexcept {
ASSERT(inv());
return *ExecutionPolicy;
}
bool DeluxeSensor::setExecutionPolicy(
std::unique_ptr<DeluxeExecutionPolicy> &&EP) noexcept {
ASSERT(inv());
+ LOG_TRACE_STREAM << "DeluxeSensor " << FullName
+ << " setting execution policy " << *EP << std::endl;
bool Success = false;
// \note The \c rosa::System the \c rosa::Unit is created with is a
// \c rosa::DeluxeSystem.
const DeluxeSystem &DS = static_cast<DeluxeSystem &>(Unit::system());
if (EP && EP->canHandle(self(), DS)) {
ExecutionPolicy.swap(EP);
Success = true;
+ } else {
+ LOG_TRACE_STREAM << "Execution policy " << *EP
+ << " cannot handle DeluxeSensor " << FullName << std::endl;
}
ASSERT(inv());
return Success;
}
Optional<AgentHandle> DeluxeSensor::master(void) const noexcept {
ASSERT(inv());
return Master;
}
void DeluxeSensor::registerMaster(const Optional<AgentHandle> _Master) noexcept {
ASSERT(inv() && (!_Master || unwrapAgent(*_Master).Kind == atoms::AgentKind));
Master = _Master;
ASSERT(inv());
}
void DeluxeSensor::clearSimulationDataSource(void) noexcept {
ASSERT(inv());
SFP = nullptr;
ASSERT(inv());
}
bool DeluxeSensor::simulationDataSourceIsSet(void) const noexcept {
ASSERT(inv());
return SFP != nullptr;
}
void DeluxeSensor::handleTrigger(atoms::Trigger) noexcept {
ASSERT(inv());
// Use \c rosa::deluxe::DeluxeSensor::SFP if set, otherwise
// \c rosa::deluxe::DeluxeSensor::FP.
const H &F = SFP ? SFP : FP;
F();
ASSERT(inv());
}
} // End namespace deluxe
} // End namespace rosa
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 3:55 PM (10 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157284
Default Alt Text
(27 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment