diff --git a/include/rosa/deluxe/DeluxeExecutionPolicy.h b/include/rosa/deluxe/DeluxeExecutionPolicy.h index 33bb063..ffbe353 100644 --- a/include/rosa/deluxe/DeluxeExecutionPolicy.h +++ b/include/rosa/deluxe/DeluxeExecutionPolicy.h @@ -1,76 +1,175 @@ //===-- 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 #include #include namespace rosa { namespace deluxe { // Forward declaration of DeluxeSystem. Do not include the corresponding header // in this file because of cyclic dependency. class DeluxeSystem; -/// \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. +/// *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 th + /// 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 th 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 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 awaitAll(const std::set &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 awaitAny(const std::set &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 &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 #endif // ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H diff --git a/lib/deluxe/executionpolicies/AwaitAll.h b/lib/deluxe/executionpolicies/AwaitAll.h index 28a42fe..1374f90 100644 --- a/lib/deluxe/executionpolicies/AwaitAll.h +++ b/lib/deluxe/executionpolicies/AwaitAll.h @@ -1,35 +1,48 @@ //===-- deluxe/executionpolicies/AwaitAll.h ---------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/executionpolicies/AwaitAll.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2019 /// -/// \brief Declaration of the DeluxeExecutionPolicy AwaitAll. +/// \brief Declaration of the *execution policy* *await all*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H #define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H #include "AwaitBase.h" namespace rosa { namespace deluxe { +/// Implementation of the *execution policy* *await all*. +/// +/// \see \c rosa::deluxe::DeluxeExecutionPolicy::awaitAll() class AwaitAll : public AwaitBase { public: + /// Constructor. + /// + /// The constructor instatiates \c rosa::deluxe::AwaitBase so that execution + /// is allowed when all *slave* positions included in \p S have received new + /// input since the last triggering. + /// + /// \param S set of *slave* positoins to check AwaitAll(const std::set &S); + /// Dumps \p this object into textual representation. + /// + /// \return textual representation of \p this object std::string dump(void) const noexcept override; }; } // End namespace deluxe } // End namespace rosa #endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H diff --git a/lib/deluxe/executionpolicies/AwaitAny.h b/lib/deluxe/executionpolicies/AwaitAny.h index 53fc3b4..d69df29 100644 --- a/lib/deluxe/executionpolicies/AwaitAny.h +++ b/lib/deluxe/executionpolicies/AwaitAny.h @@ -1,35 +1,48 @@ //===-- deluxe/executionpolicies/AwaitAny.h ---------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/executionpolicies/AwaitAny.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2019 /// -/// \brief Declaration of the DeluxeExecutionPolicy AwaitAny. +/// \brief Declaration of the *execution policy* *await any*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H #define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H #include "AwaitBase.h" namespace rosa { namespace deluxe { +/// Implementation of the *execution policy* *await any*. +/// +/// \see \c rosa::deluxe::DeluxeExecutionPolicy::awaitAny() class AwaitAny : public AwaitBase { public: + /// Constructor. + /// + /// The constructor instatiates \c rosa::deluxe::AwaitBase so that execution + /// is allowed when any of the *slave* positions included in \p S has received + /// new input since the last triggering. + /// + /// \param S set of *slave* positoins to check AwaitAny(const std::set &S); + /// Dumps \p this object into textual representation. + /// + /// \return textual representation of \p this object std::string dump(void) const noexcept override; }; } // End namespace deluxe } // End namespace rosa #endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H diff --git a/lib/deluxe/executionpolicies/AwaitBase.h b/lib/deluxe/executionpolicies/AwaitBase.h index 17f3d93..9e5fdbb 100644 --- a/lib/deluxe/executionpolicies/AwaitBase.h +++ b/lib/deluxe/executionpolicies/AwaitBase.h @@ -1,55 +1,105 @@ //===-- deluxe/executionpolicies/AwaitBase.h --------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/executionpolicies/AwaitBase.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2019 /// -/// \brief Declaration of the DeluxeExecutionPolicy AwaitBase. +/// \brief Declaration of an *execution policy* that makes decisions depending +/// on input state of *slave* positions. /// //===----------------------------------------------------------------------===// #ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITBASE_H #define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITBASE_H #include "rosa/deluxe/DeluxeExecutionPolicy.h" #include namespace rosa { namespace deluxe { +/// Implementation of an *execution policy* that makes decisions depending on +/// whether new input has been received at some *slave* positions since the +/// laste triggering. +/// +/// The class implements the \c rosa::deluxe::DeluxeExecutionPolicy interface +/// but delegates the defintion of the actual decision-making function to +/// subclasses. +/// +/// \see rosa::deluxe::AwaitAll +/// \see rosa::deluxe::AwaitAny class AwaitBase : public DeluxeExecutionPolicy { protected: + /// Set of *slave* positions to check. const std::set Set; + /// Type of decision-making function used in \c + /// rosa::deluxe::AwaitBase::doExecute(). using CheckerType = std::function::const_iterator, std::set::const_iterator, std::function)>; + // Decision-making function for \c rosa::deluxe::AwaitBase::doExecute(). const CheckerType Checker; + /// Protected constructor, only subclasses can instatiate the class. + /// + /// \param S set of *slave* positions to await input from + /// \param Checker function that decides about execution AwaitBase(const std::set &S, CheckerType &&Checker); public: + /// Tells if \p this object can handle the deluxe *unit* referred by \p H. + /// + /// Any *execution policy* based on this class can handle *agents* with at + /// least as many *slave* positions as the largest one defined in \c + /// rosa::deluxe::AwaitBase::Set. + /// + /// \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 bool canHandle(const AgentHandle H, const DeluxeSystem &S) const noexcept override; + /// Tells if processing function should be executed on the current triggering. + /// + /// Waiting for input allows execution when \c + /// rosa::deluxe::AwaitBase::Checker evaluates to \c true with respect to \c + /// rosa::deluxe::AwaitBase::Set and \p InputChanged. + /// + /// \param InputChanged flags indicating whether new input has been received + /// at *slave* positions + /// + /// \return if to execute processing function bool doExecute(const std::vector &InputChanged) noexcept override; private: + /// Tells if \p this object can handle a *unit* with \p NumberOfInputs *slave* + /// positions. + /// + /// \param NumberOfInputs the number of *slave* positions to consider + /// + /// \return if \p this object can handle a *unit* with \p NumberOfInputs + /// *slave* positions bool canHandleNumberOfInputs(const size_t NumberOfInputs) const noexcept; protected: + /// Dumps the set of *slave* positions that \p this object checks. + /// + /// \return textual representation of \c rosa::deluxe::AwaitBase::Set of \p + /// this object std::string dumpS(void) const noexcept; }; } // End namespace deluxe } // End namespace rosa #endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITBASE_H diff --git a/lib/deluxe/executionpolicies/Decimation.h b/lib/deluxe/executionpolicies/Decimation.h index 84db28d..8818524 100644 --- a/lib/deluxe/executionpolicies/Decimation.h +++ b/lib/deluxe/executionpolicies/Decimation.h @@ -1,44 +1,73 @@ //===-- deluxe/executionpolicies/Decimation.h -------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/executionpolicies/Decimation.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2019 /// -/// \brief Declaration of the DeluxeExecutionPolicy Decimation. +/// \brief Declaration of the *execution policy* *decimation*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H #define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H #include "rosa/deluxe/DeluxeExecutionPolicy.h" namespace rosa { namespace deluxe { +/// Implementation of the *execution policy* *decimation*. +/// +/// \see \c rosa::deluxe::DeluxeExecutionPolicy::decimation() class Decimation : public DeluxeExecutionPolicy { + + /// The rate of *decimation*. const size_t Rate; + /// Counter of triggerings. size_t Cycle; public: + /// Constructor. + /// + /// \param D the rate of *decimation* Decimation(const size_t D); + /// Tells if \p this object can handle the deluxe *unit* referred by \p H. + /// + /// *Decimation* can handle any *units*. + /// + /// \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 bool canHandle(const AgentHandle H, const DeluxeSystem &S) const noexcept override; + /// Tells if processing function should be executed on the current triggering. + /// + /// *Decimation* allows execution on each \c rosa::deluxe::Decimation::Rate + /// th triggering (i.e., calling of the function), which is counted + /// by \p this object in \c rosa::deluxe::Decimation::Cycle. + /// + /// \param InputChanged *ignored* + /// + /// \return if to execute processing function bool doExecute(const std::vector &InputChanged) noexcept override; + /// Dumps \p this object into textual representation. + /// + /// \return textual representation of \p this object std::string dump(void) const noexcept override; }; } // End namespace deluxe } // End namespace rosa #endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H