diff --git a/include/rosa/core/System.hpp b/include/rosa/core/System.hpp index f104180..25661cb 100644 --- a/include/rosa/core/System.hpp +++ b/include/rosa/core/System.hpp @@ -1,212 +1,212 @@ //===-- rosa/core/System.hpp ------------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/core/System.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Declaration of *System* interface. /// //===----------------------------------------------------------------------===// #ifndef ROSA_CORE_SYSTEM_HPP #define ROSA_CORE_SYSTEM_HPP #include "rosa/config/config.h" #include "rosa/core/forward_declarations.h" #include "rosa/support/debug.hpp" #include "rosa/support/log.h" #include #include #include namespace rosa { /// Base interface for actual agent-systems. /// /// The class provides facilities to keep track of \c rosa::Unit instances owned /// by a \c rosa::System. /// /// \note Any subclass is supposed to provide thread-safe implementation. /// /// \note The class declares only an interface to avoid trouble with multiple /// inheritance in various subclasses as in derived interfaces and derived /// implementations. /// /// \note Actual implementations are supposed to derive from \c rosa::SystemBase /// implenenting a base feature-set. class System { public: /// Signature of creator functions for \c rosa::Unit instances. /// /// \tparam T type derived from \c rosa::Unit /// \tparam S type derived from \c rosa::System template using UnitCreator = std::function; /// Returns an object implementing the \c rosa::System interface. /// /// \param Name name of the new instance /// /// \return \c std::unique_ptr for a new instance of \c rosa::System static std::unique_ptr createSystem(const std::string &Name) noexcept; protected: /// Creates an instance. /// /// \note Protected constructor restricts instantiation for subclasses. System(void) noexcept = default; /// No copying and moving of \c rosa::System. ///@{ System(const System &) = delete; System(System &&) = delete; System &operator=(const System &) = delete; System &operator=(System &&) = delete; ///@} public: /// Destroys \p this object. /// /// \note Any implementation makes sure that a \c rosa::System can be /// destroyed only if it is marked *cleaned* /// \see \c rosa::System::isSystemCleaned virtual ~System(void) = default; protected: /// Tells the next unique identifier to be used for a newly created /// \c rosa::Unit. /// /// \return \c rosa::id_t which is unique within the context of \p this /// object. /// /// \note Never returs the same value twice. virtual id_t nextId(void) noexcept = 0; /// Tells if \p this object has been marked cleaned and is ready for /// destruction. /// /// \return if \p this object is marked clean. virtual bool isSystemCleaned(void) const noexcept = 0; /// Marks \p this object cleaned. /// /// \note Can be called only once when the System does not have any live /// \c rosa::Unit instances. /// /// \pre \p this object has not yet been marked as cleaned and it has no /// \c rosa::Unit instances registered:\code /// !isSystemCleaned() && empty() /// \endcode /// /// \post \p this object is marked cleaned:\code /// isSystemCleaned() /// \encode virtual void markCleaned(void) noexcept = 0; /// Registers a \c rosa::Unit instance to \p this object. /// /// \param U \c rosa::Unit to register /// /// \pre \p this object has not yet been marked as cleaned and \p U is not /// registered yet:\code /// !isSystemCleaned() && !isUnitRegistered(U) /// \endcode /// /// \post \p U is registered:\code /// isUnitRegistered(U) /// \endcode virtual void registerUnit(Unit &U) noexcept = 0; /// Unregisters and destroys a registered \c rosa::Unit instance. /// /// \param U \c rosa::Unit to destroy /// /// \pre \p U is registered:\code /// isUnitRegistered(U) /// \endcode /// /// \post \p U is not registered and also destroyed. virtual void destroyUnit(Unit &U) noexcept = 0; /// Tells if a \c rosa::Unit is registered in \p this object. /// /// \param U \c rosa::Unit to check /// /// \return whether \p U is registered in \p this object virtual bool isUnitRegistered(const Unit &U) const noexcept = 0; /// Creates a \c rosa::Unit instance with the given /// \c rosa::System::UnitCreator and registers the new instance. /// /// \tparam T type of the actual \c rosa::Unit to instantiate /// \tparam S type of the actual \c rosa::System instantiating /// /// \param C function creating an instance of type \p T /// /// \note \p S must be the actual subclass that wants to instantiate /// \c rosa::Unit. That cannot be statically enforced, it is the /// reponsibility of the caller to provide the proper \c rosa::System /// subclass. /// /// \pre Statically, \p T is a subclass of \c rosa::Unit and \p S is a /// subclass of \c rosa::System:\code /// std::is_base_of::value && std::is_base_of::value /// \endcode Dynamically, \p this object has not yet been marked cleaned:\code /// !isSystemCleaned() /// \endcode template T &createUnit(UnitCreator C) noexcept; public: /// Tells the name of \p this object /// /// \note The returned reference remains valid as long as \p this object is /// not destroyed. /// /// \return name of \p this object virtual const std::string &name(void) const noexcept = 0; /// Tells the number of \c rosa::Unit instances constructed in the context of /// \p this object so far, including those being already destroyed. /// /// \return number of \c rosa::Unit instances created so far virtual size_t numberOfConstructedUnits(void) const noexcept = 0; /// Tells the number of live \c rosa::Unit instances in the context \p this /// object, those being constructed and not destroyed yet. /// /// \return number of \c rosa::Unit instances alive virtual size_t numberOfLiveUnits(void) const noexcept = 0; /// Tells if \p this object has no live \c rosa::Unit instances. /// /// \return whether \p this object has any live \c rosa::Unit instances virtual bool empty(void) const noexcept = 0; }; template T &System::createUnit(UnitCreator C) noexcept { STATIC_ASSERT((std::is_base_of::value), "not a Unit"); STATIC_ASSERT((std::is_base_of::value), "not a System"); if (isSystemCleaned()) { - ROSA_CRITICAL("Trying to create a Unit in a cleaned System (" + name() + - ")"); + ROSA_CRITICAL("Trying to create a Unit in a cleaned System '" + name() + + "'"); } const id_t Id = nextId(); T *U = C(Id, static_cast(*this)); registerUnit(*U); - LOG_TRACE("Unit created and registered (" + U->FullName + ")"); + LOG_TRACE("Unit created and registered '" + U->FullName + "'"); return *U; } } // End namespace rosa #endif // ROSA_CORE_SYSTEM_HPP diff --git a/lib/core/Agent.cpp b/lib/core/Agent.cpp index cb1566c..630df6c 100644 --- a/lib/core/Agent.cpp +++ b/lib/core/Agent.cpp @@ -1,50 +1,50 @@ //===-- core/Agent.cpp ------------------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file core/Agent.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Implementation of rosa/core/Agent.hpp. /// //===----------------------------------------------------------------------===// #include "rosa/core/Agent.hpp" namespace rosa { Agent::~Agent(void) { LOG_TRACE("Destroying Agent..."); } Agent::operator bool(void) const noexcept { // An Agent itself is always valid. return true; } bool Agent::operator==(const AgentHandle &H) const noexcept { // Return if the \c rosa::Agent wrapped by \p H is this very object. return this == &H.A; } AgentHandle Agent::self(void) noexcept { return Self; } void Agent::sendMessage(message_t &&M) noexcept { system().send(Self, std::move(M)); } std::string Agent::dump(void) const noexcept { - LOG_TRACE("Dumping Agent (" + FullName + ")"); + LOG_TRACE("Dumping Agent '" + FullName + "'"); return "[Agent] " + FullName; } MessagingSystem &Agent::system(void) const noexcept { // \note The \c rosa::System the \c rosa::Unit is created with is a // \c rosa::MessagingSystem. return static_cast(Unit::system()); } } // End namespace rosa diff --git a/lib/core/SystemBase.cpp b/lib/core/SystemBase.cpp index 3ddb7da..c75e8b8 100644 --- a/lib/core/SystemBase.cpp +++ b/lib/core/SystemBase.cpp @@ -1,58 +1,58 @@ //===-- core/SystemBase.cpp -------------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file core/SystemBase.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Implementation of rosa/core/SystemBase.hpp. /// //===----------------------------------------------------------------------===// #include "rosa/core/SystemBase.hpp" namespace rosa { SystemBase::SystemBase(const std::string &Name) noexcept : Name(Name), UnitCount(0), SystemIsCleaned(false) { - LOG_TRACE("Creating System (" + Name + ")"); + LOG_TRACE("Creating System '" + Name + "'"); } SystemBase::~SystemBase(void) { if (!SystemIsCleaned) { - ROSA_CRITICAL("Trying to destroy an uncleaned System (" + Name + ")"); + ROSA_CRITICAL("Trying to destroy an uncleaned System '" + Name + "'"); } - LOG_TRACE("Destroying System (" + Name + ")"); + LOG_TRACE("Destroying System '" + Name + "'"); } const std::string &SystemBase::name() const noexcept { return Name; } id_t SystemBase::nextId(void) noexcept { return ++UnitCount; } bool SystemBase::isSystemCleaned(void) const noexcept { return SystemIsCleaned; } void SystemBase::markCleaned(void) noexcept { if (SystemIsCleaned) { - ROSA_CRITICAL("System (" + Name + ") has been already mark cleaned"); + ROSA_CRITICAL("System '" + Name + "' has been already mark cleaned"); } else if (!empty()) { - ROSA_CRITICAL("Trying to mark a non-empty System (" + Name + ")"); + ROSA_CRITICAL("Trying to mark a non-empty System '" + Name + "'"); } else { SystemIsCleaned = true; - LOG_TRACE("System (" + Name + ") is marked cleaned"); + LOG_TRACE("System '" + Name + "' is marked cleaned"); } } size_t SystemBase::numberOfConstructedUnits(void) const noexcept { return UnitCount; } } // End namespace rosa diff --git a/lib/core/SystemImpl.cpp b/lib/core/SystemImpl.cpp index bda0c74..4815159 100644 --- a/lib/core/SystemImpl.cpp +++ b/lib/core/SystemImpl.cpp @@ -1,71 +1,71 @@ //===-- core/SystemImpl.cpp -------------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file core/SystemImpl.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Implementation for core/SystemImpl.hpp. /// //===----------------------------------------------------------------------===// #include "SystemImpl.hpp" #include "rosa/core/Unit.h" namespace rosa { SystemImpl::SystemImpl(const std::string &Name) noexcept : SystemBase(Name) {} SystemImpl::~SystemImpl(void) { if (!empty()) { - ROSA_CRITICAL("Trying to destroy a non-empty System (" + Name + ")"); + ROSA_CRITICAL("Trying to destroy a non-empty System '" + Name + "'"); } else { markCleaned(); } } void SystemImpl::registerUnit(Unit &U) noexcept { ASSERT(!isUnitRegistered(U) && "Unit already registered!"); // Obtain exclusive access and insert the \c rosa::Unit instance. std::lock_guard L(RegisterMutex); auto R = Units.insert(&U); if (!R.second) { ROSA_CRITICAL("Could not register Unit"); } } void SystemImpl::destroyUnit(Unit &U) noexcept { ASSERT(isUnitRegistered(U)); - LOG_TRACE("Destroying Unit (" + U.FullName + ")"); + LOG_TRACE("Destroying Unit '" + U.FullName + "'"); // Scope protected container access. { // Obtain exclusive access and remove the Unit. std::lock_guard L(RegisterMutex); auto R = Units.erase(&U); // \note This case is catched by assertion when that is enabled. if (!R) { ROSA_CRITICAL("Trying to remove unregistered Unit"); } } delete &U; } bool SystemImpl::isUnitRegistered(const Unit &U) const noexcept { // \note Casting away constness is safe here. return Units.find(const_cast(&U)) != Units.cend(); } size_t SystemImpl::numberOfLiveUnits(void) const noexcept { return Units.size(); } bool SystemImpl::empty(void) const noexcept { return Units.empty(); } } // End namespace rosa diff --git a/lib/core/Unit.cpp b/lib/core/Unit.cpp index 12764b1..e693624 100644 --- a/lib/core/Unit.cpp +++ b/lib/core/Unit.cpp @@ -1,53 +1,53 @@ //===-- core/Unit.cpp -------------------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file core/Unit.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Implementation of rosa/core/Unit.h. /// //===----------------------------------------------------------------------===// #include "rosa/core/Unit.h" #include "rosa/core/System.hpp" // NOLINT #include "rosa/support/debug.hpp" #include "rosa/support/log.h" namespace rosa { Unit::Unit(const AtomValue Kind, const id_t Id, const std::string &Name, System &S) noexcept : Kind(Kind), Id(Id), Name(Name), S(S), FullName(Name + "@" + S.name()) { ASSERT(!Name.empty()); - LOG_TRACE("Constructing Unit (" + FullName + " of kind '" + to_string(Kind) + - "')"); + LOG_TRACE("Constructing Unit '" + FullName + "' of kind '" + to_string(Kind) + + "'"); } -Unit::~Unit(void) { LOG_TRACE("Destroying Unit (" + FullName + ")"); } +Unit::~Unit(void) { LOG_TRACE("Destroying Unit '" + FullName + "'"); } /// The default implementation of \c rosa::Unit::dump emits /// \c rosa::Unit::FullName. std::string Unit::dump(void) const noexcept { - LOG_TRACE("Dumping Unit (" + FullName + ")"); + LOG_TRACE("Dumping Unit '" + FullName + "'"); return "[Unit] " + FullName; } System &Unit::system(void) const noexcept { return S; } std::ostream &operator<<(std::ostream &OS, const Unit &U) { OS << U.dump(); return OS; } } // End namespace rosa diff --git a/lib/deluxe/DeluxeContext.cpp b/lib/deluxe/DeluxeContext.cpp index cf3e0fe..7ec7ec8 100755 --- a/lib/deluxe/DeluxeContext.cpp +++ b/lib/deluxe/DeluxeContext.cpp @@ -1,151 +1,151 @@ //===-- deluxe/DeluxeContext.cpp --------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/DeluxeContext.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief Implementation for rosa/deluxe/DeluxeContext.hpp. /// //===----------------------------------------------------------------------===// #define ROSA_LIB_DELUXE_DELUXECONTEXT_CPP // For including helper macros. #include "rosa/deluxe/DeluxeContext.hpp" #include namespace rosa { namespace deluxe { std::unique_ptr DeluxeContext::create(const std::string &Name) noexcept { return std::unique_ptr(new DeluxeContext(Name)); } DeluxeContext::DeluxeContext(const std::string &Name) noexcept : System(DeluxeSystem::createSystem(Name)) { - LOG_TRACE("DeluxeContext for " + System->name() + " is created."); + LOG_TRACE("DeluxeContext for '" + System->name() + "' is created."); } DeluxeContext::~DeluxeContext(void) noexcept { // \c rosa::deluxe::DeluxeContext::System is not used outside, just clean it. for(auto U : DeluxeUnits) { System->destroyAgent(U); } System->markCleaned(); - LOG_TRACE("DeluxeContext for " + System->name() + - " prepared for destruction."); + LOG_TRACE("DeluxeContext for '" + System->name() + + "' prepared for destruction."); } DeluxeContext::ErrorCode DeluxeContext::connectSensor(AgentHandle &Agent, const size_t Pos, AgentHandle &Sensor, const std::string &Description) noexcept { // Generate trace log. auto &Trace = LOG_TRACE_STREAM; Trace << "Establishing connection"; if (!Description.empty()) { Trace << " '" << Description << "'"; } - Trace << " between " << System->unwrapAgent(Sensor).FullName << " and " - << System->unwrapAgent(Agent).FullName << "\n"; + Trace << " between '" << System->unwrapAgent(Sensor).FullName << "' and '" + << System->unwrapAgent(Agent).FullName << "'\n"; // Make sure preconditions are met. if (!System->isDeluxeAgent(Agent)) { DCRETERROR(ErrorCode::NotAgent); } else if (!System->isDeluxeSensor(Sensor)) { DCRETERROR(ErrorCode::NotSensor); } auto A = System->getDeluxeAgent(Agent); auto S = System->getDeluxeSensor(Sensor); ASSERT(A && S); // Sanity check. if (Pos >= A->NumberOfInputs) { DCRETERROR(ErrorCode::WrongPosition); } else if (A->inputType(Pos) != S->OutputType) { DCRETERROR(ErrorCode::TypeMismatch); } else if (A->slave(Pos)) { DCRETERROR(ErrorCode::AlreadyHasSlave); } else if (S->master()) { DCRETERROR(ErrorCode::AlreadyHasMaster); } // Do register. A->registerSlave(Pos, {Sensor}); S->registerMaster({Agent}); return ErrorCode::NoError; } DeluxeContext::ErrorCode DeluxeContext::connectAgents(AgentHandle &Master, const size_t Pos, AgentHandle &Slave, const std::string &Description) noexcept { // Generate trace log. auto &Trace = LOG_TRACE_STREAM; Trace << "Establishing connection"; if (!Description.empty()) { Trace << " '" << Description << "'"; } - Trace << " between " << System->unwrapAgent(Slave).FullName << " and " - << System->unwrapAgent(Master).FullName << "\n"; + Trace << " between '" << System->unwrapAgent(Slave).FullName << "' and '" + << System->unwrapAgent(Master).FullName << "'\n"; // Make sure preconditions are met. if (!(System->isDeluxeAgent(Master) && System->isDeluxeAgent(Slave))) { DCRETERROR(ErrorCode::NotAgent); } auto M = System->getDeluxeAgent(Master); auto S = System->getDeluxeSensor(Slave); ASSERT(M && S); // Sanity check. if (Pos >= M->NumberOfInputs) { DCRETERROR(ErrorCode::WrongPosition); } else if (M->inputType(Pos) != S->OutputType) { DCRETERROR(ErrorCode::TypeMismatch); } else if (M->slave(Pos)) { DCRETERROR(ErrorCode::AlreadyHasSlave); } else if (S->master()) { DCRETERROR(ErrorCode::AlreadyHasMaster); } // Do register. M->registerSlave(Pos, {Slave}); S->registerMaster({Master}); return ErrorCode::NoError; } std::weak_ptr DeluxeContext::getSystem(void) const noexcept { return std::weak_ptr(System); } void DeluxeContext::initializeSimulation(void) noexcept { // Clear simulation data sources from sensors. for (auto U : DeluxeUnits) { if (auto S = System->getDeluxeSensor(U)) { S->clearSimulationDataSource(); } } } void DeluxeContext::simulate(const size_t NumCycles) const noexcept { ASSERT(std::all_of( DeluxeUnits.begin(), DeluxeUnits.end(), [&](const AgentHandle &H) { return System->isDeluxeAgent(H) || System->isDeluxeSensor(H) && System->getDeluxeSensor(H)->simulationDataSourceIsSet(); })); for (size_t I = 1; I <= NumCycles; ++I) { LOG_TRACE("Simulation cycle: " + std::to_string(I)); for (auto U : DeluxeUnits) { U.sendMessage(Message::create(atoms::Trigger::Value)); } } } } // End namespace deluxe } // End namespace rosa