diff --git a/apps/ccam/CMakeLists.txt b/apps/ccam/CMakeLists.txt index 0f634a9..66e107a 100644 --- a/apps/ccam/CMakeLists.txt +++ b/apps/ccam/CMakeLists.txt @@ -1,12 +1,12 @@ if ( ROSA_COMPILER_IS_GCC_COMPATIBLE ) # Allow exceptions by removing restricting flag (needed by cxxopts) remove("-fno-exceptions" CMAKE_CXX_FLAGS) endif() set(SOURCES configuration.h) set(SOURCES statehandlerutils.h) ROSA_add_app(ccam ccam.cpp) ROSA_add_library_dependencies(ccam ROSAConfig) -ROSA_add_library_dependencies(ccam ROSADeluxe) +ROSA_add_library_dependencies(ccam ROSAApp) ROSA_add_library_dependencies(ccam ROSAAgent) diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp index 0f0ece9..c110fe7 100644 --- a/apps/ccam/ccam.cpp +++ b/apps/ccam/ccam.cpp @@ -1,532 +1,531 @@ //===-- apps/ccam/ccam.cpp --------------------------------------*- C++ -*-===// // // The RoSA Framework -- Application CCAM // // Distributed under the terms and conditions of the Boost Software /// License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file apps/ccam/ccam.cpp /// /// \author Maximilian Goetzinger (maximilian.goetzinger@tuwien.ac.at) /// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at) /// /// \date 2019 /// /// \brief The application CCAM implements the case study from the paper: /// M. Goetzinger, N. TaheriNejad, H. A. Kholerdi, A. Jantsch, E. Willegger, /// T. Glatzl, A.M. Rahmani, T.Sauter, P. Liljeberg: Model - Free Condition /// Monitoring with Confidence /// /// \todo Clean up source files of this app: add standard RoSA header comment /// for own files and do something with 3rd party files... //===----------------------------------------------------------------------===// #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Confidence.hpp" #include "rosa/agent/FunctionAbstractions.hpp" #include #include "rosa/config/version.h" #include "rosa/agent/SignalStateDetector.hpp" #include "rosa/agent/SystemStateDetector.hpp" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" -#include "rosa/deluxe/DeluxeTuple.hpp" +#include "rosa/app/AppTuple.hpp" #include #include #include #include #include "configuration.h" #include "statehandlerutils.h" using namespace rosa; using namespace rosa::agent; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; const std::string AppName = "CCAM"; int main(int argc, char **argv) { LOG_INFO_STREAM << '\n' << library_string() << " -- " << Color::Red << AppName << "app" << Color::Default << '\n'; // // Read the filepath of the config file of the observed system. The filepath // is in the first argument passed to the application. Fuzzy functions etc. // are described in this file. // if (argc < 2) { LOG_ERROR("Specify config File!\nUsage:\n\tccam config.json"); return 1; } std::string ConfigPath = argv[1]; // // Load config file and read in all parameters. Fuzzy functions etc. are // described in this file. // if (!readConfigFile(ConfigPath)) { LOG_ERROR_STREAM << "Could not read config from \"" << ConfigPath << "\"\n"; return 2; } // // Create a CCAM context. // LOG_INFO("Creating Context"); - std::unique_ptr ContextCCAM = DeluxeContext::create(AppName); + std::unique_ptr AppCCAM = Application::create(AppName); // // Create following function which shall give information if the time gap // between changed input(s) and changed output(s) shows already a malfunction // of the system. // // ____________ // / // / // __________/ // std::shared_ptr> BrokenDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 0.f, AppConfig.BrokenCounter, 1.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(1.f, 0.f)}}, 0.f)); // // Create following function which shall give information if the time gap // between changed input(s) and changed output(s) still shows a // well-functioning system. // // ____________ // \ // \ // \__________ // std::shared_ptr> OkDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 1.f, AppConfig.BrokenCounter, 0.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(0.f, 0.f)}}, 1.f)); // - // Create a DeluxeAgent with SystemStateDetector functionality. + // Create a AppAgent with SystemStateDetector functionality. // LOG_INFO("Create SystemStateDetector agent."); AgentHandle SystemStateDetectorAgent = createSystemStateDetectorAgent( - ContextCCAM, "SystemStateDetector", AppConfig.SignalConfigurations.size(), + AppCCAM, "SystemStateDetector", AppConfig.SignalConfigurations.size(), BrokenDelayFunction, OkDelayFunction); // // Set policy of SystemStateDetectorAgent that it wait for all // SignalStateDetectorAgents // std::set pos; for (size_t i = 0; i < AppConfig.SignalConfigurations.size(); ++i) pos.insert(pos.end(), i); - ContextCCAM->setExecutionPolicy(SystemStateDetectorAgent, - DeluxeExecutionPolicy::awaitAll(pos)); + AppCCAM->setExecutionPolicy(SystemStateDetectorAgent, + AppExecutionPolicy::awaitAll(pos)); // // Create Vectors for all sensors, all signal related fuzzy functions, all // signal state detectors, all signal state agents, and all input data files. // LOG_INFO("Creating sensors, SignalStateDetector functionalities and their " "Abstractions."); std::vector Sensors; std::vector>> SampleMatchesFunctions; std::vector>> SampleMismatchesFunctions; std::vector>> SignalIsStableFunctions; std::vector>> SignalIsDriftingFunctions; std::vector>> NumOfSamplesMatchFunctions; std::vector>> NumOfSamplesMismatchFunctions; std::vector>> SampleValidFunctions; std::vector>> SampleInvalidFunctions; std::vector>> NumOfSamplesValidFunctions; std::vector>> NumOfSamplesInvalidFunctions; std::vector>> SignalStateDetectors; std::vector SignalStateDetectorAgents; std::vector DataFiles; // // Go through all signal state configurations (number of signals), and create // functionalities for SignalStateDetector. // for (auto SignalConfiguration : AppConfig.SignalConfigurations) { // - // Create deluxe sensors. + // Create application sensors. // Sensors.emplace_back( - ContextCCAM->createSensor(SignalConfiguration.Name + "_Sensor")); + AppCCAM->createSensor(SignalConfiguration.Name + "_Sensor")); // // Create following function(s) which shall give information whether one // sample matches another one (based on the relative distance between them). // // ____________ // / \ // / \ // __________/ \__________ // // SampleMatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 0.f, -SignalConfiguration.InnerBound, 1.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 1.f, SignalConfiguration.OuterBound, 0.f)}, }, 0)); // // Create following function(s) which shall give information whether one // sample mismatches another one (based on the relative distance between // them). // // ____________ ____________ // \ / // \ / // \__________/ // // SampleMismatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 1.f, -SignalConfiguration.InnerBound, 0.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 0.f, SignalConfiguration.OuterBound, 1.f)}, }, 1)); // // Create following function(s) which shall give information whether a // signal is stable. // // ____________ // / \ // / \ // __________/ \__________ // // SignalIsStableFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 0.f, -SignalConfiguration.InnerBoundDrift, 1.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 1.f, SignalConfiguration.OuterBoundDrift, 0.f)}, }, 0)); // // Create following function(s) which shall give information whether a // signal is drifting. // // ____________ ____________ // \ / // \ / // \__________/ // // SignalIsDriftingFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 1.f, -SignalConfiguration.InnerBoundDrift, 0.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 0.f, SignalConfiguration.OuterBoundDrift, 1.f)}, }, 1)); // // Create following function(s) which shall give information how many // history samples match another sample. // // ____________ // / // / // __________/ // NumOfSamplesMatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp)); // // Create following function(s) which shall give information how many // history samples mismatch another sample. // // ____________ // \ // \ // \__________ // NumOfSamplesMismatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown)); // // Create following function(s) which shall give information how good all // samples in a state match each other. // // ____________ // / \ // / \ // __________/ \__________ // // SampleValidFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 0.f, -SignalConfiguration.InnerBound, 1.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 1.f, SignalConfiguration.OuterBound, 0.f)}, }, 0)); // // Create following function(s) which shall give information how good all // samples in a state mismatch each other. // // ____________ ____________ // \ / // \ / // \__________/ // // SampleInvalidFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 1.f, -SignalConfiguration.InnerBound, 0.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 0.f, SignalConfiguration.OuterBound, 1.f)}, }, 1)); // // Create following function(s) which shall give information how many // history samples match each other. // // ____________ // / // / // __________/ // NumOfSamplesValidFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp)); // // Create following function(s) which shall give information how many // history samples mismatch each other. // // ____________ // \ // \ // \__________ // NumOfSamplesInvalidFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown)); // // Create SignalStateDetector functionality // SignalStateDetectors.emplace_back( new SignalStateDetector( SignalConfiguration.Output ? SignalProperties::OUTPUT : SignalProperties::INPUT, std::numeric_limits::max(), SampleMatchesFunctions.back(), SampleMismatchesFunctions.back(), NumOfSamplesMatchFunctions.back(), NumOfSamplesMismatchFunctions.back(), SampleValidFunctions.back(), SampleInvalidFunctions.back(), NumOfSamplesValidFunctions.back(), NumOfSamplesInvalidFunctions.back(), SignalIsDriftingFunctions.back(), SignalIsStableFunctions.back(), SignalConfiguration.SampleHistorySize, SignalConfiguration.DABSize, SignalConfiguration.DABHistorySize)); // - // Create low-level deluxe agents + // Create low-level application agents // SignalStateDetectorAgents.push_back(createSignalStateDetectorAgent( - ContextCCAM, SignalConfiguration.Name, SignalStateDetectors.back())); + AppCCAM, SignalConfiguration.Name, SignalStateDetectors.back())); - ContextCCAM->setExecutionPolicy( + AppCCAM->setExecutionPolicy( SignalStateDetectorAgents.back(), - DeluxeExecutionPolicy::decimation(AppConfig.DownsamplingRate)); + AppExecutionPolicy::decimation(AppConfig.DownsamplingRate)); // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); - ContextCCAM->connectSensor( - SignalStateDetectorAgents.back(), 0, Sensors.back(), - SignalConfiguration.Name + "_Sensor ->" + SignalConfiguration.Name + - "_SignalStateDetector_Agent-Channel"); + AppCCAM->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(), + SignalConfiguration.Name + "_Sensor ->" + + SignalConfiguration.Name + + "_SignalStateDetector_Agent-Channel"); - ContextCCAM->connectAgents( + AppCCAM->connectAgents( SystemStateDetectorAgent, SignalStateDetectors.size() - 1, SignalStateDetectorAgents.back(), SignalConfiguration.Name + "_SignalStateDetector_Agent->SystemStateDetector_Agent_Channel"); } // // For simulation output, create a logger agent writing the output of the // high-level agent into a CSV file. // LOG_INFO("Create a logger agent."); // Create CSV writer. std::ofstream OutputCSV(AppConfig.OutputFilePath); for (auto SignalConfiguration : AppConfig.SignalConfigurations) { OutputCSV << SignalConfiguration.Name + ","; } OutputCSV << "StateID,"; OutputCSV << "Confidence State Valid,"; OutputCSV << "Confidence State Invalid,"; OutputCSV << "Confidence Inputs Matching,"; OutputCSV << "Confidence Outputs Matching,"; OutputCSV << "Confidence Inputs Mismatching,"; OutputCSV << "Confidence Outputs Mismatching,"; OutputCSV << "State Condition,"; OutputCSV << "Confidence System Functioning,"; OutputCSV << "Confidence System Malfunctioning,"; OutputCSV << "Overall Confidence,"; OutputCSV << "\n"; // The agent writes each new input value into a CSV file and produces // nothing. using Input = std::pair; - using Result = Optional>; + using Result = Optional>; using Handler = std::function; std::string Name = "Logger Agent"; - AgentHandle LoggerAgent = ContextCCAM->createAgent( + AgentHandle LoggerAgent = AppCCAM->createAgent( "Logger Agent", Handler([&OutputCSV](Input I) -> Result { const SystemStateTuple &T = I.first; OutputCSV << std::get<0>( static_cast &>(T)) << std::endl; return Result(); })); // // Connect the high-level agent to the logger agent. // LOG_INFO("Connect the high-level agent to the logger agent."); - ContextCCAM->connectAgents(LoggerAgent, 0, SystemStateDetectorAgent, - "SystemStateDetector Channel"); + AppCCAM->connectAgents(LoggerAgent, 0, SystemStateDetectorAgent, + "SystemStateDetector Channel"); // // Only log if the SystemStateDetector actually ran // - ContextCCAM->setExecutionPolicy(LoggerAgent, - DeluxeExecutionPolicy::awaitAll({0})); + AppCCAM->setExecutionPolicy(LoggerAgent, AppExecutionPolicy::awaitAll({0})); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // - // Initialize deluxe context for simulation. + // Initialize application for simulation. // - ContextCCAM->initializeSimulation(); + AppCCAM->initializeSimulation(); // // Open CSV files and register them for their corresponding sensors. // // Make sure DataFiles will not change capacity while adding elements to it. // Changing capacity moves elements away, which invalidates references // captured by CSVIterator. DataFiles.reserve(AppConfig.SignalConfigurations.size()); uint32_t i = 0; for (auto SignalConfiguration : AppConfig.SignalConfigurations) { DataFiles.emplace_back(SignalConfiguration.InputPath); if (!DataFiles.at(i)) { LOG_ERROR_STREAM << "Cannot open Input File \"" << SignalConfiguration.InputPath << "\" for Signal \"" << SignalConfiguration.Name << "\"" << std::endl; return 3; } - ContextCCAM->registerSensorValues(Sensors.at(i), - csv::CSVIterator(DataFiles.at(i)), - csv::CSVIterator()); + AppCCAM->registerSensorValues(Sensors.at(i), + csv::CSVIterator(DataFiles.at(i)), + csv::CSVIterator()); i++; } // // Start simulation. // - ContextCCAM->simulate(AppConfig.NumberOfSimulationCycles); + AppCCAM->simulate(AppConfig.NumberOfSimulationCycles); return 0; } diff --git a/apps/ccam/cheatsheet.c b/apps/ccam/cheatsheet.c deleted file mode 100644 index 749478d..0000000 --- a/apps/ccam/cheatsheet.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "rosa/deluxe/DeluxeContext.hpp" - -std::unique_ptr C = DeluxeContext::create("Deluxe"); -// sensor -C->createSensor(name, - // lambda function - [](std::pair I) -> void { - // automatically pushes its value to the - // connected agent - }); - -// --------------------------------------------------------------------------- -// communication with 1 other agent -// --------------------------------------------------------------------------- -// Handlerfunctions have to be the corresponding std::functions - -// singe input singe output -C->createAgent(Name, - Handlerfunction( - // lambda function - [](std::pair I) -> optional { - //... - // return {value}; - })); - -// multi input single output -C->createAgent(Name, - Handlerfunction( - // lambda function - [](std::pair, bool> I) - -> optional> { - //... - // DeluxeTuple output(value); - // return {output}; - })); - -// single input multi output -C->createAgent(Name, - Handlerfunction( - // lambda function - [](std::pair, bool> I) - -> optional> { - //... - // DeluxeTuple - // output(value1,value2); - // return {output}; - })); - -// multi in/out and handles results from master -C->createAgent( - Name, - // Master-input handler. - MasterHandlerfunction( - // lambda function - [](std::pair, bool> I) - -> void { // you can again return something to the master but i - // don't know at the moment the changes that would cause - // - //.. - }), - // input handler. - Handlerfunction( - // lambda function - [](std::pair, bool> I) - -> optional> { - //... - // DeluxeTuple - // output(value1,value2); - // return {output}; - })); - -// --------------------------------------------------------------------------- -// communication with n other agent -// --------------------------------------------------------------------------- - -// I don't know how it reacts if input 1 is a DeluxeTuple and input 2 is just a -// value I'm just using all with DeluxeTuples -C->createAgent( - Name, Handlerfunction( - // lambda function - [](std::pair, bool> I0, - std::pair, bool> I1, - std::pair, bool> I2, - ...) -> std::tuple>, - Optional>, - Optional>, - Optional>, ...>; - { - // ... - // return {{for_master}, {for_slave_1}, {for_slave_1}, - // {for_slave_1}}; - })); \ No newline at end of file diff --git a/apps/ccam/cheatsheet.cpp b/apps/ccam/cheatsheet.cpp new file mode 100644 index 0000000..06e52e9 --- /dev/null +++ b/apps/ccam/cheatsheet.cpp @@ -0,0 +1,90 @@ +#include "rosa/app/Application.hpp" + +std::unique_ptr A = Application::create("App"); +// sensor +A->createSensor(name, + // lambda function + [](std::pair I) -> void { + // automatically pushes its value to the + // connected agent + }); + +// --------------------------------------------------------------------------- +// communication with 1 other agent +// --------------------------------------------------------------------------- +// Handlerfunctions have to be the corresponding std::functions + +// singe input singe output +A->createAgent(Name, + Handlerfunction( + // lambda function + [](std::pair I) -> optional { + //... + // return {value}; + })); + +// multi input single output +A->createAgent(Name, Handlerfunction( + // lambda function + [](std::pair, bool> I) + -> optional> { + //... + // AppTuple output(value); + // return {output}; + })); + +// single input multi output +A->createAgent(Name, Handlerfunction( + // lambda function + [](std::pair, bool> I) + -> optional> { + //... + // AppTuple + // output(value1,value2); + // return {output}; + })); + +// multi in/out and handles results from master +A->createAgent( + Name, + // Master-input handler. + MasterHandlerfunction( + // lambda function + [](std::pair, bool> I) + -> void { // you can again return something to the master but i + // don't know at the moment the changes that would cause + // + //.. + }), + // input handler. + Handlerfunction( + // lambda function + [](std::pair, bool> I) + -> optional> { + //... + // AppTuple + // output(value1,value2); + // return {output}; + })); + +// --------------------------------------------------------------------------- +// communication with n other agent +// --------------------------------------------------------------------------- + +// I don't know how it reacts if input 1 is a AppTuple and input 2 is just a +// value I'm just using all with AppTuples +A->createAgent( + Name, Handlerfunction( + // lambda function + [](std::pair, bool> I0, + std::pair, bool> I1, + std::pair, bool> I2, + ...) -> std::tuple>, + Optional>, + Optional>, + Optional>, ...>; + { + // ... + // return {{for_master}, {for_slave_1}, {for_slave_1}, + // {for_slave_1}}; + })); diff --git a/apps/ccam/configuration.h b/apps/ccam/configuration.h index 24214a6..723ee91 100644 --- a/apps/ccam/configuration.h +++ b/apps/ccam/configuration.h @@ -1,87 +1,87 @@ #ifndef CONFIGURATION_H #define CONFIGURATION_H // clang-tidy off // clang-format off #include "json.hpp" // clang-format on // clang-tidy on #include "rosa/config/version.h" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include using namespace rosa; using nlohmann::json; struct SignalConfiguration { std::string Name; std::string InputPath; bool Output; float InnerBound; float OuterBound; float InnerBoundDrift; float OuterBoundDrift; uint32_t SampleHistorySize; uint32_t DABSize; uint32_t DABHistorySize; }; struct AppConfiguration { std::string OutputFilePath; uint32_t BrokenCounter; uint32_t NumberOfSimulationCycles; uint32_t DownsamplingRate; std::vector SignalConfigurations; }; void from_json(const json &J, SignalConfiguration &SC) { J.at("Name").get_to(SC.Name); J.at("InputPath").get_to(SC.InputPath); J.at("Output").get_to(SC.Output); J.at("InnerBound").get_to(SC.InnerBound); J.at("OuterBound").get_to(SC.OuterBound); J.at("InnerBoundDrift").get_to(SC.InnerBoundDrift); J.at("OuterBoundDrift").get_to(SC.OuterBoundDrift); J.at("SampleHistorySize").get_to(SC.SampleHistorySize); J.at("DABSize").get_to(SC.DABSize); J.at("DABHistorySize").get_to(SC.DABHistorySize); } void from_json(const json &J, AppConfiguration &AC) { J.at("OutputFilePath").get_to(AC.OutputFilePath); J.at("BrokenCounter").get_to(AC.BrokenCounter); J.at("NumberOfSimulationCycles").get_to(AC.NumberOfSimulationCycles); J.at("DownsamplingRate").get_to(AC.DownsamplingRate); J.at("SignalConfigurations").get_to(AC.SignalConfigurations); } AppConfiguration AppConfig; bool readConfigFile(std::string ConfigPath) { LOG_INFO("READING CONFIG FILE"); LOG_INFO_STREAM << "Looking for config file at \"" << ConfigPath << "\"\n"; std::ifstream ConfigFile; ConfigFile.open(ConfigPath); if (!ConfigFile) { LOG_ERROR("Unable to open config file"); return false; } json ConfigObj; ConfigFile >> ConfigObj; LOG_INFO_STREAM << "Read JSON file as \"" << ConfigObj << "\"\n"; try { ConfigObj.get_to(AppConfig); } catch (nlohmann::detail::type_error ex) { LOG_ERROR("Misformatted Config File"); return false; } return true; } #endif // CONFIGURATION_H diff --git a/apps/ccam/statehandlerutils.h b/apps/ccam/statehandlerutils.h index 924689c..3542842 100644 --- a/apps/ccam/statehandlerutils.h +++ b/apps/ccam/statehandlerutils.h @@ -1,229 +1,229 @@ #ifndef STATEHANDLERUTILS_H #define STATEHANDLERUTILS_H #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Confidence.hpp" #include "rosa/agent/FunctionAbstractions.hpp" #include #include #include #include #include "rosa/config/version.h" #include "rosa/agent/SignalStateDetector.hpp" #include "rosa/agent/SystemStateDetector.hpp" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" #include #include #include #include using namespace rosa; using namespace rosa::agent; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; // For the convinience to write a shorter data type name using SignalStateTuple = - DeluxeTuple; + AppTuple; AgentHandle createSignalStateDetectorAgent( - std::unique_ptr &C, const std::string &Name, + std::unique_ptr &C, const std::string &Name, std::shared_ptr< SignalStateDetector> SigSD) { - using Input = std::pair, bool>; + using Input = std::pair, bool>; using Result = Optional; using Handler = std::function; return C->createAgent( Name, Handler([&, Name, SigSD](Input I) -> Result { LOG_INFO_STREAM << "\n******\n" << Name << " " << (I.second ? "" : "") << " value: " << std::get<0>( static_cast &>(I.first)) << "\n******\n"; auto StateInfo = SigSD->detectSignalState( std::get<0>(static_cast &>(I.first))); if (I.second) { SignalStateTuple Res = { std::get<0>(static_cast &>(I.first)), StateInfo.StateID, StateInfo.SignalProperty, StateInfo.ConfidenceOfMatchingState, StateInfo.ConfidenceOfMismatchingState, StateInfo.ConfidenceStateIsValid, StateInfo.ConfidenceStateIsInvalid, StateInfo.ConfidenceStateIsStable, StateInfo.ConfidenceStateIsDrifting, StateInfo.StateCondition, StateInfo.NumberOfInsertedSamplesAfterEntrance, static_cast( (StateInfo.StateIsValid ? 4 : 0) + (StateInfo.StateJustGotValid ? 2 : 0) + (StateInfo.StateIsValidAfterReentrance ? 1 : 0))}; return Result(Res); } return Result(); })); } // System State -using SystemStateTuple = DeluxeTuple; +using SystemStateTuple = AppTuple; template struct Handler_helper; template struct function_helper { static_assert(std::conjunction_v...>, "All types need to be identical"); static B function(A valA, As... valAs) { std::vector ar({valA, valAs...}); return func()(ar); } }; template struct Handler_helper<0, ret, functype, typeA, B...> { using handler = function_helper; }; template struct Handler_helper { using handler = typename Handler_helper, B...>::handler; }; template using Handler = typename Handler_helper::handler; // TODO: Change it from global to local variable if possible std::shared_ptr< SystemStateDetector> SysSD; template struct function { ret operator()(A a) { std::vector> SignalStateInfos; std::stringstream OutString; for (auto _SignalStateTuple : a) { // convert tuple to info struct out.push_back({}); OutString << std::get<0>(_SignalStateTuple.first) << ","; SignalStateInformation Info; Info.StateID = std::get<1>(_SignalStateTuple.first); Info.SignalProperty = static_cast(std::get<2>(_SignalStateTuple.first)); Info.ConfidenceOfMatchingState = std::get<3>(_SignalStateTuple.first); Info.ConfidenceOfMismatchingState = std::get<4>(_SignalStateTuple.first); Info.ConfidenceStateIsValid = std::get<5>(_SignalStateTuple.first); Info.ConfidenceStateIsInvalid = std::get<6>(_SignalStateTuple.first); Info.ConfidenceStateIsStable = std::get<7>(_SignalStateTuple.first); Info.ConfidenceStateIsDrifting = std::get<8>(_SignalStateTuple.first); Info.StateCondition = static_cast(std::get<9>(_SignalStateTuple.first)); Info.NumberOfInsertedSamplesAfterEntrance = std::get<10>(_SignalStateTuple.first); Info.StateIsValid = (std::get<11>(_SignalStateTuple.first) & 4) > 0; Info.StateJustGotValid = (std::get<11>(_SignalStateTuple.first) & 2) > 0; Info.StateIsValidAfterReentrance = (std::get<11>(_SignalStateTuple.first) & 1) > 0; SignalStateInfos.push_back(Info); } SystemStateInformation SystemStateInfo = SysSD->detectSystemState(SignalStateInfos); OutString << SystemStateInfo.StateID << ","; OutString << SystemStateInfo.ConfidenceStateIsValid << ","; OutString << SystemStateInfo.ConfidenceStateIsInvalid << ","; OutString << SystemStateInfo.ConfidenceOfInputsMatchingState << ","; OutString << SystemStateInfo.ConfidenceOfInputsMismatchingState << ","; OutString << SystemStateInfo.ConfidenceOfOutputsMatchingState << ","; OutString << SystemStateInfo.ConfidenceOfOutputsMismatchingState << ","; OutString << SystemStateInfo.StateCondition << ","; OutString << SystemStateInfo.ConfidenceSystemIsFunctioning << ","; OutString << SystemStateInfo.ConfidenceSystemIsMalfunctioning << ","; OutString << SystemStateInfo.ConfidenceOfAllDecisions << ","; return ret(std::make_tuple(OutString.str())); } }; using arr = std::vector>; template AgentHandle createSystemStateDetectorAgent( - std::unique_ptr &C, const std::string &Name, + std::unique_ptr &C, const std::string &Name, std::shared_ptr> BrokenDelayFunction, std::shared_ptr> OkDelayFunction) { LOG_TRACE("Creating fixed SystemStateDetectorAgent"); using Input = SignalStateTuple; using Result = Optional; std::shared_ptr< SystemStateDetector> _SysSD( new SystemStateDetector( std::numeric_limits::max(), NumOfSlaves, BrokenDelayFunction, OkDelayFunction)); SysSD = _SysSD; auto HandlerFunction = Handler, arr>, Input>::function; return C->createAgent(Name, std::function(HandlerFunction)); } AgentHandle createSystemStateDetectorAgent( - std::unique_ptr &C, const std::string &Name, + std::unique_ptr &C, const std::string &Name, size_t NumOfSlaves, std::shared_ptr> BrokenDelayFunction, std::shared_ptr> OkDelayFunction) { LOG_TRACE("Creating dynamic SystemStateDetectorAgent"); switch (NumOfSlaves) { // clang-format off case 2: return createSystemStateDetectorAgent< 2>(C, Name, BrokenDelayFunction, OkDelayFunction); case 3: return createSystemStateDetectorAgent< 3>(C, Name, BrokenDelayFunction, OkDelayFunction); case 4: return createSystemStateDetectorAgent< 4>(C, Name, BrokenDelayFunction, OkDelayFunction); case 5: return createSystemStateDetectorAgent< 5>(C, Name, BrokenDelayFunction, OkDelayFunction); case 6: return createSystemStateDetectorAgent< 6>(C, Name, BrokenDelayFunction, OkDelayFunction); case 7: return createSystemStateDetectorAgent< 7>(C, Name, BrokenDelayFunction, OkDelayFunction); case 8: return createSystemStateDetectorAgent< 8>(C, Name, BrokenDelayFunction, OkDelayFunction); case 9: return createSystemStateDetectorAgent< 9>(C, Name, BrokenDelayFunction, OkDelayFunction); case 10: return createSystemStateDetectorAgent<10>(C, Name, BrokenDelayFunction, OkDelayFunction); case 11: return createSystemStateDetectorAgent<11>(C, Name, BrokenDelayFunction, OkDelayFunction); case 12: return createSystemStateDetectorAgent<12>(C, Name, BrokenDelayFunction, OkDelayFunction); case 13: return createSystemStateDetectorAgent<13>(C, Name, BrokenDelayFunction, OkDelayFunction); case 14: return createSystemStateDetectorAgent<14>(C, Name, BrokenDelayFunction, OkDelayFunction); case 15: return createSystemStateDetectorAgent<15>(C, Name, BrokenDelayFunction, OkDelayFunction); case 16: return createSystemStateDetectorAgent<16>(C, Name, BrokenDelayFunction, OkDelayFunction); case 17: return createSystemStateDetectorAgent<17>(C, Name, BrokenDelayFunction, OkDelayFunction); case 18: return createSystemStateDetectorAgent<18>(C, Name, BrokenDelayFunction, OkDelayFunction); case 19: return createSystemStateDetectorAgent<19>(C, Name, BrokenDelayFunction, OkDelayFunction); case 20: return createSystemStateDetectorAgent<20>(C, Name, BrokenDelayFunction, OkDelayFunction); case 21: return createSystemStateDetectorAgent<21>(C, Name, BrokenDelayFunction, OkDelayFunction); case 22: return createSystemStateDetectorAgent<22>(C, Name, BrokenDelayFunction, OkDelayFunction); case 23: return createSystemStateDetectorAgent<23>(C, Name, BrokenDelayFunction, OkDelayFunction); case 24: return createSystemStateDetectorAgent<24>(C, Name, BrokenDelayFunction, OkDelayFunction); case 25: return createSystemStateDetectorAgent<25>(C, Name, BrokenDelayFunction, OkDelayFunction); case 1: default: return createSystemStateDetectorAgent<1>(C, Name, BrokenDelayFunction, OkDelayFunction); // clang-format on } } #endif // STATEHANDLERUTILS_H diff --git a/apps/sa-ews1/CMakeLists.txt b/apps/sa-ews1/CMakeLists.txt index b26026f..1e2a6a9 100644 --- a/apps/sa-ews1/CMakeLists.txt +++ b/apps/sa-ews1/CMakeLists.txt @@ -1,4 +1,4 @@ ROSA_add_app(sa-ews1 sa-ews1.cpp) ROSA_add_library_dependencies(sa-ews1 ROSAConfig) -ROSA_add_library_dependencies(sa-ews1 ROSADeluxe) +ROSA_add_library_dependencies(sa-ews1 ROSAApp) ROSA_add_library_dependencies(sa-ews1 ROSAAgent) diff --git a/apps/sa-ews1/sa-ews1.cpp b/apps/sa-ews1/sa-ews1.cpp index e137d8e..0433e43 100644 --- a/apps/sa-ews1/sa-ews1.cpp +++ b/apps/sa-ews1/sa-ews1.cpp @@ -1,324 +1,326 @@ //===-- apps/sa-ews1/sa-ews1.cpp --------------------------------*- C++ -*-===// // // The RoSA Framework -- Application SA-EWS1 // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file apps/sa-ews1/sa-ews1.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// /// \brief The application SA-EWS1 implements the case study from the paper: /// M. Götzinger, N. Taherinejad, A. M. Rahmani, P. Liljeberg, A. Jantsch, and /// H. Tenhunen: Enhancing the Early Warning Score System Using Data Confidence /// DOI: 10.1007/978-3-319-58877-3_12 //===----------------------------------------------------------------------===// #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Confidence.hpp" #include "rosa/config/version.h" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" #include using namespace rosa; using namespace rosa::agent; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; const std::string AppName = "SA-EWS1"; /// Paths for the CSV files for simulation. /// ///@{ const std::string HRCSVPath = "HR.csv"; const std::string BRCSVPath = "BR.csv"; const std::string SpO2CSVPath = "SpO2.csv"; const std::string BPSysCSVPath = "BPSys.csv"; const std::string BodyTempCSVPath = "BodyTemp.csv"; const std::string ScoreCSVPath = "Score.csv"; ///@} /// How many cycles of simulation to perform. const size_t NumberOfSimulationCycles = 16; /// Warning levels for abstraction. enum WarningScore { No = 0, Low = 1, High = 2, Emergency = 3 }; -/// Helper function creating a deluxe agent for pre-processing sensory values. +/// Helper function creating an application agent for pre-processing sensory +/// values. /// /// Received values are first validated for confidence. Values which the /// validator does not mark confident are ignored. Confident values are /// abstracted into a \c WarningScore value, which is the result of the /// processing function. /// /// \note The result, \c WarningScore, is returned as \c uint32_t because /// enumeration types are not integrated into built-in types. Hence, a master /// to these agents receives its input as \c uint32_t values, and may cast them /// to \c WarningScore explicitly. /// /// \tparam T type of values to receive from the sensor /// -/// \param C the deluxe context to create the agent in +/// \param App the application to create the agent in /// \param Name name of the new agent /// \param CC confidence validator to use /// \param A abstraction to use /// /// \return handle for the new agent template -AgentHandle createLowLevelAgent(std::unique_ptr &C, +AgentHandle createLowLevelAgent(std::unique_ptr &App, const std::string &Name, const Confidence &CC, const Abstraction &A) { using handler = std::function(std::pair)>; using result = Optional; - return C->createAgent( + return App->createAgent( Name, handler([&, Name](std::pair I) -> result { LOG_INFO_STREAM << "\n******\n" << Name << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; return (I.second && CC(I.first)) ? result(A(I.first)) : result(); })); } int main(void) { LOG_INFO_STREAM << '\n' << library_string() << " -- " << Color::Red << AppName << "app" << Color::Default << '\n' << Color::Yellow << "CSV files are read from and written to the current working directory." << Color::Default << '\n'; - std::unique_ptr C = DeluxeContext::create(AppName); + std::unique_ptr App = Application::create(AppName); // - // Create deluxe sensors. + // Create application 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 HRSensor = C->createSensor("HR Sensor"); - AgentHandle BRSensor = C->createSensor("BR Sensor"); - AgentHandle SpO2Sensor = C->createSensor("SpO2 Sensor"); - AgentHandle BPSysSensor = C->createSensor("BPSys Sensor"); - AgentHandle BodyTempSensor = C->createSensor("BodyTemp Sensor"); + AgentHandle HRSensor = App->createSensor("HR Sensor"); + AgentHandle BRSensor = App->createSensor("BR Sensor"); + AgentHandle SpO2Sensor = App->createSensor("SpO2 Sensor"); + AgentHandle BPSysSensor = App->createSensor("BPSys Sensor"); + AgentHandle BodyTempSensor = App->createSensor("BodyTemp Sensor"); // // Create functionalities. // LOG_INFO("Creating Functionalities for Agents."); // // Define confidence validators. // // Lower bounds are inclusive and upper bounds are exclusive. Confidence HRConfidence(0, 501); Confidence BRConfidence(0, 301); Confidence SpO2Confidence(0, 101); Confidence BPSysConfidence(0,501); Confidence BodyTempConfidence(-60, nextRepresentableFloatingPoint(50.0f)); // // Define abstractions. // RangeAbstraction HRAbstraction( {{{0, 40}, Emergency}, {{40, 51}, High}, {{51, 60}, Low}, {{60, 100}, No}, {{100, 110}, Low}, {{110, 129}, High}, {{129, 200}, Emergency}}, Emergency); RangeAbstraction BRAbstraction({{{0, 9}, High}, {{9, 14}, No}, {{14, 20}, Low}, {{20, 29}, High}, {{29, 50}, Emergency}}, Emergency); RangeAbstraction SpO2Abstraction({{{1, 85}, Emergency}, {{85, 90}, High}, {{90, 95}, Low}, {{95, 100}, No}}, Emergency); RangeAbstraction BPSysAbstraction( {{{0, 70}, Emergency}, {{70, 81}, High}, {{81, 101}, Low}, {{101, 149}, No}, {{149, 169}, Low}, {{169, 179}, High}, {{179, 200}, Emergency}}, Emergency); RangeAbstraction BodyTempAbstraction( {{{0.f, 28.f}, Emergency}, {{28.f, 32.f}, High}, {{32.f, 35.f}, Low}, {{35.f, 38.f}, No}, {{38.f, 39.5f}, High}, {{39.5f, 100.f}, Emergency}}, Emergency); // - // Create low-level deluxe agents with \c createLowLevelAgent. + // Create low-level application agents with \c createLowLevelAgent. // LOG_INFO("Creating low-level agents."); AgentHandle HRAgent = - createLowLevelAgent(C, "HR Agent", HRConfidence, HRAbstraction); + createLowLevelAgent(App, "HR Agent", HRConfidence, HRAbstraction); AgentHandle BRAgent = - createLowLevelAgent(C, "BR Agent", BRConfidence, BRAbstraction); + createLowLevelAgent(App, "BR Agent", BRConfidence, BRAbstraction); AgentHandle SpO2Agent = - createLowLevelAgent(C, "SpO2 Agent", SpO2Confidence, SpO2Abstraction); - AgentHandle BPSysAgent = - createLowLevelAgent(C, "BPSys Agent", BPSysConfidence, BPSysAbstraction); + createLowLevelAgent(App, "SpO2 Agent", SpO2Confidence, SpO2Abstraction); + AgentHandle BPSysAgent = createLowLevelAgent( + App, "BPSys Agent", BPSysConfidence, BPSysAbstraction); AgentHandle BodyTempAgent = createLowLevelAgent( - C, "BodyTemp Agent", BodyTempConfidence, BodyTempAbstraction); + App, "BodyTemp Agent", BodyTempConfidence, BodyTempAbstraction); // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); - C->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel"); - C->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel"); - C->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel"); - C->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel"); - C->connectSensor(BodyTempAgent, 0, BodyTempSensor, "BodyTemp Sensor Channel"); + App->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel"); + App->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel"); + App->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel"); + App->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel"); + App->connectSensor(BodyTempAgent, 0, BodyTempSensor, + "BodyTemp Sensor Channel"); // - // Create a high-level deluxe agent. + // Create a high-level application agent. // LOG_INFO("Create high-level agent."); // The new agent logs its input values and results in the the sum of them. - AgentHandle BodyAgent = C->createAgent( + AgentHandle BodyAgent = App->createAgent( "Body Agent", std::function( std::pair, std::pair, std::pair, std::pair, std::pair)>( [](std::pair HR, std::pair BR, std::pair SpO2, std::pair BPSys, std::pair BodyTemp) -> Optional { LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n" << (HR.second ? "" : "") << " HR warning score: " << HR.first << "\n" << (BR.second ? "" : "") << " BR warning score: " << BR.first << "\n" << (SpO2.second ? "" : "") << " SpO2 warning score: " << SpO2.first << "\n" << (BPSys.second ? "" : "") << " BPSys warning score: " << BPSys.first << "\n" << (BodyTemp.second ? "" : "") << " BodyTemp warning score: " << BodyTemp.first << "\n******\n"; return {HR.first + BR.first + SpO2.first + BPSys.first + BodyTemp.first}; })); // // Connect low-level agents to the high-level agent. // LOG_INFO("Connect low-level agents to the high-level agent."); - C->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel"); - C->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel"); - C->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel"); - C->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel"); - C->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel"); + App->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel"); + App->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel"); + App->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel"); + App->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel"); + App->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel"); // // For simulation output, create a logger agent writing the output of the // high-level agent into a CSV file. // LOG_INFO("Create a logger agent."); // Create CSV writer. std::ofstream ScoreCSV(ScoreCSVPath); csv::CSVWriter ScoreWriter(ScoreCSV); // The agent writes each new input value into a CSV file and produces nothing. - AgentHandle LoggerAgent = C->createAgent( + AgentHandle LoggerAgent = App->createAgent( "Logger Agent", std::function(std::pair)>( [&ScoreWriter](std::pair Score) -> Optional { if (Score.second) { // The state of \p ScoreWriter is not checked, expecting good. ScoreWriter << Score.first; } 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, BodyAgent, "Body Agent Channel"); + App->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel"); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // - // Initialize deluxe context for simulation. + // Initialize application for simulation. // - C->initializeSimulation(); + App->initializeSimulation(); // // Open CSV files and register them for their corresponding sensors. // // Type aliases for iterators. using CSVInt = csv::CSVIterator; using CSVFloat = csv::CSVIterator; std::ifstream HRCSV(HRCSVPath); - C->registerSensorValues(HRSensor, CSVInt(HRCSV), CSVInt()); + App->registerSensorValues(HRSensor, CSVInt(HRCSV), CSVInt()); std::ifstream BRCSV(BRCSVPath); - C->registerSensorValues(BRSensor, CSVInt(BRCSV), CSVInt()); + App->registerSensorValues(BRSensor, CSVInt(BRCSV), CSVInt()); std::ifstream SpO2CSV(SpO2CSVPath); - C->registerSensorValues(SpO2Sensor, CSVInt(SpO2CSV), CSVInt()); + App->registerSensorValues(SpO2Sensor, CSVInt(SpO2CSV), CSVInt()); std::ifstream BPSysCSV(BPSysCSVPath); - C->registerSensorValues(BPSysSensor, CSVInt(BPSysCSV), CSVInt()); + App->registerSensorValues(BPSysSensor, CSVInt(BPSysCSV), CSVInt()); std::ifstream BodyTempCSV(BodyTempCSVPath); - C->registerSensorValues(BodyTempSensor, CSVFloat(BodyTempCSV), CSVFloat()); + App->registerSensorValues(BodyTempSensor, CSVFloat(BodyTempCSV), CSVFloat()); // // Simulate. // - C->simulate(NumberOfSimulationCycles); + App->simulate(NumberOfSimulationCycles); return 0; } diff --git a/docs/Design.rst b/docs/Design.rst index 4f07a0f..7c93566 100644 --- a/docs/Design.rst +++ b/docs/Design.rst @@ -1,119 +1,119 @@ =============== Design Overview =============== Last updated: 2019-11-27 TODO: - Add cross references to relevant parts of the documentation and external links (e.g., relevant papers or source of info) .. contents:: :local: Principles ========== The main priorities for the design of the software implementation are #. providing a high-level, easy-to-use but safe interface for application developers; #. allowing the same application code to be used for *simulation* and *deployment*; #. realizing small-footprint software that can be deployed in resource-constrained embedded devices. The RoSA software framework, is implemented in C++. The language allows defining high-level but lightweight interfaces with flexibility in the realization. The framework heavily utilizes templates, template metaprogramming, and constant expressions to let the compiler generate optimized code. We also encode dynamically-relevant static information into a custom format so that RoSA supports message passing with flexibility and minimal resource need --- without the dynamic overhead of C++ RTTI. Performing message passing and data manipulation is decoupled from the agent interface. The implementation of the runtime system is easily switched behind the declarative definition of agent-based applications. Running an application in different modes (e.g., simulation and deployment) is a matter of static configuration. Simulation is the execution of the application on a computer with sensor and actuator agents associated to input and output streams, respectively. Those sensor and actuator agents may interface actual sensors and actuators with custom C++ code when deployed in an embedded device. Case studies have been dony in simulation; support for deployment requires further development effort to complete the corresponding runtime implementation. The framework is being coded in standard C++. The only exceptions are some OS-specific code snippets within debugging and simulation facilities. The software can readily be deployed to all devices that are supported by a modern C++ compiler. Software Modules ================ The software implementation consists of four main modules: `Support` provides general debugging, logging, typing, and I/O facilities, which are used in other modules and application code. `Agent` is a library of self-aware functionalities for defining agents in application code. `Core` defines a minimal agent system with message passing capabilities and runtime system implementations. -`Deluxe` +`App` provides an interface that matches the RoSA Architecture and utilizes RoSA Core. -The RoSA Deluxe interface wraps the general agent interface of RoSA Core. -RoSA Deluxe agents are defined by functions that take their input messages as parameters and provide their output messages as return values. +The RoSA App interface wraps the general agent interface of RoSA Core. +RoSA App agents are defined by functions that take their input messages as parameters and provide their output messages as return values. The implementation takes care of handling messages --- minimizing boilerplate in application code --- and may perform static and dynamic checks to ensure operating conditions. Agents and Agent Systems ------------------------ RoSA Core defines the means for agents to receive and send messages. Messages are statically-typed tuples of basic types. An agent is defined as a list of message handler functions. An incoming message is handled by the first handler that can take the message as actual parameter. The handler may generate output messages via RoSA API calls. -RoSA Deluxe agents build on RoSA Core agents and provide a higher abstraction level by hiding message passing. +RoSA App agents build on RoSA Core agents and provide a higher abstraction level for applications by hiding message passing. Each agent is owned by a *system*. Systems can instantiate agents and provide the actual implementation for execution: channels --- for message passing --- and control --- for triggering data manipulation. RoSA Core allows message passing between arbitrary agents within a system. -The RoSA Deluxe interface enforces a hierarchical structure with master-slave relations. +The RoSA App interface enforces a hierarchical structure with master-slave relations. A RoSA application is an agent system. -The Deluxe module allows implementing a system as a set of agent definitions and declarative description of their connections. +The App module allows implementing an application system as a set of agent definitions and declarative description of their connections. Execution Model --------------- How an application (i.e., agent system) is executed depends on the system implementation. The implementation of the system --- channel and control facilities --- is decoupled from the definition of an application --- agents and their connections within a system. RoSA Core allows swapping the system implementation for any application as a configuration option or by changing one line of application code. The current system implementation is based on Models of Computations (MoCs). We use the untimed MoC and are prepared for the discrete-timed MoC when time aspects have to be represented. The concepts of the agent-based approach are easily mapped to the formal MoCs. =================== =========== Agent-based concept MoC concept =================== =========== Agent Process Channel Signal Message Event =================== =========== A RoSA agent system --- mapping to a process network --- can be analysed in the formal model. Building and Running Applications --------------------------------- RoSA has a CMake build project, which allows using the framework in different development environments. The build project defines compile-time options to disable or tune features statically (e.g., logging, debugging, and tracing facilities). Disabling unnecessary features improves the efficiency of compiled framework code in particular uses. A RoSA application and framework modules are linked into one executable, which allows exploiting link-time optimization possibilities (optimizing framework code for application need, removing unused framework code, etc.). The RoSA runtime system is a thin layer between the self-aware application and the underlying system; still it fulfills important responsibilities. The runtime system initializes the application by instantiating an agent system, performs message passing, and triggers data manipulation in agents. I/O and monitoring features are also provided by RoSA. The application code is not bloated with system-level bookkeeping and developers can focus on details of self-awareness. diff --git a/docs/Dev.rst b/docs/Dev.rst index f4bdda9..c5e2ada 100755 --- a/docs/Dev.rst +++ b/docs/Dev.rst @@ -1,387 +1,387 @@ ============================= Developing the RoSA Framework ============================= .. contents:: :local: This document provides information that might be useful for contributing to RoSA. Please also consult :doc:`Build`. .. _Dev_Source_Directory: The Source Directory ==================== The source directory consists of the following subdirectories: `cmake` Contains files used for configuring the `CMake Project`_. `docs` Contains `Documentation`_-related files. `examples` Contains `Examples`_ on using the public API. `include/rosa` Contains the RoSA public API -- that is the interface of RoSA `Libraries`_. The directory `include` is to be used as include directory and RoSA header files are to be included in C++ sources as `"rosa/"`. `lib` Contains the implementation of the RoSA public API -- that is the implementation of RoSA `Libraries`_. `apps` Contains `Apps`_ based on RoSA features. `tools` Contains `Tools`_ based on RoSA features. `modules` Contains third-party `Modules`_ that are not part of RoSA but used by `Apps`_ Software Sources ================ The section describes the `Logical Structure`_ of the software sources and what `Coding Standards`_ are supposed to be followed for the implementation. Logical Structure ----------------- Various features provided by RoSA are sorted into different `Libraries`_. `Examples`_ , `Apps`_, and `Tools`_ using those `Libraries`_ are separated from the implementation of the RoSA features into different directories. `Examples`_ , `Apps`_, and `Tools`_ may also use third-party libraries, called `Modules`_. Libraries ~~~~~~~~~ The framework consists of separate libraries providing different features. The public interfaces for RoSA libraries are defined in `include/rosa`, while corresponding implementation is in `lib`. Each library has its own subdirectory in the mentioned directories. RoSA provides the following libraries: `config` Provides information on the configuration used to build the framework, e.g., version number, log level, assertions, and debugging. `support` Provides general features -- template metaprograms dealing with types, for instance -- for implementing other libraries. `core` Provides the basic RoSA features, like systems managing agents passing messages. `agent` Provides features to be used for implementing agents. -`deluxe` - Provides a somewhat more modular interface for defining systems with RoSA. +`app` + Provides a modular interface for defining applications with RoSA. .. _Library_Dependencies: Dependencies '''''''''''' The following table summarizes dependencies among libraries. A marking in a row denotes that the library in the beginning of the row depends on the library in the head of the given column. -+---------+--------+---------+------+--------+-------+ -| | config | support | core | deluxe | agent | -+=========+========+=========+======+========+=======+ -| config | | | | | | -+---------+--------+---------+------+--------+-------+ -| support | | | | | | -+---------+--------+---------+------+--------+-------+ -| core | | × | | | | -+---------+--------+---------+------+--------+-------+ -| deluxe | | | × | | | -+---------+--------+---------+------+--------+-------+ -| agent | | | | | | -+---------+--------+---------+------+--------+-------+ ++---------+--------+---------+------+-----+-------+ +| | config | support | core | app | agent | ++=========+========+=========+======+=====+=======+ +| config | | | | | | ++---------+--------+---------+------+-----+-------+ +| support | | | | | | ++---------+--------+---------+------+-----+-------+ +| core | | × | | | | ++---------+--------+---------+------+-----+-------+ +| app | | | × | | | ++---------+--------+---------+------+-----+-------+ +| agent | | | | | | ++---------+--------+---------+------+-----+-------+ Examples ~~~~~~~~ Some simple samples are provided in `examples` to demonstrate how to to use different parts of the RoSA API. Apps ~~~~ Apps, actual applications based on the RoSA libraries, are implemented in `apps`. Tools ~~~~~ Tools, programs based on the RoSA libraries and providing standalone functionalities, are implemented in `tools`. Modules ~~~~~~~ This directory contains third-party modules that can be used inside RoSA. These include: * cxxopts: https://github.com/jarro2783/cxxopts Example usage can be seen in modules/cxxopts/src/example.cpp .. _Coding_Standards: Coding Standards ---------------- RoSA is implemented in standard *C++17* code. All the software sources are to be written in accordance to the `LLVM Coding Standards`_. .. _nortti-noexceptions: Feature Restrictions ~~~~~~~~~~~~~~~~~~~~ Pay attention `not to use RTTI and Exceptions`_. Those features are disabled in the CMake project. Documentation Comments ~~~~~~~~~~~~~~~~~~~~~~ It is important to remember to document source code using `doxygen comments`_ as `API Documentation`_ is generated directly from sources. Note that the syntax of documentation comments is checked during compilation -- at least when using a GCC-compatible compiler. Further, check :ref:`Doxygen warnings ` as issues not being detected by the compiler may be found when actually generating the documentation. Whenever you work on a source file, make sure your name is in the author-list defined in the header comment of the file. Each author should be defined with a separate `\\author` command so that recent authors come first. Authors not participating in further development of a file anymore may be marked with the period of their contribution. If declarations belonging to a namespace are spread to more than one source files, document the namespace in a separate `namespace.h` in the directory belonging to the library. Otherwise, document the namespace in the only file in which entities of the namespace are declared. Header Files ~~~~~~~~~~~~ Follow the recommendations on public and private header files and the usage of `#include` from the `LLVM Coding Standards`_. Use `.h` and `.hpp` extensions to indicate the content of the header file: * header files containing any *definition* -- template or inline definition -- or including another header file with `.hpp` extension have `.hpp` extension; * header files containing only *declarations* and including only header files with `.h` extension have `.h` extension. It may happen that a header file does not need any corresponding implementation in a `.cpp` file. Nevertheless, do create a corresponding `.cpp` file which only includes the header file in this case. That makes sure that the header file is compiled and hence checked for errors, and also a corresponding entry in the compilation database is generated. Checking and Enforcing the Coding Standards ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The tools `clang-tidy `_ and `clang-format `_ can be used to check and enforce the coding standards. The two tools are integrated into the CMake project, refer to CMake variables :ref:`ROSA_ENABLE_CLANG_TIDY ` and :ref:`ROSA_INCLUDE_CLANG_FORMAT `. Note that there may be situations when `clang-tidy` checks result in false positives -- for example, for some cases of the order of `#include` directives. One can order `clang-tidy` to suppress warnings for a line of code by marking that line with:: // NOLINT It may be preferred to diverge from the standard formatting -- for example for the sake of readability of static definition of arrays following some structure. One can disable `clang-format` for some lines of code by designating a range with two special comments as:: // clang-format off ... clang-format is disabled here ... // clang-format on Documentation ============= The RoSA Framework is delivered with two kinds of documentation: `General Documentation`_ and `API Documentation`_, generation of both of which is integrated into the CMake project. References between the two documentations are relative addresses corresponding to the directory structure of the :ref:`generated documentation `. General Documentation --------------------- General documentation is written as `reStructuredText `_ compiled with `Sphinx `_. For build integration, refer to the CMake variable :ref:`ROSA_ENABLE_SPHINX `. Documentation files are located in `docs` with extension `.rst`. The main page of the documentation is `docs/index.rst`. Configuration for building the documentation is `docs/conf.py`. The directory `docs/CommandGuide` contains documentation for each separate tool. Those pages are included in the HTML documentation via `docs/CommandGuide/index.rst`. Moreover, man pages can be generated from those tool documentation pages. API Documentation ----------------- API documentation is directly generated from sources with `Doxygen `_. For build integration, refer to the CMake variable :ref:`ROSA_ENABLE_DOXYGEN `. The main page used for the API documentation is `docs/doxygen-mainpage.dox`. Configuration for generating the API documentation is `docs/doxygen.cfg.in`. .. _CMake Project: Managing the CMake Project ========================== This section briefly summarizes when and how to modify CMake files during the development process. No general discussion on CMake features is provided here. When modifying `Documentation`_, no need to update the CMake files. Software -------- One needs to modify the CMake files only if source files are to be added or removed from the project. Here follows some typical scenarios. Source Files ~~~~~~~~~~~~ Each library and executable target has its own directory and its own definition as a file called `CMakeLists.txt` in that directory. When adding or removing a source file -- both headers and `.cpp` files -- to a library or executable, locate the corresponding `CMakeLists.txt` file. The file is typically in the same directory where the file to be added or removed is located. Except for header files of the public API, for which the corresponding CMake target is defined in a `lib` subdirectory corresponding to the library the header files belongs to. Update the source list in the argument of the `add_library` or `add_executable` command in the `CMakeLists.txt`, for libraries and executables, respectively. A library and executable may use features provided by another library. Such a dependency is to be defined in the `CMakeLists.txt` file of the dependent target by using the `ROSA_add_library_dependencies` command. CMake Libraries ~~~~~~~~~~~~~~~ When adding or removing a library, add or remove the corresponding directories from `include` and `lib`. If you have already had generated a build project with CMake, `touch` [#]_ `lib/CMakeLists.txt` to make CMake rescan subdirectories on next build. When defining a new library, the new subdirectory under `lib` needs to contain a `CMakeLists.txt`, which needs to contain at least an `add_library` command defining the name of the library and the source files belonging to it. CMake Executables ~~~~~~~~~~~~~~~~~ When adding or removing an executable, add or remove the corresponding directory from `apps`, `examples`, or `tools`. If you have already had generated a build project with CMake, `touch` `CMakeLists.txt` in the containing directory (like in the case of libraries) to make CMake rescan subdirectories on next build. When defining a new executable, the new subdirectory needs to contain a `CMakeLists.txt`, which needs to contain at least an `add_executable` command defining the name of the executable and the source files belonging to it. .. _Dev Managing Sources: Managing Sources ================ Consider the followings before committing changes to the repository: * your code complies with the `Coding Standards`_ as much as possible; * your code is well documented; * your code is not bloated with unusued code and/or comments; * your changes do not break building and executing the framework: * test all of the supported platforms if possible, * look into the generated documentation if you have edited `General Documentation`_; * you do not pollute the repository with unused and generated files. When committing changes to the repository, provide a concise log message with your commit. Miscellaneous Concerns ====================== Using YCM --------- If you happen to use `YCM `_, just make a copy of the provided `ycm_extra_conf.py.template` file as `.ycm_extra_conf.py` in the RoSA source directory, and set the following two variables in it: `compilation_database_folder` the absolute path of your build directory `extra_system_include_dirs` any system include directory which might not be searched by `libclang` [#]_. You probably want compile with Clang if you use YCM, so run CMake with environment variables `CC=clang` and `CXX=clang++` set. Also note that header files in the `include` directory are compiled for YCM with the compiler flags of a corresponding source file in the `lib` directory, if any. Header files in other locations are supposed to have a corresponding source file in the same directory. Notes ~~~~~ * If the project's include directory (`include/rosa`) would ever be changed, then the YCM configuration file needs to be adjusted accordingly. .. rubric:: Footnotes .. [#] Set the last modified time of the file to the current time. .. [#] See: https://github.com/Valloric/YouCompleteMe/issues/303; use the following command to figure out the used system directories: echo | clang -std=c++11 -v -E -x c++ - .. _`LLVM Coding Standards`: http://llvm.org/docs/CodingStandards.html .. _`not to use RTTI and Exceptions`: http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-exceptions .. _`doxygen comments`: http://llvm.org/docs/CodingStandards.html#doxygen-use-in-documentation-comments diff --git a/docs/Issues.rst b/docs/Issues.rst index c873116..5cad604 100755 --- a/docs/Issues.rst +++ b/docs/Issues.rst @@ -1,52 +1,53 @@ ================================================================== Known Issues with the Current Implementation of the RoSA Framework ================================================================== .. contents:: :local: TODO ==== * Project logo - `docs/_themes/rosa-theme/static/logo.png` * Packaging with `CPack `_. * What about design documentation on the basics of RoSA? * What about testing the framework? Known Issues ============ The issues that are listed below are described assuming :ref:`minimal build dependencies ` are met. * C++ * The noexcept-specification is part of the function type since C++17 but `std::function` is not defined for noexcept template arguments. So we cannot enforce the expected noexcept semantics for functions stored in `std::function`. See affected functions - `rosa::Invoker::wrap()`, `rosa::deluxe::DeluxeAgent::DeluxeAgent()`, - `rosa::deluxe::DeluxeSensor::DeluxeSensor()`, and - `rosa::deluxe::DeluxeSensor::registerSimulationDataSource()`. + `rosa::Invoker::wrap()`, `rosa::app::AppAgent::AppAgent()`, + `rosa::app::AppSensor::AppSensor()`, and + `rosa::app::AppSensor::registerSimulationDataSource()`. * MSVC * While :ref:`RoSA does not use exceptions `, we cannot disable unwind semantics with MSVC because some included header files define functions that use exceptions. * Doxygen * "Potential recursive class relation" is detected for `rosa::GenSeq`, which is true if one ignores the template specialization for the terminal case. It would be nice not to have this pointless warning. * clang-tidy * Clang-tidy reports warnings about `noexcept` marking for the move constructor and move assignment operator of `rosa::Optional` in some situations when the template with the non-specialized argument list is used - -- for example, in the file `example/deluxe-interface/deluxe-interface.cpp`. + -- for example, in the file + `example/application-interface/application-interface.cpp`. However, the condition for the `noexcept` marking should be met and the warning is pointless. diff --git a/examples/CSVFiles/CMakeLists.txt b/examples/CSVFiles/CMakeLists.txt index cfc92e7..7bb38a4 100644 --- a/examples/CSVFiles/CMakeLists.txt +++ b/examples/CSVFiles/CMakeLists.txt @@ -1,3 +1,3 @@ add_executable(csvfiles main.cpp) ROSA_add_library_dependencies(csvfiles ROSAConfig) -ROSA_add_library_dependencies(csvfiles ROSADeluxe) +ROSA_add_library_dependencies(csvfiles ROSAApp) diff --git a/examples/CSVFiles/main.cpp b/examples/CSVFiles/main.cpp index 12b4e61..b010a0a 100644 --- a/examples/CSVFiles/main.cpp +++ b/examples/CSVFiles/main.cpp @@ -1,358 +1,358 @@ -//===-- examples/CSVFiles/main.cpp ------------------*- C++ -*-===// +//===-- examples/CSVFiles/main.cpp ------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file examples/basic-system/basic-system.cpp /// /// \author Edwin Willegger (edwin.willegger@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \brief A simple example on the basic \c rosa::csv, \c rosa::iterator and /// \c rosa::writer classes. Focus is on the tuple impementations. /// //===----------------------------------------------------------------------===// #include #include #include #include #include #include #include #include #include #include #include #include // includes for an complete example to read and write // with sensors and agents. -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include "rosa/config/version.h" // includes to test the basic functionality // to read and write tuples. #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" #include "rosa/support/iterator/split_tuple_iterator.hpp" #include "rosa/support/writer/split_tuple_writer.hpp" /// the name of the example const std::string ExampleName = "csvfiles"; /// How many cycles of simulation to perform. const size_t NumberOfSimulationCycles = 10; /// Paths for the CSV files for simulation. /// input csv files const std::string csvPath = "../examples/CSVFiles/"; const std::string csvFileWithHeader = csvPath + "HR-New.csv"; const std::string csvFileNoHeader = csvPath + "HR.csv"; const std::string csvFileHeaderSemi = csvPath + "HR-New-Semicolon.csv"; /// output csv files const std::string csvFileWriteHea = csvPath + "csvwriter_noheader.csv"; const std::string csvFileWriteNoHeaSplit = csvPath + "csvSplitwriter_noheader.csv"; using namespace rosa; /// /// This function tests the basic CSVIterator capablities, and shows you /// how you could work with this class. /// void testtupleCSVReader(void){ //different streams to get the csv data out of the files //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data(csvFileWithHeader); //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data_2(csvFileWithHeader); //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data_3(csvFileWithHeader); //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data_4(csvFileWithHeader); //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data_5(csvFileWithHeader); //file contains header and valid data entries, delimter = ',' std::ifstream file_header_data_6(csvFileWithHeader); //file contains no header an valid data entries, delimter = ',' std::ifstream file2(csvFileNoHeader); //file contains header and valid data entries, delimter = ';' std::ifstream file3(csvFileHeaderSemi); csv::CSVIterator it(file_header_data); it.setDelimiter(','); (void)++it; (void)++it; //if you iterate over the end of file, the last values //of the file will remain in the data structure but no //error occurs. (void)++it; (void)++it; //------------------------------------------------------------------- // a possiblity to get the data out of the iterator std::tuple value = *it; // // Show the value of one iterator // LOG_INFO( "Values are: "); LOG_INFO(std::get<0>(value) ); LOG_INFO(std::get<1>(value) ); //-------------------------------------------------------------------- //testing differnet parameters to the constructor //uncomment to see that it is not possible to iterate over an vector in the tuple. //rosa::csv::CSVIterator> it2(file, 1); //try to skip a valid number of lines after the header csv::CSVIterator it2_0(file_header_data_2, 1); //try to skip a valid number of lines after the header, but you assume that the file has no header //uncomment this line to crash the programm //csv::CSVIterator it2_1(file_header_data_3, 0, csv::HeaderInformation::HasNoHeader); //try to skip a valid number of lines after the header, but you assume that the file has no header //uncomment this line to crash the program //csv::CSVIterator it2_2(file_header_data_4, 1, csv::HeaderInformation::HasNoHeader); //try to skip a valid number of lines of a file without header csv::CSVIterator it2_3(file2, 1, csv::HeaderInformation::HasNoHeader); //try to skip a valid number of lines after the header, but with different delimiter csv::CSVIterator it2_4(file3, 2, csv::HeaderInformation::HasHeader, ';'); // if you skip more lines than valid, you generate an infinte loop //csv::CSVIterator it3(file_header_data_5, 500); //if you don't need data from all columns just select the number of columns you //need. You get the data back from the first column (index 0) to the fourth column //all values from the fifth column are ignored. csv::CSVIterator it4(file_header_data_6); } /// /// This function tests the basic CSVTupleWriter capablities, and shows you /// how you could work with this class. /// void testtupleCSVWriter(void){ // // Create output writer with an file // std::ofstream file_header_out(csvFileWriteHea); csv::CSVTupleWriter wri(file_header_out); // // Create test tuples // std::tuple values(5, 8.3f, "hallo"); std::tuple values2(3, 8.3f, "end"); // // Create test header lines for the test tuples // std::array header{ {"zero column", "first column", "second column"}}; std::array headerWrong{ {"zero column", "first column", "second column", "third column"}}; std::array headerWrongShort{ {"zero column", "first column"}}; //if you uncomment this line than it would be possible for you to write the header into the stream //in the next line. //wri.write(values); wri.writeHeader(header); wri.write(values); wri.write(values); // it is not possible to write an additional header into the stream. wri.writeHeader(header); wri.write(values); wri << values; wri << values2; //uncomment this line to see, that you can't write a header with the too many elements. //wri.writeHeader(headerWrong); //uncomment this line to see, that you can't write a header with the too few elements. //wri.writeHeader(headerWrongShort); } /// /// This function tests the basic splitTupleIterator capablities, and shows you /// how you could work with this class, this class is used if you want to split /// a CSVIterator in separate parts. /// void testsplitTupleIterator(void) { // - // Create deluxe context + // Create application // - std::unique_ptr C = - deluxe::DeluxeContext::create(ExampleName); + std::unique_ptr App = + app::Application::create(ExampleName); // - // Create deluxe sensors. + // Create application 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. // Three different sensors were created, this is just a random number taken. - AgentHandle Elem0Sensor = C->createSensor("Element1 Sensor"); - AgentHandle Elem1Sensor = C->createSensor("Element2 Sensor"); - AgentHandle Elem2Sensor = C->createSensor("Element3 Sensor"); + AgentHandle Elem0Sensor = App->createSensor("Element1 Sensor"); + AgentHandle Elem1Sensor = App->createSensor("Element2 Sensor"); + AgentHandle Elem2Sensor = App->createSensor("Element3 Sensor"); // - // Initialize deluxe context for simulation. + // Initialize application for simulation. // - C->initializeSimulation(); + App->initializeSimulation(); // Type aliases for iterators using Iterator = rosa::csv::CSVIterator; using IteratorValue = std::tuple; static_assert( std::is_same::value, "Iterator must provide tuples"); // // Open CSV file and register the columns to the corresponding sensors. // std::ifstream TestCSV(csvFileWithHeader); // // Test data looks like: // Element1, Element2, Element3, Element4, Element5 -- is the header line // 3, 5, 8, 9.5, 17 -- first line of values // 100, -8, 30, 18.8, 29 -- other line of values // were also in the file // 5, 20, -100, -200.1, -30 -- if you have less number // of values than simulation rounds all values // -- beyond your last value // will be zero. // get element iterator ranges auto[Elem0Range, Elem1Range, Elem2Range] = iterator::splitTupleIterator(Iterator(TestCSV), Iterator()); // dissect a range into begin and end iterators by structred bindings auto[Elem0Begin, Elem0End] = Elem0Range; // deissect a range with functions auto Elem1Begin = iterator::begin(Elem1Range); auto Elem1End = iterator::end(Elem1Range); - C->registerSensorValues(Elem0Sensor, std::move(Elem0Begin), Elem0End); - C->registerSensorValues(Elem1Sensor, std::move(Elem1Begin), Elem1End); - C->registerSensorValues(Elem2Sensor, std::move(iterator::begin(Elem2Range)), - iterator::end(Elem2Range)); + App->registerSensorValues(Elem0Sensor, std::move(Elem0Begin), Elem0End); + App->registerSensorValues(Elem1Sensor, std::move(Elem1Begin), Elem1End); + App->registerSensorValues(Elem2Sensor, std::move(iterator::begin(Elem2Range)), + iterator::end(Elem2Range)); // // Simulate. // - C->simulate(NumberOfSimulationCycles); + App->simulate(NumberOfSimulationCycles); } /// /// This function tests the basic splitTupleWriter capablities, and shows you /// how you could work with this class, this class is used if you want to split /// a CSVWriter in separate parts. /// void testsplitTupleWriter(void){ // // Create output writer with an file // std::ofstream file_header_out(csvFileWriteNoHeaSplit); csv::CSVTupleWriter wri(file_header_out); // if you omit, the type definition in the template, than auto generated types were used, // and they may not fit to the used CSVTupleWriter. wri << std::make_tuple(1000, 50.6f, "tuple_created"); auto [T0Writer, T1Writer, T2Writer] = writer::splitTupleWriter(std::move(wri), writer::IncompleteTuplePolicy::Ignore); //writing elements in sequential order into the writer classes, but you can write the values into the writers in //a random order. T0Writer << (500); T1Writer << (3.0); T2Writer << "splitted writter"; T2Writer << "splitting is cool"; T0Writer << (-30); T1Writer << (-0.004f); // you can also write more often values into a writer and later into the other writers // all data will be processed correctly into the right order. T0Writer << (1); T0Writer << (2); T1Writer << (-0.4f); T0Writer << (3); T2Writer << "again"; T0Writer << (4); T1Writer << (-0.1f); T1Writer << (-0.2f); T2Writer << "and"; T1Writer << (-0.3f); T2Writer << "splitting"; T2Writer << "once again"; // again writing data of one tuple entry to the different writers in a random fashion. T1Writer << (-0.004f); T2Writer << "splitting is cool"; T0Writer << (-30); } int main(void) { LOG_INFO_STREAM << library_string() << " -- " << terminal::Color::Red << ExampleName << " example" << terminal::Color::Default << '\n'; // // Testing CSVWriter. // LOG_INFO("Testing CSVWriter CSVTupleItrator implementation: "); testtupleCSVWriter(); // // Testing CSVReader. // LOG_INFO("Testing CSVReader CSVTupleIterator implementation: "); testtupleCSVReader(); // // Testing SplitTupleIterator. // LOG_INFO("Testing SplitTupleIterator: "); testsplitTupleIterator(); // // Testing SplitTupleWriter. // LOG_INFO("Testing SplitTupleWriter: "); testsplitTupleWriter(); // // info that user knows programm has finished. // LOG_INFO("All tests finished."); return 0; } diff --git a/examples/agent-functionalities/Reliability-functionality-agent-context/CMakeLists.txt b/examples/agent-functionalities/Reliability-functionality-agent-context/CMakeLists.txt index 4571f33..0b83a62 100644 --- a/examples/agent-functionalities/Reliability-functionality-agent-context/CMakeLists.txt +++ b/examples/agent-functionalities/Reliability-functionality-agent-context/CMakeLists.txt @@ -1,6 +1,6 @@ #add_executable(Reliability-agents Reliability-agents.cpp) #ROSA_add_library_dependencies(Reliability-agents ROSAConfig) #ROSA_add_library_dependencies(Reliability-agents ROSACore) #ROSA_add_library_dependencies(Reliability-agents ROSAAgent) -#ROSA_add_library_dependencies(Reliability-agents ROSADeluxe) +#ROSA_add_library_dependencies(Reliability-agents ROSAApp) diff --git a/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp b/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp index 03c5bef..220505c 100644 --- a/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp +++ b/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp @@ -1,340 +1,340 @@ //===- examples/agent-functionalities/Reliability-functionality.cpp *C++-*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file examples/agent-functionalities/Reliability-functionality.cpp /// /// \author Daniel Schnoell (daniel.schnoell@tuwien.ac.at ) /// /// \date 2019 /// /// \brief A simple example on defining Relianility Functionalities inside a /// master slave context. /// \note This is not finished. and is currently inactive /// //===----------------------------------------------------------------------===// #define Reliability_trace_level 5 #include "rosa/config/version.h" #include "rosa/support/log.h" #include "rosa/agent/CrossReliability.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/Reliability.h" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include #include typedef double SensorValueType; typedef long StateType; typedef double ReliabilityType; #include "./helper.h" // just stuff from Rel-func to increase readability using namespace rosa::agent; using namespace rosa; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; #define NumberOfSimulationCycles 10 // ------------------------------------------------------------------------------- // Bunch of recusive templates to simplify usage // ------------------------------------------------------------------------------- template struct conversion; template class A, typename... TypesB, template class B> struct conversion, B> { using type = typename conversion, std::tuple>::type; }; template class A, typename... TypesB, template class B> struct conversion<0, A, B> { - using type = DeluxeTuple; + using type = AppTuple; }; template using unrolled_data_type = typename conversion, std::tuple<>>::type; //-------------------------------------------------------------------------------- template struct __convert_to_vector { void operator()(std::vector> &feedback, unrolled_data_type I) { __convert_to_vector()(feedback, I); feedback.push_back({std::get(I), std::get(I)}); } }; template struct __convert_to_vector { void operator()(std::vector> &feedback, unrolled_data_type I) { feedback.push_back({std::get<0>(I), std::get<1>(I)}); } }; template void convert_to_vector( std::vector> &feedback, unrolled_data_type I) { __convert_to_vector()(feedback, I); } //---------------------------------------------------------------------------- // template struct unrole_vector {}; // // template v, typename... vT, // template class T, typename... TT, typename... types> // struct unrole_vector,T, types...> { // void operator()(c vec, types... A) { // unrole_vector, T, auto>()(vec, // vec.at(size).score, // vec.at(size).score); // } //}; // --------------------------------------------------------------------------- // main // --------------------------------------------------------------------------- int main(void) { const std::size_t number_of_states = 3; - std::unique_ptr C = DeluxeContext::create("Deluxe"); + std::unique_ptr App = Application::create("App"); //---------------------- Sensors ------------------------------------- //-------------------------------------------------------------------- const std::string SensorName1 = "Sensor1"; const std::string SensorName2 = "Sensor2"; const std::string SensorName3 = "Sensor3"; - AgentHandle Sensor1 = C->createSensor( + AgentHandle Sensor1 = App->createSensor( SensorName1, [&SensorName1](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName1 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); - AgentHandle Sensor2 = C->createSensor( + AgentHandle Sensor2 = App->createSensor( SensorName2, [&SensorName2](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName2 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); - AgentHandle Sensor3 = C->createSensor( + AgentHandle Sensor3 = App->createSensor( SensorName3, [&SensorName3](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName3 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); //------------------------- lowlevel agents -------------------------------- //-------------------------------------------------------------------------- const std::string LowLevelAgentName1 = "LowLevelAgent1"; const std::string LowLevelAgentName2 = "LowLevelAgent2"; const std::string LowLevelAgentName3 = "LowLevelAgent3"; using conf = unrolled_data_type< number_of_states, StateType, ReliabilityType>; // this is the confidence expressed as one tuple it // uses the format // (first.state,first.rel,second.sate...) using LowLevelAgentMasterResult = void; // no return using LowLevelReturnFromMaster = std::pair; using FloatMasterHandler = std::function; - using FloatResult = Optional>; + using FloatResult = Optional>; using FloatHandler = - std::function, bool>)>; + std::function, bool>)>; auto lowlevel1 = create_lowlevel_func(); auto lowlevel2 = create_lowlevel_func(); auto lowlevel3 = create_lowlevel_func(); - AgentHandle SlaveAgent1 = C->createAgent( + AgentHandle SlaveAgent1 = App->createAgent( LowLevelAgentName1, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName1, lowlevel1](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName1 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel1->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName1, lowlevel1]( - std::pair, bool> I) -> FloatResult { + std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName1 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel1->operator()(std::get<0>(I.first)); - DeluxeTuple ret(tmp.score, tmp.Likeliness); + AppTuple ret(tmp.score, tmp.Likeliness); return {ret}; })); - AgentHandle SlaveAgent2 = C->createAgent( + AgentHandle SlaveAgent2 = App->createAgent( LowLevelAgentName2, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName2, lowlevel2](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName2 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel2->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName2, lowlevel2]( - std::pair, bool> I) -> FloatResult { + std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName2 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel2->operator()(std::get<0>(I.first)); - DeluxeTuple ret(tmp.score, tmp.Likeliness); + AppTuple ret(tmp.score, tmp.Likeliness); return {ret}; })); - AgentHandle SlaveAgent3 = C->createAgent( + AgentHandle SlaveAgent3 = App->createAgent( LowLevelAgentName3, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName3, lowlevel3](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName3 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel3->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName3, lowlevel3]( - std::pair, bool> I) -> FloatResult { + std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName3 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel3->operator()(std::get<0>(I.first)); - DeluxeTuple ret(tmp.score, tmp.Likeliness); + AppTuple ret(tmp.score, tmp.Likeliness); return {ret}; })); //------------------------- high level rel --------------------------------- //-------------------------------------------------------------------------- auto highlevel = create_highlevel_func(); using conf1 = Optional>; // this is the confidence expressed as one tuple it // uses the format // (first.state,first.rel,second.sate...) using MasterResult = - std::tuple>, conf1, conf1, conf1>; - using SlaveOutputs = DeluxeTuple; + std::tuple>, conf1, conf1, conf1>; + using SlaveOutputs = AppTuple; using MasterHandler = std::function, std::pair, std::pair)>; - AgentHandle MasterAgent = C->createAgent( + AgentHandle MasterAgent = App->createAgent( "Master Agent", MasterHandler([&](std::pair I0, std::pair I1, std::pair I2) -> MasterResult { ReliabilityForHighLevelAgents::InputType input; input.push_back({0, std::get<0>(I0.first), std::get<1>(I0.first)}); input.push_back({1, std::get<0>(I1.first), std::get<1>(I1.first)}); input.push_back({2, std::get<0>(I2.first), std::get<1>(I2.first)}); auto out = highlevel->operator()(input); - DeluxeTuple rel(out.CrossLikeliness); + AppTuple rel(out.CrossLikeliness); conf c[3]; for (std::size_t at = 0; at < 3; at++) { std::get<0>(c[at]) = out.Likeliness.at(at).at(0).score; std::get<1>(c[at]) = out.Likeliness.at(at).at(0).Likeliness; std::get<2>(c[at]) = out.Likeliness.at(at).at(1).score; std::get<3>(c[at]) = out.Likeliness.at(at).at(1).Likeliness; std::get<4>(c[at]) = out.Likeliness.at(at).at(2).score; std::get<5>(c[at]) = out.Likeliness.at(at).at(2).Likeliness; } return {{rel}, {c[0]}, {c[1]}, {c[2]}}; })); // ------------------------------------------------------------------------- // Sensors and connecting // ------------------------------------------------------------------------- std::vector FloatValues(NumberOfSimulationCycles); std::generate(FloatValues.begin(), FloatValues.end(), [f = 0.5f](void) mutable { f += 0.3f; return std::floor(f) + 0.5f; }); - C->registerSensorValues(Sensor1, FloatValues.begin(), FloatValues.end()); - C->registerSensorValues(Sensor2, FloatValues.begin(), FloatValues.end()); - C->registerSensorValues(Sensor3, FloatValues.begin(), FloatValues.end()); + App->registerSensorValues(Sensor1, FloatValues.begin(), FloatValues.end()); + App->registerSensorValues(Sensor2, FloatValues.begin(), FloatValues.end()); + App->registerSensorValues(Sensor3, FloatValues.begin(), FloatValues.end()); // Connection - C->connectSensor(SlaveAgent1, 0, Sensor1, "Sensor 1"); - C->connectSensor(SlaveAgent2, 0, Sensor2, "Sensor 2"); - C->connectSensor(SlaveAgent3, 0, Sensor3, "Sensor 3"); + App->connectSensor(SlaveAgent1, 0, Sensor1, "Sensor 1"); + App->connectSensor(SlaveAgent2, 0, Sensor2, "Sensor 2"); + App->connectSensor(SlaveAgent3, 0, Sensor3, "Sensor 3"); - C->connectAgents(MasterAgent, 0, SlaveAgent1, "Slave1"); - C->connectAgents(MasterAgent, 1, SlaveAgent2, "Slave2"); - C->connectAgents(MasterAgent, 2, SlaveAgent3, "Slave3"); + App->connectAgents(MasterAgent, 0, SlaveAgent1, "Slave1"); + App->connectAgents(MasterAgent, 1, SlaveAgent2, "Slave2"); + App->connectAgents(MasterAgent, 2, SlaveAgent3, "Slave3"); // Logger - AgentHandle LoggerAgent = C->createAgent( - "Logger Agent", std::function>( - std::pair, bool>)>( - [](std::pair, bool> Sum) - -> Optional> { + AgentHandle LoggerAgent = App->createAgent( + "Logger Agent", std::function>( + std::pair, bool>)>( + [](std::pair, bool> Sum) + -> Optional> { if (Sum.second) { LOG_INFO_STREAM << "Result: Rel: " << std::get<0>(Sum.first) << "\n"; } return {}; })); - C->connectAgents(LoggerAgent, 0, MasterAgent, "Sum Agent Channel"); + App->connectAgents(LoggerAgent, 0, MasterAgent, "Sum Agent Channel"); // ------------------------------------------------------------------------------- // Simulate // ------------------------------------------------------------------------------- - C->simulate(NumberOfSimulationCycles); + App->simulate(NumberOfSimulationCycles); delete highlevel; delete lowlevel1; delete lowlevel2; } diff --git a/examples/agent-functionalities/Reliability-functionality-agent-context/helper.h b/examples/agent-functionalities/Reliability-functionality-agent-context/helper.h index 472fbcc..2bab293 100644 --- a/examples/agent-functionalities/Reliability-functionality-agent-context/helper.h +++ b/examples/agent-functionalities/Reliability-functionality-agent-context/helper.h @@ -1,170 +1,170 @@ #include "rosa/config/version.h" #include "rosa/support/log.h" #include "rosa/agent/CrossReliability.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/Reliability.h" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include #include using namespace rosa::agent; using namespace rosa; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; auto create_lowlevel_func() { std::unique_ptr> Confidence(new RangeConfidence( {{0, PartialFunction( { {{0, 3}, std::make_shared>( 0, 1.0 / 3)}, {{3, 6}, std::make_shared>(1, 0)}, {{6, 9}, std::make_shared>( 3.0, -1.0 / 3)}, }, 0)}, {1, PartialFunction( { {{6, 9}, std::make_shared>( -2, 1.0 / 3)}, {{9, 12}, std::make_shared>(1, 0)}, {{12, 15}, std::make_shared>( 5, -1.0 / 3)}, }, 0)}, {2, PartialFunction( { {{12, 15}, std::make_shared>( -4, 1.0 / 3)}, {{15, 18}, std::make_shared>(1, 0)}, {{18, 21}, std::make_shared>( 7, -1.0 / 3)}, }, 0)}})); std::unique_ptr> Reliability( new LinearFunction(1, -1.0 / 3)); std::unique_ptr> ReliabilitySlope( new LinearFunction(1, -1.0 / 3)); std::unique_ptr> TimeConfidence( new LinearFunction(1, -1.0 / 3)); auto lowlevel = new ReliabilityForLowLevelAgents(); std::vector states; states.push_back(0); states.push_back(1); states.push_back(2); lowlevel->setConfidenceFunction(Confidence); lowlevel->setAbsoluteReliabilityFunction(Reliability); lowlevel->setReliabilitySlopeFunction(ReliabilitySlope); lowlevel->setTimeFunctionForLikelinessFunction(TimeConfidence); lowlevel->setIdentifiers(states); lowlevel->setHistoryLength(2); lowlevel->setTimeStep(1); return lowlevel; } auto create_highlevel_func(){ std::vector states; states.push_back(0); states.push_back(1); states.push_back(2); ReliabilityForHighLevelAgents *highlevel = new ReliabilityForHighLevelAgents(); std::unique_ptr> CrossReliability1(new CrossReliability()); std::unique_ptr> func1( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); std::unique_ptr> func2( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); std::unique_ptr> func3( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); CrossReliability1->addCrossLikelinessProfile(0, 1, func1); CrossReliability1->addCrossLikelinessProfile(0, 2, func2); CrossReliability1->addCrossLikelinessProfile(2, 1, func3); CrossReliability1->setCrossReliabilityMethod( CrossReliability::AVERAGE); CrossReliability1->setCrossLikelinessParameter(1); std::unique_ptr> CrossConfidence1( new CrossConfidence()); std::unique_ptr> func4( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); std::unique_ptr> func5( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); std::unique_ptr> func6( new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); CrossConfidence1->addCrossLikelinessProfile(0, 1, func4); CrossConfidence1->addCrossLikelinessProfile(0, 2, func5); CrossConfidence1->addCrossLikelinessProfile(2, 1, func6); CrossConfidence1->setCrossReliabilityMethod( CrossConfidence::AVERAGE); CrossConfidence1->setCrossLikelinessParameter(1); highlevel->setCrossConfidence(CrossConfidence1); highlevel->setCrossReliability(CrossReliability1); highlevel->addStates(0, states); highlevel->addStates(1, states); highlevel->addStates(2, states); return highlevel; } diff --git a/examples/application-interface/CMakeLists.txt b/examples/application-interface/CMakeLists.txt new file mode 100644 index 0000000..bb9bd24 --- /dev/null +++ b/examples/application-interface/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(application-interface application-interface.cpp) +ROSA_add_library_dependencies(application-interface ROSAConfig) +ROSA_add_library_dependencies(application-interface ROSAApp) diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/application-interface/application-interface.cpp similarity index 57% rename from examples/deluxe-interface/deluxe-interface.cpp rename to examples/application-interface/application-interface.cpp index 3795e86..8d71d95 100644 --- a/examples/deluxe-interface/deluxe-interface.cpp +++ b/examples/application-interface/application-interface.cpp @@ -1,344 +1,345 @@ -//===-- examples/deluxe-interface/deluxe-interface.cpp ----------*- C++ -*-===// +//===-- examples/application-interface/application-interface.cpp *- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file examples/deluxe-interface/deluxe-interface.cpp +/// \file examples/application-interface/application-interface.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// -/// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related +/// \brief A simple example on the \c rosa::app::Application and related /// classes. //===----------------------------------------------------------------------===// #include "rosa/config/version.h" -#include "rosa/deluxe/DeluxeContext.hpp" +#include "rosa/app/Application.hpp" #include #include #include using namespace rosa; -using namespace rosa::deluxe; +using namespace rosa::app; using namespace rosa::terminal; /// How many cycles of simulation to perform. const size_t NumberOfSimulationCycles = 16; int main(void) { LOG_INFO_STREAM << '\n' << library_string() << " -- " << Color::Red - << "deluxe-interface example" << Color::Default << '\n'; + << "application-interface example" << Color::Default << '\n'; - std::unique_ptr C = DeluxeContext::create("Deluxe"); + std::unique_ptr App = Application::create("App"); // - // Create deluxe sensors. + // Create application sensors. // LOG_INFO("Creating sensors."); // All sensors are created without defining a normal generator function, but // with the default value of the last argument. That, however, requires the // data type to be explicitly defined. This is good for simulation only. // The first and second sensors do not receive master-input. - AgentHandle BoolSensor = C->createSensor("BoolSensor"); - AgentHandle IntSensor = C->createSensor("IntSensor"); + AgentHandle BoolSensor = App->createSensor("BoolSensor"); + AgentHandle IntSensor = App->createSensor("IntSensor"); // This sensor receives master-input and dumps it to \c LOG_INFO_STREAM. const std::string FloatSensorName = "FloatSensor"; - AgentHandle FloatSensor = C->createSensor( + AgentHandle FloatSensor = App->createSensor( FloatSensorName, [&FloatSensorName](std::pair I) { LOG_INFO_STREAM << "\n******\n" - << FloatSensorName - << " master-input " << (I.second ? "" : "") + << FloatSensorName << " master-input " + << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); // This sensor do not receive master-input but produces tuples. - using TupleType = DeluxeTuple; - AgentHandle TupleSensor = C->createSensor("TupleSensor"); + using TupleType = AppTuple; + AgentHandle TupleSensor = App->createSensor("TupleSensor"); // // Check and set execution policy for sensors. // LOG_INFO("Execution policies for sensors."); - LOG_INFO(std::to_string(*C->getExecutionPolicy(IntSensor))); - C->setExecutionPolicy(IntSensor, DeluxeExecutionPolicy::decimation(2)); - C->setExecutionPolicy(FloatSensor, DeluxeExecutionPolicy::decimation(2)); - LOG_INFO(std::to_string(*C->getExecutionPolicy(IntSensor))); + LOG_INFO(std::to_string(*App->getExecutionPolicy(IntSensor))); + App->setExecutionPolicy(IntSensor, AppExecutionPolicy::decimation(2)); + App->setExecutionPolicy(FloatSensor, AppExecutionPolicy::decimation(2)); + LOG_INFO(std::to_string(*App->getExecutionPolicy(IntSensor))); // - // Create low-level deluxe agents with \c createLowLevelAgent. + // Create low-level application agents with \c createLowLevelAgent. // LOG_INFO("Creating low-level agents."); // All agents below dump their received values to \c LOG_INFO_STREAM on each // triggering. // This agent does not receive master-input and does not produce // master-output. It results in the value it received. const std::string BoolAgentName = "BoolAgent"; using BoolResult = Optional; using BoolHandler = std::function)>; - AgentHandle BoolAgent = C->createAgent( + AgentHandle BoolAgent = App->createAgent( BoolAgentName, BoolHandler([&BoolAgentName](std::pair I) -> BoolResult { LOG_INFO_STREAM << "\n******\n" << BoolAgentName << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; return {I.first}; })); // This agent receives master-input but does not produce master-output. The // agent maintains a state in \c IntAgentOffset. The master-input handler // updates \c IntAgentOffset according to each received (new) value from its // master. The slave-input handler results in the sum of the received value // and the actual value of \c IntAgentOffset. const std::string IntAgentName = "IntAgent"; using IntMasterHandler = std::function)>; using IntResult = Optional; using IntHandler = std::function)>; uint32_t IntAgentOffset = 0; - AgentHandle IntAgent = C->createAgent( + AgentHandle IntAgent = App->createAgent( IntAgentName, // Master-input handler. - IntMasterHandler([&IntAgentName, - &IntAgentOffset](std::pair I) { - LOG_INFO_STREAM << "\n******\n" - << IntAgentName - << " master-input " << (I.second ? "" : "") - << " value: " << I.first << "\n******\n"; - if (I.second) { - IntAgentOffset = I.first; - } - }), + IntMasterHandler( + [&IntAgentName, &IntAgentOffset](std::pair I) { + LOG_INFO_STREAM << "\n******\n" + << IntAgentName << " master-input " + << (I.second ? "" : "") + << " value: " << I.first << "\n******\n"; + if (I.second) { + IntAgentOffset = I.first; + } + }), // Slave-input handler. IntHandler([&IntAgentName, &IntAgentOffset](std::pair I) -> IntResult { LOG_INFO_STREAM << "\n******\n" << IntAgentName << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; return {I.first + IntAgentOffset}; })); // This agent receives master-input and produces master-output. The // master-input handler propagaates each received (new) value to its slave as // master-output. The slave-input handler results in the value it received and // produces no actual master-output. const std::string FloatAgentName = "FloatAgent"; using FloatMasterResult = std::tuple>; using FloatMasterHandler = std::function)>; using FloatResult = std::tuple, Optional>; using FloatHandler = std::function)>; - AgentHandle FloatAgent = C->createAgent( + AgentHandle FloatAgent = App->createAgent( FloatAgentName, // Master-input handler. - FloatMasterHandler([&FloatAgentName]( - std::pair I) -> FloatMasterResult { - LOG_INFO_STREAM << "\n******\n" - << FloatAgentName - << " master-input " << (I.second ? "" : "") - << " value: " << I.first << "\n******\n"; - const auto Output = - I.second ? Optional(I.first) : Optional(); - return {Output}; - }), + FloatMasterHandler( + [&FloatAgentName](std::pair I) -> FloatMasterResult { + LOG_INFO_STREAM << "\n******\n" + << FloatAgentName << " master-input " + << (I.second ? "" : "") + << " value: " << I.first << "\n******\n"; + const auto Output = + I.second ? Optional(I.first) : Optional(); + return {Output}; + }), // Slave-input handler. FloatHandler([&FloatAgentName](std::pair I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << FloatAgentName << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; return {{I.first}, {}}; })); // This agent does not receive master-input and does not produce // master-output. It results in the sum of the values it receives in a tuple. const std::string TupleAgentName = "TupleAgent"; - using TupleSumResult = Optional>; + using TupleSumResult = Optional>; using TupleHandler = std::function)>; - AgentHandle TupleAgent = C->createAgent( + AgentHandle TupleAgent = App->createAgent( TupleAgentName, TupleHandler( [&TupleAgentName](std::pair I) -> TupleSumResult { LOG_INFO_STREAM << "\n******\n" << TupleAgentName << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; return {std::get<0>(I.first) + std::get<1>(I.first)}; })); // // 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})); + App->setExecutionPolicy(IntAgent, AppExecutionPolicy::awaitAll({0})); + App->setExecutionPolicy(FloatAgent, AppExecutionPolicy::awaitAll({0})); // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); - C->connectSensor(BoolAgent, 0, BoolSensor, "Bool Sensor Channel"); - C->connectSensor(IntAgent, 0, IntSensor, "Int Sensor Channel"); - C->connectSensor(FloatAgent, 0, FloatSensor, "Float Sensor Channel"); - C->connectSensor(TupleAgent, 0, TupleSensor, "Tuple Sensor Channel"); + App->connectSensor(BoolAgent, 0, BoolSensor, "Bool Sensor Channel"); + App->connectSensor(IntAgent, 0, IntSensor, "Int Sensor Channel"); + App->connectSensor(FloatAgent, 0, FloatSensor, "Float Sensor Channel"); + App->connectSensor(TupleAgent, 0, TupleSensor, "Tuple Sensor Channel"); // - // Create a high-level deluxe agent. + // Create a high-level application agent. // LOG_INFO("Create high-level agent."); - using SingleDoubleOutputType = Optional>; - using SingleUInt32OutputType = Optional>; - using NoOutputType = Optional; + using SingleDoubleOutputType = Optional>; + using SingleUInt32OutputType = Optional>; + using NoOutputType = Optional; // This agent does not receive master-input but produces master-output for its // slaves at positions `1` and `2` but not for that at position `0`. The agent // maintains a state in \c SumAgentState. The handler increments \c // SumAgentState upon each received (new) `true` value from its slave at // position `0`. Whenever \c SumAgentState has been updated, it is sent to the // slaves at positions `1` and `2`. The handler results in the sum of the // values received from slaves at positions `1`, `2`, and `3`. using SumResult = std::tuple; using SumHandler = std::function, bool>, std::pair, bool>, - std::pair, bool>, - std::pair, bool>)>; + std::pair, bool>, std::pair, bool>, + std::pair, bool>, std::pair, bool>)>; uint32_t SumAgentState = 0; - AgentHandle SumAgent = C->createAgent( + AgentHandle SumAgent = App->createAgent( "Sum Agent", - SumHandler([&SumAgentState]( - std::pair, bool> I0, - std::pair, bool> I1, - std::pair, bool> I2, - std::pair, bool> I3) -> SumResult { - const auto V0 = std::get<0>(I0.first); - const auto V1 = std::get<0>(I1.first); - const auto V2 = std::get<0>(I2.first); - const auto V3 = std::get<0>(I3.first); - LOG_INFO_STREAM << "\n*******\nSum Agent triggered with values:\n" - << (I0.second ? "" : "") - << " bool value: " << V0 << "\n" - << (I1.second ? "" : "") - << " int value: " << V1 << "\n" - << (I2.second ? "" : "") - << " float value: " << V2 << "\n" - << (I3.second ? "" : "") - << " double value: " << V3 << "\n******\n"; - if (I0.second && V0) { - ++SumAgentState; - } - const SingleUInt32OutputType MasterOutput = - I0.second && V0 - ? SingleUInt32OutputType(DeluxeTuple(SumAgentState)) - : SingleUInt32OutputType(); - const DeluxeTuple Output = {V1 + V2 + V3}; - return {{Output}, {}, {MasterOutput}, {MasterOutput}, {}}; - })); + SumHandler( + [&SumAgentState](std::pair, bool> I0, + std::pair, bool> I1, + std::pair, bool> I2, + std::pair, bool> I3) -> SumResult { + const auto V0 = std::get<0>(I0.first); + const auto V1 = std::get<0>(I1.first); + const auto V2 = std::get<0>(I2.first); + const auto V3 = std::get<0>(I3.first); + LOG_INFO_STREAM << "\n*******\nSum Agent triggered with values:\n" + << (I0.second ? "" : "") + << " bool value: " << V0 << "\n" + << (I1.second ? "" : "") + << " int value: " << V1 << "\n" + << (I2.second ? "" : "") + << " float value: " << V2 << "\n" + << (I3.second ? "" : "") + << " double value: " << V3 << "\n******\n"; + if (I0.second && V0) { + ++SumAgentState; + } + const SingleUInt32OutputType MasterOutput = + I0.second && V0 + ? SingleUInt32OutputType(AppTuple(SumAgentState)) + : SingleUInt32OutputType(); + const AppTuple Output = {V1 + V2 + V3}; + return {{Output}, {}, {MasterOutput}, {MasterOutput}, {}}; + })); // // Connect low-level agents to the high-level agent. // LOG_INFO("Connect low-level agents to the high-level agent."); - C->connectAgents(SumAgent, 0, BoolAgent, "Bool Agent Channel"); - C->connectAgents(SumAgent, 1, IntAgent, "Int Agent Channel"); - C->connectAgents(SumAgent, 2, FloatAgent, "Float Agent Channel"); - C->connectAgents(SumAgent, 3, TupleAgent, "Tuple Agent Channel"); + App->connectAgents(SumAgent, 0, BoolAgent, "Bool Agent Channel"); + App->connectAgents(SumAgent, 1, IntAgent, "Int Agent Channel"); + App->connectAgents(SumAgent, 2, FloatAgent, "Float Agent Channel"); + App->connectAgents(SumAgent, 3, TupleAgent, "Tuple 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 dumps each received (new) value to \c LOG_INFO_STREAM and // produces nothing; does not receive mater-input and does not produce // master-output. - AgentHandle LoggerAgent = - C->createAgent("Logger Agent", - std::function(std::pair)>( - [](std::pair Sum) -> Optional { - if (Sum.second) { - LOG_INFO_STREAM << "Result: " << Sum.first << "\n"; - } - return {}; - })); + AgentHandle LoggerAgent = App->createAgent( + "Logger Agent", std::function(std::pair)>( + [](std::pair Sum) -> Optional { + 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"); + App->connectAgents(LoggerAgent, 0, SumAgent, "Sum Agent Channel"); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // - // Initialize deluxe context for simulation. + // Initialize application for simulation. // - C->initializeSimulation(); + App->initializeSimulation(); // // Create some vectors and register them for their corresponding sensors. // std::vector BoolValues(NumberOfSimulationCycles); std::generate(BoolValues.begin(), BoolValues.end(), [i = 0](void) mutable -> bool { return (++i % 4) == 0; }); - C->registerSensorValues(BoolSensor, BoolValues.begin(), BoolValues.end()); + App->registerSensorValues(BoolSensor, BoolValues.begin(), BoolValues.end()); std::vector IntValues(NumberOfSimulationCycles); std::generate(IntValues.begin(), IntValues.end(), [i = 0](void) mutable { return ++i; }); - C->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end()); + App->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end()); std::vector 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()); + App->registerSensorValues(FloatSensor, FloatValues.begin(), + FloatValues.end()); std::vector TupleValues(NumberOfSimulationCycles); std::generate(TupleValues.begin(), TupleValues.end(), [f1 = 0.f, f2 = 3.14f](void) mutable -> TupleType { f1 += f2; f2 -= f1; return {f1, f2}; }); - C->registerSensorValues(TupleSensor, TupleValues.begin(), TupleValues.end()); + App->registerSensorValues(TupleSensor, TupleValues.begin(), + TupleValues.end()); // // Simulate. // - C->simulate(NumberOfSimulationCycles); + App->simulate(NumberOfSimulationCycles); return 0; } diff --git a/examples/deluxe-interface/CMakeLists.txt b/examples/deluxe-interface/CMakeLists.txt deleted file mode 100755 index 7b5017b..0000000 --- a/examples/deluxe-interface/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_executable(deluxe-interface deluxe-interface.cpp) -ROSA_add_library_dependencies(deluxe-interface ROSAConfig) -ROSA_add_library_dependencies(deluxe-interface ROSADeluxe) - diff --git a/include/rosa/deluxe/DeluxeAgent.hpp b/include/rosa/app/AppAgent.hpp similarity index 70% rename from include/rosa/deluxe/DeluxeAgent.hpp rename to include/rosa/app/AppAgent.hpp index 3b6000f..78ba748 100644 --- a/include/rosa/deluxe/DeluxeAgent.hpp +++ b/include/rosa/app/AppAgent.hpp @@ -1,1463 +1,1456 @@ -//===-- rosa/deluxe/DeluxeAgent.hpp -----------------------------*- C++ -*-===// +//===-- rosa/app/AppAgent.hpp -----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeAgent.hpp +/// \file rosa/app/AppAgent.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// -/// \brief Specialization of \c rosa::Agent for *agent* role of the *deluxe +/// \brief Specialization of \c rosa::Agent for *agent* role of the *application /// interface*. /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXEAGENT_HPP -#define ROSA_DELUXE_DELUXEAGENT_HPP +#ifndef ROSA_APP_APPAGENT_HPP +#define ROSA_APP_APPAGENT_HPP #include "rosa/core/Agent.hpp" -#include "rosa/deluxe/DeluxeAtoms.hpp" -#include "rosa/deluxe/DeluxeExecutionPolicy.h" -#include "rosa/deluxe/DeluxeTuple.hpp" +#include "rosa/app/AppAtoms.hpp" +#include "rosa/app/AppExecutionPolicy.h" +#include "rosa/app/AppTuple.hpp" #include /// Local helper macros to deal with built-in types. /// ///@{ -/// Creates function name for member functions in \c rosa::deluxe::DeluxeAgent. +/// Creates function name for member functions in \c rosa::app::AppAgent. /// /// \param N name suffix to use -#define DASLAVEHANDLERNAME(N) handleSlave_##N +#define AASLAVEHANDLERNAME(N) handleSlave_##N -/// Creates function name for member functions in \c rosa::deluxe::DeluxeAgent. +/// Creates function name for member functions in \c rosa::app::AppAgent. /// /// \param N name suffix to use -#define DAMASTERHANDLERNAME(N) handleMaster_##N +#define AAMASTERHANDLERNAME(N) handleMaster_##N /// Defines member functions for handling messages from *slaves* in -/// \c rosa::deluxe::DeluxeAgent. +/// \c rosa::app::AppAgent. /// -/// \see \c DeluxeAgentInputHandlers +/// \see \c AppAgentInputHandlers /// /// \note No pre- and post-conditions are validated directly by these functions, -/// they rather rely on \c rosa::deluxe::DeluxeAgent::saveInput to do that. +/// they rather rely on \c rosa::app::AppAgent::saveInput to do that. /// /// \param T the type of input to handle /// \param N name suffix for the function identifier -#define DASLAVEHANDLERDEFN(T, N) \ - void DASLAVEHANDLERNAME(N)(atoms::Slave, id_t SlaveId, token_size_t Pos, \ +#define AASLAVEHANDLERDEFN(T, N) \ + void AASLAVEHANDLERNAME(N)(atoms::Slave, id_t SlaveId, token_size_t Pos, \ T Value) noexcept { \ saveInput(SlaveId, Pos, Value); \ } /// Defines member functions for handling messages from *master* in -/// \c rosa::deluxe::DeluxeAgent. +/// \c rosa::app::AppAgent. /// -/// \see \c DeluxeAgentMasterInputHandlers +/// \see \c AppAgentMasterInputHandlers /// /// \note No pre- and post-conditions are validated directly by these functions, -/// they rather rely on \c rosa::deluxe::DeluxeAgent::saveMasterInput to do +/// they rather rely on \c rosa::app::AppAgent::saveMasterInput to do /// that. /// /// \param T the type of input to handle /// \param N name suffix for the function identifier -#define DAMASTERHANDLERDEFN(T, N) \ - void DAMASTERHANDLERNAME(N)(atoms::Master, id_t MasterId, token_size_t Pos, \ +#define AAMASTERHANDLERDEFN(T, N) \ + void AAMASTERHANDLERNAME(N)(atoms::Master, id_t MasterId, token_size_t Pos, \ T Value) noexcept { \ saveMasterInput(MasterId, Pos, Value); \ } -/// Convenience macro for \c DASLAVEHANDLERDEFN with identical arguments. +/// Convenience macro for \c AASLAVEHANDLERDEFN with identical arguments. /// -/// \see \c DASLAVEHANDLERDEFN +/// \see \c AASLAVEHANDLERDEFN /// -/// This macro can be used instead of \c DASLAVEHANDLERDEFN if the actual value +/// This macro can be used instead of \c AASLAVEHANDLERDEFN if the actual value /// of \p T can be used as a part of a valid identifier. /// /// \param T the type of input to handle -#define DASLAVEHANDLERDEF(T) DASLAVEHANDLERDEFN(T, T) +#define AASLAVEHANDLERDEF(T) AASLAVEHANDLERDEFN(T, T) -/// Convenience macro for \c DAMASTERHANDLERDEFN with identical arguments. +/// Convenience macro for \c AAMASTERHANDLERDEFN with identical arguments. /// -/// \see \c DAMASTERHANDLERDEFN +/// \see \c AAMASTERHANDLERDEFN /// -/// This macro can be used instead of \c DAMASTERHANDLERDEFN if the actual value +/// This macro can be used instead of \c AAMASTERHANDLERDEFN if the actual value /// of \p T can be used as a part of a valid identifier. /// /// \param T the type of input to handle -#define DAMASTERHANDLERDEF(T) DAMASTERHANDLERDEFN(T, T) +#define AAMASTERHANDLERDEF(T) AAMASTERHANDLERDEFN(T, T) /// Results in a \c THISMEMBER reference to a member function defined by -/// \c DASLAVEHANDLERDEFN. +/// \c AASLAVEHANDLERDEFN. /// -/// Used in the constructor of \c rosa::deluxe::DeluxeAgent to initialize super -/// class \c rosa::Agent with member function defined by \c DASLAVEHANDLERDEFN. +/// Used in the constructor of \c rosa::app::AppAgent to initialize super +/// class \c rosa::Agent with member function defined by \c AASLAVEHANDLERDEFN. /// -/// \see \c DASLAVEHANDLERDEFN, \c THISMEMBER +/// \see \c AASLAVEHANDLERDEFN, \c THISMEMBER /// /// \param N name suffix for the function identifier -#define DASLAVEHANDLERREF(N) THISMEMBER(DASLAVEHANDLERNAME(N)) +#define AASLAVEHANDLERREF(N) THISMEMBER(AASLAVEHANDLERNAME(N)) /// Results in a \c THISMEMBER reference to a member function defined by -/// \c DAMASTERHANDLERDEFN. +/// \c AAMASTERHANDLERDEFN. /// -/// Used in the constructor of \c rosa::deluxe::DeluxeAgent to initialize super -/// class \c rosa::Agent with member function defined by \c DAMASTERHANDLERDEFN. +/// Used in the constructor of \c rosa::app::AppAgent to initialize super +/// class \c rosa::Agent with member function defined by \c AAMASTERHANDLERDEFN. /// -/// \see \c DAMASTERHANDLERDEFN, \c THISMEMBER +/// \see \c AAMASTERHANDLERDEFN, \c THISMEMBER /// /// \param N name suffix for the function identifier -#define DAMASTERHANDLERREF(N) THISMEMBER(DAMASTERHANDLERNAME(N)) +#define AAMASTERHANDLERREF(N) THISMEMBER(AAMASTERHANDLERNAME(N)) ///@} namespace rosa { -namespace deluxe { +namespace app { -/// Specialization of \c rosa::Agent for *agent* role of the *deluxe interface*. +/// Specialization of \c rosa::Agent for *agent* role of the *application +/// interface*. /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// /// \invariant There is a compatible *execution policy* set, all input-related /// container objects have a size matching \c -/// rosa::deluxe::DeluxeAgent::NumberOfInputs, thus having a corresponding entry -/// for each input. \c rosa::deluxe::DeluxeAgent::NumberOfMasterOutputs matches -/// \c rosa::deluxe::DeluxeAgent::NumberOfInputs. All master-output-related +/// rosa::app::AppAgent::NumberOfInputs, thus having a corresponding entry +/// for each input. \c rosa::app::AppAgent::NumberOfMasterOutputs matches +/// \c rosa::app::AppAgent::NumberOfInputs. All master-output-related /// container objects have a size matching \c -/// rosa::deluxe::DeluxeAgent::NumberOfMasterOutputs. Types and type-related +/// rosa::app::AppAgent::NumberOfMasterOutputs. Types and type-related /// information of input and master-output values are consistent throughout all /// the input-related and master-output-related containers, respectively. The -/// actual values in \c rosa::deluxe::DeluxeAgent::InputNextPos and \c -/// rosa::deluxe::DeluxeAgent::MasterInputNextPos are valid with respect to the +/// actual values in \c rosa::app::AppAgent::InputNextPos and \c +/// rosa::app::AppAgent::MasterInputNextPos are valid with respect to the /// corresponding types. No *slave* is registered at more than one input /// position. *Slave* registrations and corresponding reverse lookup /// information are consistent. /// -/// \see Definition of \c rosa::deluxe::DeluxeAgent::inv on the class invariant +/// \see Definition of \c rosa::app::AppAgent::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 DeluxeAgent : public Agent { +class AppAgent : public Agent { /// Checks whether \p this object holds the class invariant. /// - /// \see Invariant of the class \c rosa::deluxe::DeluxeAgent + /// \see Invariant of the class \c rosa::app::AppAgent /// /// \return if \p this object holds the class invariant bool inv(void) const noexcept; - /// The \c rosa::deluxe::DeluxeExecutionPolicy that controls the execution of + /// The \c rosa::app::AppExecutionPolicy that controls the execution of /// \c this object. - std::unique_ptr ExecutionPolicy; + std::unique_ptr ExecutionPolicy; public: /// The type of values produced by \p this object. /// /// That is the types of values \p this object sends to its *master* in a \c - /// rosa::deluxe::DeluxeTUple. + /// rosa::app::AppTUple. /// - /// \see \c rosa::deluxe::DeluxeAgent::master + /// \see \c rosa::app::AppAgent::master const Token OutputType; /// Number of inputs processed by \p this object. const size_t NumberOfInputs; /// The type of values \p this object processes from its *master*. /// /// That is the types of values \p this object receives from its *master* in a - /// \c rosa::deluxe::DeluxeTuple. + /// \c rosa::app::AppTuple. /// - /// \see \c rosa::deluxe::DeluxeAgent::master + /// \see \c rosa::app::AppAgent::master const Token MasterInputType; /// Number of outputs produces by \p this object for its *slaves*. /// /// \note This values is equal to \c - /// rosa::deluxe::DeluxeAgent::NumberOfInputs. + /// rosa::app::AppAgent::NumberOfInputs. /// - /// \see \c rosa::deluxe::DeluxeAgent::slave. + /// \see \c rosa::app::AppAgent::slave. const size_t NumberOfMasterOutputs; private: /// Types of input values produced by *slaves* of \p this object. /// /// \note The \c rosa::Token values stored correspond to \c - /// rosa::deluxe::DeluxeTuple instances at each argument position. The \c + /// rosa::app::AppTuple instances at each argument position. The \c /// rosa::TypeNumber values from the stored \c rosa::Token values match the - /// corresponding values in \c rosa::deluxe::DeluxeAgent::InputValues in + /// corresponding values in \c rosa::app::AppAgent::InputValues in /// order. /// /// \note The position of a \c rosa::Token in the \c std::vector indicates /// which argument of \p this object's processing function it belongs to. See - /// also \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// also \c rosa::app::AppAgent::AppAgent. const std::vector InputTypes; /// Indicates which element of an input is expected from any particular /// *slave*. /// - /// The *slave* is supposed to send one \c rosa::deluxe::DeluxeTuple value + /// The *slave* is supposed to send one \c rosa::app::AppTuple value /// element by element in their order of definition. This member field tells /// the element at which position in the tuple should be received next from /// the *slave* at a given position. /// /// \p this object is supposed to be triggered only when input values has been /// received completely, that is all values in the field should hold the value /// `0`. /// - /// \see \c rosa::deluxe::DeluxeAgent::handleTrigger - /// \c rosa::deluxe::DeluxeAgent::saveInput + /// \see \c rosa::app::AppAgent::handleTrigger + /// \c rosa::app::AppAgent::saveInput std::vector InputNextPos; /// Indicates whether any particular input value has been changed since the /// last trigger received from the system. /// /// All the flags are reset to \c false upon handling a trigger and then set - /// to \c true by \c rosa::deluxe::DeluxeAgent::saveInput when storing a new - /// input value in \c rosa::deluxe::DeluxeAgent::InputValues. + /// to \c true by \c rosa::app::AppAgent::saveInput when storing a new + /// input value in \c rosa::app::AppAgent::InputValues. /// /// \note The position of a flag in the \c std::vector indicates which /// argument of \p this object's processing function it belongs to. See also - /// \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \c rosa::app::AppAgent::AppAgent. std::vector InputChanged; /// Stores the actual input values. /// /// \note The types of stored values match the corresponding /// \c rosa::TypeNumber values (in \c rosa::Token in order) in \c - /// rosa::deluxe::DeluxeAgent::InputTypes. + /// rosa::app::AppAgent::InputTypes. /// /// \note The position of a \c rosa::AbstractTokenizedStorage in the \c /// std::vector indicates which argument of \p this object's processing /// function the tuple is; and the position of the value in the \c /// rosa::AbstractTokenizedStorage indicates which element of that tuple the - /// value is. See also \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// value is. See also \c rosa::app::AppAgent::AppAgent. const std::vector> InputValues; /// Indicates which element of the master-input is expected from the *master*. /// - /// The *master* is supposed to send one \c rosa::deluxe::DeluxeTuple value + /// The *master* is supposed to send one \c rosa::app::AppTuple value /// element by element in their order of definition. This member field tells /// the element at which position should be received next. /// /// \p this object is supposed to be triggered only when a complete /// master-input has been received, that is the field should hold the value /// `0`. /// - /// \see \c rosa::deluxe::DeluxeAgent::handleTrigger - /// \c rosa::deluxe::DeluxeAgent::saveMasterInput + /// \see \c rosa::app::AppAgent::handleTrigger + /// \c rosa::app::AppAgent::saveMasterInput token_size_t MasterInputNextPos; /// Indicates whether the input value from the *master* has been changed since /// the last trigger received from the system. /// /// The flag is reset to \c false upon handling a trigger and then set to \c - /// true by \c rosa::deluxe::DeluxeAgent::saveMasterInput when storig a new - /// input value in \c rosa::deluxe::DeluxeAgent::MasterInputValue. + /// true by \c rosa::app::AppAgent::saveMasterInput when storig a new + /// input value in \c rosa::app::AppAgent::MasterInputValue. bool MasterInputChanged; /// Stores the actual input value from *master*. /// /// \note The type of the stored value matches the types indicated by \c - /// rosa::deluxe::DeluxeAgent::MasterInputType. + /// rosa::app::AppAgent::MasterInputType. const std::unique_ptr MasterInputValue; /// Types of output values produced by \p this object for its *slaves*. /// /// That is the types of values \p this object sends to its *slaves* in a \c - /// rosa::deluxe::DeluxeTuple. + /// rosa::app::AppTuple. /// /// \note The position of a type in the \c std::vector indicates which /// *slave* of \p this object the type belongs to. See also - /// \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \c rosa::app::AppAgent::AppAgent. const std::vector MasterOutputTypes; /// Alias for function objects used as trigger handler for - /// \c rosa::deluxe::DeluxeAgent. + /// \c rosa::app::AppAgent. /// /// \note The function used for \c H is to be \c noexcept. /// - /// \see \c rosa::deluxe::DeluxeAgent::FP + /// \see \c rosa::app::AppAgent::FP using H = std::function; /// Handles trigger from the system. /// /// The actual functions processing *slave* and *master* inputs and generating /// optional output to *master* and *slaves* are captured in a lambda /// expression that is in turn wrapped in a \c std::function object. The /// lambda expression calls the master-input processing function with the /// actual master-input data and sends its result -- if any -- to *slaves* by - /// calling \c rosa::deluxe::DeluxeAgent::handleMasterOutputs; then calls the + /// calling \c rosa::app::AppAgent::handleMasterOutputs; then calls the /// input processing function with the actual input data and sends its result /// -- if any -- to *master* by calling \c - /// rosa::deluxe::DeluxeAgent::sendToMaster and *slaves* by calling \c - /// rosa::deluxe::DeluxeAgent::handleMasterOutputs. Also, all the flags stored - /// in \c rosa::deluxe::DeluxeAgent::InputChanged and \c - /// rosa::deluxe::DeluxeAgent::MasterInputChanged are reset when the current + /// rosa::app::AppAgent::sendToMaster and *slaves* by calling \c + /// rosa::app::AppAgent::handleMasterOutputs. Also, all the flags stored + /// in \c rosa::app::AppAgent::InputChanged and \c + /// rosa::app::AppAgent::MasterInputChanged are reset when the current /// values are processed. The function \c - /// rosa::deluxe::DeluxeAgent::handleTrigger needs only to call the + /// rosa::app::AppAgent::handleTrigger needs only to call the /// function object. /// /// \see \c - /// rosa::deluxe::DeluxeAgent::triggerHandlerFromProcessingFunctions + /// rosa::app::AppAgent::triggerHandlerFromProcessingFunctions const H FP; /// The *master* to send values to. /// /// \note *Masters* are set dynamically, hence it is possible that a - /// \c rosa::deluxe::DeluxeAgent instance does not have any *master* at a + /// \c rosa::app::AppAgent instance does not have any *master* at a /// given moment. Optional Master; /// The *slaves* sending input to \p this object. /// /// \note The position of a *slave* in the \c std::vector indicates which /// argument of \p this object's processing function it belongs to. See also - /// \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \c rosa::app::AppAgent::AppAgent. /// /// \note *Slaves* are set dynamically, hence it is possible that a - /// \c rosa::deluxe::DeluxeAgent instance does have input positions without + /// \c rosa::app::AppAgent instance does have input positions without /// any *slave* associated to them. /// /// \note Reverse lookup information is maintained in - /// \c rosa::deluxe::DeluxeAgent::SlaveIds, which is to be kept in sync with + /// \c rosa::app::AppAgent::SlaveIds, which is to be kept in sync with /// the *slaves* stored here. std::vector> Slaves; /// Associates \c rosa::id_t values to corresponding indices of registered /// *slaves*. /// - /// \see \c rosa::deluxe::DeluxeAgent::Slaves + /// \see \c rosa::app::AppAgent::Slaves std::map SlaveIds; /// Tells the unique identifier of the *master* of \p this object, if any /// registered. /// /// \return the unique identifier of the *master* /// /// \pre A *master* is registered for \p this object: \code /// Master /// \endcode id_t masterId(void) const noexcept; /// Tells whether types stored in \c rosa::TypeList \p As match the input /// types of \p this object. /// /// \tparam As \c rosa::TypeList containing types to match against values in - /// \c rosa::deluxe::DeluxeAgent::InputTypes + /// \c rosa::app::AppAgent::InputTypes /// /// \note Instatiation of the template fails if \p As is not \c /// rosa::TypeList. /// - /// \return if types in \p As are instances of \c rosa::deluxe::DeluxeTuple + /// \return if types in \p As are instances of \c rosa::app::AppTuple /// and their types match \c rosa::Token values stored in \c - /// rosa::deluxe::DeluxeAgent::InputTypes + /// rosa::app::AppAgent::InputTypes template bool inputTypesMatch(void) const noexcept; /// Tells whether types stored in \c rosa::TypeList \p Ts match the /// master-output types of \p this object. /// /// \tparam Ts \c rosa::TypeList containing types to match against values in - /// \c rosa::deluxe::DeluxeAgent::MasterOutputTypes + /// \c rosa::app::AppAgent::MasterOutputTypes /// /// \note Instatiation of the template fails if \p As is not \c /// rosa::TypeList. /// /// \return if types in \p Ts match \c rosa::Token and in turn \c /// rosa::TypeNumber values stored in \c - /// rosa::deluxe::DeluxeAgent::MasterOutputTypes + /// rosa::app::AppAgent::MasterOutputTypes template bool masterOutputTypesMatch(void) const noexcept; /// Gives the current input value for slave position \p Pos. /// /// \tparam Pos slave position to get input value for /// \tparam Ts types of elements of the input value /// \tparam S0 indices for accessing elements of the input value /// /// \note The arguments provide types and indices statically as template /// arguments \p Ts... \p S0..., respectively, so their actual values are /// ignored. /// /// \return current input value for slave position \p Pos /// /// \pre Statically, the provided indices \p S0... match the length of \p /// Ts...: \code /// sizeof...(Ts) == sizeof...(S0) /// \endcode Dynamically, \p Pos is a valid slave position and type arguments /// \p Ts... match the corresponding input value: \code - /// Pos < NumberOfInputs && DeluxeTuple::TT == InputTypes[Pos] + /// Pos < NumberOfInputs && AppTuple::TT == InputTypes[Pos] /// \endcode template - DeluxeTuple prepareInputValueAtPos(TypeList, Seq) const + AppTuple prepareInputValueAtPos(TypeList, Seq) const noexcept; /// Gives an \c std::tuple containing the current input values and their /// change flags so that they can be used for the processing function. /// /// \tparam As types of the input values /// \tparam S0 indices for accessing input values and their change flags /// /// \note The only argument provides indices statically as template arguments /// \p S0..., so its actual value is ignored. /// /// \return current input values and their change flags prepared for invoking /// the processing function with them /// /// \pre Statically, all type arguments \p As... are instances of \c - /// rosa::deluxe::DeluxeTuple and the provided indices \p S0... match the + /// rosa::app::AppTuple and the provided indices \p S0... match the /// length of \p As...: \code - /// TypeListAllDeluxeTuple>::Value && + /// TypeListAllAppTuple>::Value && /// sizeof...(As) == sizeof...(S0) /// \endcode Dynamically, type arguments \p As... match the input types of \p /// this object: \code /// inputTypesMatch>() /// \endcode template std::tuple...> prepareCurrentInputs(Seq) const noexcept; /// Invokes a processing function matching the input, output, and /// master-output types of \p this object with actual arguments provided in a /// \c std::tuple. /// /// \note \p Args providing the actual arguments for \p F is to be created by - /// \c rosa::deluxe::DeluxeAgent::prepareCurrentInputs. + /// \c rosa::app::AppAgent::prepareCurrentInputs. /// /// \tparam T output type of the processing function /// \tparam Ts types of master-output values of the processing function /// \tparam As types of inputs for the processing function /// \tparam S0 indices starting with `0` for extracting actual arguments from /// \p Args /// /// \param F the processing function to invoke /// \param Args the actual arguments to invoke \p F with /// /// \note The last argument provides indices statically as template arguments /// \p S0..., so its actual value is ignored. /// /// \return the result of \p F for actual arguments \p Args /// /// \pre The provided sequence of indices \p S0... constitutes a proper /// sequence for extracting all actual arguments for /// \p F from \p Args: \code /// sizeof...(As) == sizeof...(S0) /// \endcode template static std::tuple, Optional...> invokeWithTuple(std::function, Optional...>( std::pair...)> F, const std::tuple...> Args, Seq) noexcept; /// Handles a master-output value for a particular *slave* position. /// /// \p Value is a \c rosa::Optional resulted by a processing function and /// contains a master-output value for the *slave* at position \p Pos. The /// function takes the master-output value and sends its actual value, if any, /// to the corresponding *slave*. /// - /// \note A master-output of type \c rosa::deluxe::EmptyDeluxeTuple indicates + /// \note A master-output of type \c rosa::app::EmptyAppTuple indicates /// no actual output and hence no message is generated for a position whose - /// corresponding master-output type is \c rosa::deluxe::EmptyDeluxeTuple. + /// corresponding master-output type is \c rosa::app::EmptyAppTuple. /// /// \note The function provides position-based implementation for \c - /// rosa::deluxe::DeluxeAgent::handleMasterOutputs. + /// rosa::app::AppAgent::handleMasterOutputs. /// /// \tparam Pos the position of the master-output to send \p Value for /// \tparam Ts types of elements in \p Value /// - /// \param Value \c rosa::deluxe::DeluxeTuple resulted by the processing + /// \param Value \c rosa::app::AppTuple resulted by the processing /// function for *slave* position \p Pos /// /// \pre \p Pos is a valid master-output position and \p Value matches the /// master-output type of \p this object at position \p Pos: \code /// Pos < NumberOfMasterOutputs && - /// DeluxeTuple::TT == MasterOutputTypes[Pos] + /// AppTuple::TT == MasterOutputTypes[Pos] /// \endcode template - void - handleMasterOutputAtPos(const Optional> &Value) noexcept; + void handleMasterOutputAtPos(const Optional> &Value) noexcept; /// Handles master-output values from \p Output. /// /// \p Output is a \c std::tuple resulted by a processing function and /// contains master-output values starting at position \p Offset. The function /// takes master-output values and sends each actual value to the /// corresponding *slave*. /// /// \tparam Offset index of the first master-output value in \p Output /// \tparam Ts output types stored in \p Output /// \tparam S0 indices starting with `0` for extracting master-output values /// from \p Output /// /// \note Instantiation fails if any of the type arguments \p Ts... starting - /// at position \p Offset is not an instance of \c rosa::deluxe::DeluxeTuple + /// at position \p Offset is not an instance of \c rosa::app::AppTuple /// or the number of types \p Ts... is not consistent with the other template /// arguments. /// /// \param Output \c std::tuple resulted by a processing function /// /// \pre Statically, type arguments \p Ts... starting at position \p Offset - /// are instances of \c rosa::deluxe::DeluxeTuple and the number of types \p + /// are instances of \c rosa::app::AppTuple and the number of types \p /// Ts... is consistent with the other template arguments: \code - /// TypeListAllDeluxeTuple< + /// TypeListAllAppTuple< /// typename TypeListDrop>::Type>::Value && /// sizeof...(Ts) == Offset + sizeof...(S0) /// \endcode Dynamically, \p Output matches the master-output types \p this /// object was created with and the provided sequence of indices \p S0... /// constitues a proper sequence for extracting all master-output values from /// \p Output: \code /// masterOutputTypesMatch>::Type>() && /// sizeof...(S0) == NumberOfMasterOutputs /// \endcode template void handleMasterOutputs(const std::tuple...> &Output, Seq) noexcept; /// Wraps processing functions into a trigger handler. /// - /// \see \c rosa::deluxe::DeluxeAgent::FP + /// \see \c rosa::app::AppAgent::FP /// /// \note The function cannot be const qualified because the lambda /// expression defined in it needs to capture \p this object by a non-const /// reference /// /// \tparam MTs types of elements of master-input processed by \p MF /// \tparam T type of output /// \tparam Ts types of master-output values /// \tparam As types of input values /// \tparam S0 indices for accessing master-input values /// /// \note Instantiation fails if any of the type arguments \p T, \p Ts..., - /// and \p As... is not an instance of \c rosa::deluxe::DeluxeTuple. + /// and \p As... is not an instance of \c rosa::app::AppTuple. /// /// \param MF function processing master-input and generating output /// \param F function processing inputs and generating output /// /// \note The last argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// - /// \note A master-input type of \c rosa::deluxe::EmptyDeluxeTuple indicates + /// \note A master-input type of \c rosa::app::EmptyAppTuple indicates /// that \p this object does not receive master-input, \p MF is never called /// if \p MTs is empty. /// /// \return trigger handler function based on \p F and \p MF /// /// \pre Statically, type arguments \p T, \p Ts..., and \p As... are - /// instances of \c rosa::deluxe::DeluxeTuple and the indices match + /// instances of \c rosa::app::AppTuple and the indices match /// master-input elements: \code - /// TypeListAllDeluxeTuple>::Value && + /// TypeListAllAppTuple>::Value && /// sizeof...(MTs) == sizeof...(S0) /// \endcode Dynamically, template arguments \p MTs..., \p T, \p Ts..., and /// \p As... match the corresponding types \p this object was created with: /// \code - /// MasterInputType == DeluxeTuple::TT && OutputType == T::TT && + /// MasterInputType == AppTuple::TT && OutputType == T::TT && /// inputTypesMatch>() && /// masterOutputTypesMatch>() /// \endcode template H triggerHandlerFromProcessingFunctions( - std::function...>( - std::pair, bool>)> &&MF, + std::function< + std::tuple...>(std::pair, bool>)> &&MF, std::function< std::tuple, Optional...>(std::pair...)> &&F, Seq) noexcept; public: /// Creates a new instance. /// /// The constructor instantiates the base-class with functions to handle - /// messages as defined for the *deluxe interface*. + /// messages as defined for the *application interface*. /// /// The function \p F generates a \c std::tuple of values: the first value is /// the output for the *master* and the rest is for the *slaves*. All output /// generated by the function is optional as an agent may decide not to output /// anything at some situation. /// /// \todo Enforce \p F and \p MF do not potentially throw exception. /// /// \tparam MT type of master-input handled by \p MF /// \tparam T type of output of \p F /// \tparam Ts type of master-output values of \p F and \p MF /// \tparam As types of input values of \p F /// /// \note Instantiation fails if any of the type arguments \p MT, \p T, \p - /// Ts..., and \p As... is not an instance of \c rosa::deluxe::DeluxeTuple or - /// any of \p T and \p As... is \c rosa::deluxe::EmptyDeluxeTuple or the + /// Ts..., and \p As... is not an instance of \c rosa::app::AppTuple or + /// any of \p T and \p As... is \c rosa::app::EmptyAppTuple or the /// number of inputs and master-outputs are not equal. /// - /// \note If \p MT is \c rosa::deluxe::EmptyDeluxeTuple, the constructed + /// \note If \p MT is \c rosa::app::EmptyAppTuple, the constructed /// object does not receive master-input. Similarly, if any of \p Ts... is \c - /// rosa::deluxe::EmptyDeluxeTuple, the constructed object does not generated + /// rosa::app::EmptyAppTuple, the constructed object does not generated /// master-output for the corresponding *slave* position. /// /// \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 MF function to process master-input values and generate /// master-output with /// \param F function to process input values and generate output and /// master-output with /// /// \pre Statically, all the type arguments \p MT, \p T, \p Ts..., and \p - /// As... are instances of \c rosa::deluxe::DeluxeTuple, with \p T and \p + /// As... are instances of \c rosa::app::AppTuple, with \p T and \p /// As... containing at least one element, and the number of input and /// master-output types are equal: \code - /// TypeListAllDeluxeTuple::Value && + /// TypeListAllAppTuple::Value && /// T::Length > 0 && (true && ... && As::Length > 0) && /// sizeof...(Ts) == sizeof...(As) ///\endcode /// Dynamically, the instance is created as of kind \c - /// rosa::deluxe::atoms::AgentKind: \code - /// Kind == rosa::deluxe::atoms::AgentKind + /// rosa::app::atoms::AgentKind: \code + /// Kind == rosa::app::atoms::AgentKind /// \endcode /// - /// \see \c rosa::deluxe::DeluxeTuple + /// \see \c rosa::app::AppTuple template >::Value && + TypeListAllAppTuple>::Value && (T::Length > 0) && (true && ... && (As::Length > 0)) && sizeof...(Ts) == sizeof...(As)>> - DeluxeAgent( - const AtomValue Kind, const id_t Id, const std::string &Name, - MessagingSystem &S, - std::function...>(std::pair)> &&MF, - std::function, Optional...>( - std::pair...)> &&F) noexcept; + AppAgent(const AtomValue Kind, const id_t Id, const std::string &Name, + MessagingSystem &S, + std::function...>(std::pair)> &&MF, + std::function, Optional...>( + std::pair...)> &&F) noexcept; /// Destroys \p this object. - ~DeluxeAgent(void) noexcept; + ~AppAgent(void) noexcept; /// Returns the current execution policy of \p this object. /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \note The returned reference is valid only as long as \c - /// rosa::deluxe::DeluxeAgent::setExecutionPolicy() is not called and \p this + /// rosa::app::AppAgent::setExecutionPolicy() is not called and \p this /// object is not destroyed. /// - /// \return \c rosa::deluxe::DeluxeAgent::ExecutionPolicy - const DeluxeExecutionPolicy &executionPolicy(void) const noexcept; + /// \return \c rosa::app::AppAgent::ExecutionPolicy + const AppExecutionPolicy &executionPolicy(void) const noexcept; /// Sets the current execution policy of \p this object to \p EP. /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \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 &&EP) noexcept; + bool setExecutionPolicy(std::unique_ptr &&EP) noexcept; /// The *master* of \p this object, if any is registered. /// - /// \see \c rosa::deluxe::DeluxeAgent::registerMaster + /// \see \c rosa::app::AppAgent::registerMaster /// /// \return the *master* registered for \p this object Optional 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*. /// - /// \note Any call to \c rosa::deluxe::DeluxeAgent::registerMaster should be + /// \note Any call to \c rosa::app::AppAgent::registerMaster should be /// paired with a corresponding call of \c - /// rosa::deluxe::DeluxeAgent::registerSlave, which validates that + /// rosa::app::AppAgent::registerSlave, which validates that /// input/output types of master and slave matches. /// /// \param _Master the *master* to register /// - /// \pre \p _Master is empty or of kind \c rosa::deluxe::atoms::AgentKind: + /// \pre \p _Master is empty or of kind \c rosa::app::atoms::AgentKind: /// \code - /// !_Master || unwrapAgent(*_Master).Kind == rosa::deluxe::atoms::AgentKind + /// !_Master || unwrapAgent(*_Master).Kind == rosa::app::atoms::AgentKind /// \endcode void registerMaster(const Optional _Master) noexcept; /// Tells the types of values consumed from the *slave* at a position. /// /// That is the type of values \p this object expect to be sent to it in a \c - /// rosa::deluxe::DeluxeTuple by its *slave* registered at position \p Pos. + /// rosa::app::AppTuple by its *slave* registered at position \p Pos. /// - /// \see \c rosa::deluxe::DeluxeAgent::slave + /// \see \c rosa::app::AppAgent::slave /// /// \param Pos position of *slave* /// /// \return \c rosa::Token representing the types of values consumed from /// the *slave* at position \p Pos /// /// \pre \p Pos is a valid index of input: \code /// Pos < NumberOfInputs /// \endcode Token inputType(const size_t Pos) const noexcept; /// Tells the types of values produced for the *slave* at a position. /// /// That is the types of values \p this object potentially sends in a \c - /// rosa::deluxe::DeluxeTuple to its *slave* registered at position \p Pos. + /// rosa::app::AppTuple to its *slave* registered at position \p Pos. /// - /// \see \c rosa::deluxe::DeluxeAgent::slave + /// \see \c rosa::app::AppAgent::slave /// /// \param Pos position of *slave* /// /// \return \c rosa::Token representing the types of values produced for /// the *slave* at position \p Pos /// /// \pre \p Pos is a valid index of input: \code /// Pos < NumberOfMasterOutputs /// \endcode Token masterOutputType(const size_t Pos) const noexcept; /// The *slave* of \p this object registered at a position, if any. /// - /// \see \c rosa::deluxe::DeluxeAgent::registerSlave + /// \see \c rosa::app::AppAgent::registerSlave /// /// \param Pos position of *slave* /// /// \return the *slave* registered for \p this object at position \p Pos /// /// \pre \p Pos is a valid index of input: \code /// Pos < NumberOfInputs /// \endcode Optional slave(const size_t Pos) const noexcept; /// Registers a *slave* for \p this object at a position. /// /// The new *slave* is registered by overwriting the reference to any already /// registered *slave* at position \p Pos. One can clear the registered /// reference by passing an *empty* \c rosa::Optional object as actual /// argument. If \p Slave is already registered for another position, the /// other position gets cleared. /// /// \note The role of the referred *slave* is validated by checking its /// *kind*. /// /// \note The type of values produced by the referred *slave* is validated by /// matching its `OutputType` against the corresponding value in - /// \c rosa::deluxe::DeluxeAgent::InputTypes. + /// \c rosa::app::AppAgent::InputTypes. /// /// \note The type of master-input values processed by the referred *slave* is /// validated by matching its `MasterInputType` against the corresponding - /// value in \c rosa::deluxe::DeluxeAgent::MasterOutputTypes. + /// value in \c rosa::app::AppAgent::MasterOutputTypes. /// /// \param Pos position to register \p Slave at /// \param Slave the *slave* to register /// /// \pre \p Pos is a valid index of input, \p Slave is empty or of kind - /// \c rosa::deluxe::atoms::AgentKind or \c rosa::deluxe::atoms::SensorKind, + /// \c rosa::app::atoms::AgentKind or \c rosa::app::atoms::SensorKind, /// and \p Slave -- if not empty -- produces values of types matching the /// expected input type at position \p Pos and processes values of types /// matching the produced master-output type at position \p Pos: /// \code /// Pos < NumberOfInputs && /// (!Slave || - /// (unwrapAgent(*Slave.)Kind == rosa::deluxe::atoms::SensorKind && - /// static_cast(unwrapAgent(*Slave)).OutputType == + /// (unwrapAgent(*Slave.)Kind == rosa::app::atoms::SensorKind && + /// static_cast(unwrapAgent(*Slave)).OutputType == /// InputTypes[Pos] && /// (emptyToken(MasterOutputTypes[Pos]) || - /// static_cast(unwrapAgent(*Slave)).MasterInputType + /// static_cast(unwrapAgent(*Slave)).MasterInputType /// == MasterOutputTypes[Pos])) || - /// (unwrapAgent(*Slave).Kind == rosa::deluxe::atoms::AgentKind && - /// static_cast(unwrapAgent(*Slave)).OutputType == + /// (unwrapAgent(*Slave).Kind == rosa::app::atoms::AgentKind && + /// static_cast(unwrapAgent(*Slave)).OutputType == /// InputTypes[Pos] && /// (emptyToken(MasterOutputTypes[Pos]) || - /// static_cast(unwrapAgent(*Slave)).MasterInputType == + /// static_cast(unwrapAgent(*Slave)).MasterInputType == /// MasterOutputTypes[Pos]))) /// \endcode void registerSlave(const size_t Pos, const Optional Slave) noexcept; /// Tells the position of a registered *slave*. /// /// \param Slave \c rosa::AgentHandle for the *slave* to check /// /// \return position of \p Slave if it is registered and found, - /// \c rosa::deluxe::DeluxeAgent::NumberOfInputs otherwise. + /// \c rosa::app::AppAgent::NumberOfInputs otherwise. size_t positionOfSlave(AgentHandle Slave) const noexcept; private: /// Sends a value to the *master* of \p this object. /// - /// \p Value is getting sent to \c rosa::deluxe::DeluxeAgent::Master if it - /// contains a valid handle for a \c rosa::deluxe::DeluxeAgent. The function + /// \p Value is getting sent to \c rosa::app::AppAgent::Master if it + /// contains a valid handle for a \c rosa::app::AppAgent. The function /// does nothing otherwise. /// /// The elements from \p Value are sent one by one in separate messages to the /// *master*. /// /// \tparam Ts types of the elements in \p Value /// \tparam S0 indices for accessing elements of \p Value /// /// \param Value value to send /// /// \note The second argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// /// \pre Statically, the indices match the elements: \code /// sizeof...(Ts) == sizeof...(S0) /// \endcode Dynamically, \p Ts match \c - /// rosa::deluxe::DeluxeiAgent::OutputType: \code + /// rosa::app::AppiAgent::OutputType: \code /// OutputType == TypeToken::Value /// \endcode template - void sendToMaster(const DeluxeTuple &Value, Seq) noexcept; + void sendToMaster(const AppTuple &Value, Seq) noexcept; /// Sends a value to a *slave* of \p this object at position \p Pos. /// - /// \p Value is getting sent to \c rosa::deluxe::DeluxeAgent::Slaves[Pos] if + /// \p Value is getting sent to \c rosa::app::AppAgent::Slaves[Pos] if /// it contains a valid handle. The function does nothing otherwise. /// /// The elements from \p Value are sent one by one in separate messages to the /// *slave*. /// /// \tparam Ts types of the elements in \p Value /// \tparam S0 indices for accessing elements of \p Value /// /// \param Pos the position of the *slave* to send \p Value to /// \param Value value to send /// /// \pre Statically, the indices match the elements: \code /// sizeof...(Ts) == sizeof...(S0) /// \endcode Dynamically, \p Pos is a valid *slave* position and \p Ts match - /// \c rosa::deluxe::DeluxeiAgent::MasterOutputTypes[Pos]: \code + /// \c rosa::app::AppiAgent::MasterOutputTypes[Pos]: \code /// Pos < NumberOfMasterOutputs && /// MasterOutputTypes[Pos] == TypeToken::Value /// \endcode template - void sendToSlave(const size_t Pos, const DeluxeTuple &Value, + void sendToSlave(const size_t Pos, const AppTuple &Value, Seq) noexcept; /// Generates the next output by processing current input values upon trigger /// from the system. /// - /// Executes \c rosa::deluxe::DeluxeAgent::FP. + /// Executes \c rosa::app::AppAgent::FP. /// /// \note The only argument is a \c rosa::AtomConstant, hence its actual /// value is ignored. /// /// \pre Master-input and all input from *slaves* are supposed to be /// completely received upon triggering: \code /// MasterInputNextPos == 0 && /// std::all_of(InputNextPos.begin(), InputNextPos.end(), /// [](const token_size_t &I){return I == 0;}) /// \endcode void handleTrigger(atoms::Trigger) noexcept; /// Stores a new input value from a *slave*. /// /// The function stores \p Value at position \p Pos in \c - /// rosa::deluxe::DeluxeAgent::InputValues at the position associated to \p Id - /// in \c rosa::deluxe::DeluxeAgent::SlaveIds and also sets the corresponding - /// flag in \c rosa::deluxe::DeluxeAgent::InputChanged. The function also + /// rosa::app::AppAgent::InputValues at the position associated to \p Id + /// in \c rosa::app::AppAgent::SlaveIds and also sets the corresponding + /// flag in \c rosa::app::AppAgent::InputChanged. The function also /// takes care of checking and updating \c - /// rosa::deluxe::DeluxeSensor::MasterInputNextPos at the corresponding + /// rosa::app::AppSensor::MasterInputNextPos at the corresponding /// position: increments the value and resets it to `0` when the last element /// is received. /// - /// \note Utilized by member functions of group \c DeluxeAgentInputHandlers. + /// \note Utilized by member functions of group \c AppAgentInputHandlers. /// /// \tparam T type of input to store /// /// \param Id unique identifier of *slave* - /// \param Pos position of the value in the \c rosa::deluxe::DeluxeTuple + /// \param Pos position of the value in the \c rosa::app::AppTuple /// \param Value the input value to store /// /// \pre The *slave* with \p Id is registered, \p Pos is the expected /// position of input from the *slave*, and the input from it is expected to /// be of type \p T: \code /// SlaveIds.find(Id) != SlaveIds.end() && /// Pos == InputNextPos[SlaveIds.find(Id)->second] && /// typeAtPositionOfToken(InputTypes[SlaveIds.find(Id)->second], Pos) == /// TypeNumberOf::Value /// \endcode template void saveInput(id_t Id, token_size_t Pos, T Value) noexcept; /// Stores a new input value from the *master*. /// /// The function stores \p Value at position \p Pos in \c - /// rosa::deluxe::DeluxeAgent::MasterInputValue and also sets the - /// flag \c rosa::deluxe::DeluxeAgent::MasterInputChanged. The function also + /// rosa::app::AppAgent::MasterInputValue and also sets the + /// flag \c rosa::app::AppAgent::MasterInputChanged. The function also /// takes care of checking and updating \c - /// rosa::deluxe::DeluxeAgent::MasterInputNextPos: increments its value and + /// rosa::app::AppAgent::MasterInputNextPos: increments its value and /// reset to `0` when the last element is received. /// /// \note Utilized by member functions of group \c - /// DeluxeAgentMasterInputHandlers. + /// AppAgentMasterInputHandlers. /// /// \tparam T type of input to store /// /// \param Id unique identifier of the *master* - /// \param Pos position of the value in the \c rosa::deluxe::DeluxeTuple + /// \param Pos position of the value in the \c rosa::app::AppTuple /// \param Value the input value to store /// /// \pre The *master* with \p Id is registered, \p Pos is the expected /// position of master-input, and the input from the *master* at position \p /// Pos is expected to be of type \p T: \code /// Master && masterId() == Id && Pos == MasterInputNextPos && /// typeAtPositionOfToken(MasterInputType, Pos) == TypeNumberOf::Value /// \endcode template void saveMasterInput(id_t Id, token_size_t Pos, T Value) noexcept; - /// \defgroup DeluxeAgentInputHandlers Input handlers of - /// rosa::deluxe::DeluxeAgent + /// \defgroup AppAgentInputHandlers Input handlers of + /// rosa::app::AppAgent /// /// Definition of member functions handling messages from *slaves* with /// different types of input /// /// A *master* generally needs to be prepared to deal with values of any /// built-in type to handle messages from its *slaves*. Each type requires a /// separate message handler, which are implemented by these functions. The - /// functions instantiate \c rosa::deluxe::DeluxeAgent::saveInput with the + /// functions instantiate \c rosa::app::AppAgent::saveInput with the /// proper template argument and pass the content of the message on for /// processing. /// /// \note The member functions in this group are defined by \c - /// DASLAVEHANDLERDEF. + /// AASLAVEHANDLERDEF. /// /// \note Keep these definitions in sync with \c rosa::BuiltinTypes. /// ///@{ - DASLAVEHANDLERDEF(AtomValue) - DASLAVEHANDLERDEF(int16_t) - DASLAVEHANDLERDEF(int32_t) - DASLAVEHANDLERDEF(int64_t) - DASLAVEHANDLERDEF(int8_t) - DASLAVEHANDLERDEFN(long double, long_double) - DASLAVEHANDLERDEFN(std::string, std__string) - DASLAVEHANDLERDEF(uint16_t) - DASLAVEHANDLERDEF(uint32_t) - DASLAVEHANDLERDEF(uint64_t) - DASLAVEHANDLERDEF(uint8_t) - DASLAVEHANDLERDEF(unit_t) - DASLAVEHANDLERDEF(bool) - DASLAVEHANDLERDEF(double) - DASLAVEHANDLERDEF(float) + AASLAVEHANDLERDEF(AtomValue) + AASLAVEHANDLERDEF(int16_t) + AASLAVEHANDLERDEF(int32_t) + AASLAVEHANDLERDEF(int64_t) + AASLAVEHANDLERDEF(int8_t) + AASLAVEHANDLERDEFN(long double, long_double) + AASLAVEHANDLERDEFN(std::string, std__string) + AASLAVEHANDLERDEF(uint16_t) + AASLAVEHANDLERDEF(uint32_t) + AASLAVEHANDLERDEF(uint64_t) + AASLAVEHANDLERDEF(uint8_t) + AASLAVEHANDLERDEF(unit_t) + AASLAVEHANDLERDEF(bool) + AASLAVEHANDLERDEF(double) + AASLAVEHANDLERDEF(float) /// @} - /// \defgroup DeluxeAgentMasterInputHandlers Master-input handlers of - /// rosa::deluxe::DeluxeAgent + /// \defgroup AppAgentMasterInputHandlers Master-input handlers of + /// rosa::app::AppAgent /// /// Definition of member functions handling messages from the *master* with /// different types of input /// /// A *slave* generally needs to be prepared to deal with values of any /// built-in type to handle messages from its *master*. Each type requires a /// separate message handler, which are implemented by these functions. The - /// functions instantiate \c rosa::deluxe::DeluxeAgent::saveMasterInput with + /// functions instantiate \c rosa::app::AppAgent::saveMasterInput with /// the proper template argument and pass the content of the message on for /// processing. /// /// \note The member functions in this group are defined by \c - /// DAMASTERHANDLERDEF. + /// AAMASTERHANDLERDEF. /// /// \note Keep these definitions in sync with \c rosa::BuiltinTypes. /// ///@{ - DAMASTERHANDLERDEF(AtomValue) - DAMASTERHANDLERDEF(int16_t) - DAMASTERHANDLERDEF(int32_t) - DAMASTERHANDLERDEF(int64_t) - DAMASTERHANDLERDEF(int8_t) - DAMASTERHANDLERDEFN(long double, long_double) - DAMASTERHANDLERDEFN(std::string, std__string) - DAMASTERHANDLERDEF(uint16_t) - DAMASTERHANDLERDEF(uint32_t) - DAMASTERHANDLERDEF(uint64_t) - DAMASTERHANDLERDEF(uint8_t) - DAMASTERHANDLERDEF(unit_t) - DAMASTERHANDLERDEF(bool) - DAMASTERHANDLERDEF(double) - DAMASTERHANDLERDEF(float) + AAMASTERHANDLERDEF(AtomValue) + AAMASTERHANDLERDEF(int16_t) + AAMASTERHANDLERDEF(int32_t) + AAMASTERHANDLERDEF(int64_t) + AAMASTERHANDLERDEF(int8_t) + AAMASTERHANDLERDEFN(long double, long_double) + AAMASTERHANDLERDEFN(std::string, std__string) + AAMASTERHANDLERDEF(uint16_t) + AAMASTERHANDLERDEF(uint32_t) + AAMASTERHANDLERDEF(uint64_t) + AAMASTERHANDLERDEF(uint8_t) + AAMASTERHANDLERDEF(unit_t) + AAMASTERHANDLERDEF(bool) + AAMASTERHANDLERDEF(double) + AAMASTERHANDLERDEF(float) /// @} }; /// Anonymous namespace with implementation for \c -/// rosa::deluxe::DeluxeAgent::DeluxeAgent, \c -/// rosa::deluxe::DeluxeAgent::inputTypesMatch, and \c -/// rosa::deluxe::DeluxeAgent::masterOutputTypesMatch, consider it private. +/// rosa::app::AppAgent::AppAgent, \c +/// rosa::app::AppAgent::inputTypesMatch, and \c +/// rosa::app::AppAgent::masterOutputTypesMatch, consider it private. namespace { /// Creates storages for data of types \p Ts... in a \c std::vector of \c /// rosa::TokenizedStorage. /// -/// \note Utilized by \c rosa::deluxe::DeluxeAgnet::DeluxeAgent to initialize \c -/// rosa::deluxe::DeluxeAgent::InputValues. That is due to not being able to use +/// \note Utilized by \c rosa::app::AppAgnet::AppAgent to initialize \c +/// rosa::app::AppAgent::InputValues. That is due to not being able to use /// an initializer list directly; the initializer list always copies but \c /// std::unique_ptr is not copyable. /// /// \tparam Ts types to create storages for /// /// \note Instantiation fails if any of the type arguments \p Ts... is not an -/// instance of \c rosa::deluxe::DeluxeTuple. +/// instance of \c rosa::app::AppTuple. /// /// \return \c std::vector with pointers for the created storage objects /// /// \pre Statically, all the type arguments \p Ts... are instances of \c -/// rosa::deluxe::DeluxeTuple: \code -/// TypeListAllDeluxeTuple>::Value +/// rosa::app::AppTuple: \code +/// TypeListAllAppTuple>::Value /// \endcode template std::vector> makeInputStorages(void) noexcept { std::vector> InputStorages; (InputStorages.push_back( std::make_unique::Type>::Type>()), + typename UnwrapAppTuple::Type>::Type>()), ...); return InputStorages; } /// Template \c struct whose specializations provide a recursive implementation /// for \c TypesMatchList. /// /// \tparam As types to match template struct TypesMatchImpl; /// Template specialization for the case, when at least one type is to -/// be matched and that is an instance of \c rosa::deluxe::DeluxeTuple. +/// be matched and that is an instance of \c rosa::app::AppTuple. /// -/// \tparam Ts types of elements in the \c rosa::deluxe::DeluxeTuple to match +/// \tparam Ts types of elements in the \c rosa::app::AppTuple to match /// \tparam As further types to match template -struct TypesMatchImpl, As...> { - /// Tells whether types \c rosa::deluxe::DeluxeTuple and \p As... match +struct TypesMatchImpl, As...> { + /// Tells whether types \c rosa::app::AppTuple and \p As... match /// \c rosa::Token values stored in \p Tokens starting at position \p Pos. /// /// The function has got a recursive implementation: it matches the first - /// type \c rosa::deluxe::DeluxeTuple against \c rosa::Token at + /// type \c rosa::app::AppTuple against \c rosa::Token at /// position \p Pos of \p Tokens, then further types \p As... are matched /// recursively starting at position \c (Pos + 1). /// /// \param Tokens container of \c rosa::Token values to match types against /// \param Pos position in \p Tokens to start matching at /// - /// \return if types \c rosa::deluxe::DeluxeTuple and \p As... match \c + /// \return if types \c rosa::app::AppTuple and \p As... match \c /// rosa::Token values stored in \p Tokens starting at position \p Pos static bool f(const std::vector &Tokens, size_t Pos) noexcept { return Pos < Tokens.size() && TypeToken::Value == Tokens[Pos] && TypesMatchImpl::f(Tokens, Pos + 1); } }; /// Template specialization for the case, when at least one type is to -/// be matched and that is *not* an instance of \c rosa::deluxe::DeluxeTuple. +/// be matched and that is *not* an instance of \c rosa::app::AppTuple. /// /// \tparam T first type to match /// \tparam As further types to match template struct TypesMatchImpl { /// Tells whether types \p T and \p As... match \c rosa::Token values stored /// in \p Tokens starting at position \p Pos. /// /// This specialization is used only when \p T is not an instance of \c - /// rosa::deluxe::DeluxeTuple, in which case the match is not successful. + /// rosa::app::AppTuple, in which case the match is not successful. /// /// \note The function takes two parameters to match the general signature but /// the actual values are ignored. /// /// \return `false` static bool f(const std::vector &, size_t) noexcept { return false; } }; /// Template specialization for the terminal case, when no type remains to /// check. template <> struct TypesMatchImpl<> { /// Tells whether \p Pos is the number of values stored in \p Tokens. /// /// In this terminal case, there is no more types to match because all the /// types are supposed to be already matched successfully. The whole list of /// types already matched is a complete match if it covers all values in /// \p Tokens. That is true if \p Pos points exactly to the end of \p Tokens. /// /// \param Tokens container of \c rosa::Token values to match types against /// \param Pos position in \p Tokens to start matching at /// /// \return if \p Pos is the number of values stored in \p Tokens static bool f(const std::vector &Tokens, size_t Pos) noexcept { return Pos == Tokens.size(); } }; /// Template \c struct that provides an implementation for \c -/// rosa::deluxe::DeluxeAgent::inputTypesMatch and \c -/// rosa::deluxe::DeluxeAgent::masterOutputTypesMatch. +/// rosa::app::AppAgent::inputTypesMatch and \c +/// rosa::app::AppAgent::masterOutputTypesMatch. /// /// \note Match a list of types \p List against a \c std::vector of /// \c rosa::Token values, \c Tokens, like \code /// bool match = TypesMatchList::f(Tokens); /// \endcode /// If any type in \c rosa::TypeList \p Listis not an instance of \c -/// rosa::deluxe::DeluxeTuple, the match gives a negative result. +/// rosa::app::AppTuple, the match gives a negative result. /// /// \tparam List \c rosa::TypeList that contains types to match template struct TypesMatchList; /// Template specialization implementing the feature. /// /// \tparam As types to match template struct TypesMatchList> { /// Tells whether types \p As... match \c rosa::Token values stored in \p /// Tokens. /// /// The function unwraps the types from \c rosa::TypeList and utilizes \c /// TypesMatchImpl to do the check. /// /// \param Tokens container of \c rosa::Token values to match types against /// /// \return if types \p As... match \c rosa::Token values stored in \p Tokens static bool f(const std::vector &Tokens) noexcept { return TypesMatchImpl::f(Tokens, 0); } }; } // End namespace -template bool DeluxeAgent::inputTypesMatch(void) const noexcept { +template bool AppAgent::inputTypesMatch(void) const noexcept { return TypesMatchList::f(InputTypes); } template -bool DeluxeAgent::masterOutputTypesMatch(void) const noexcept { +bool AppAgent::masterOutputTypesMatch(void) const noexcept { return TypesMatchList::f(MasterOutputTypes); } template -DeluxeTuple DeluxeAgent::prepareInputValueAtPos(TypeList, - Seq) const - noexcept { - using T = DeluxeTuple; +AppTuple AppAgent::prepareInputValueAtPos(TypeList, + Seq) const noexcept { + using T = AppTuple; STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent type arguments"); ASSERT(inv() && Pos < NumberOfInputs && T::TT == InputTypes[Pos]); // The below should hold because of the above, just leave it for sanity check. STATIC_ASSERT((true && ... && (static_cast(static_cast(S0)) == S0)), "Should not happen"); const auto &SlaveInput = InputValues[Pos]; // Get all elements of the tuple in a fold expression. return T(*static_cast( SlaveInput->pointerTo(static_cast(S0)))...); } template std::tuple...> -DeluxeAgent::prepareCurrentInputs(Seq) const noexcept { - STATIC_ASSERT(TypeListAllDeluxeTuple>::Value, - "not tuple types"); +AppAgent::prepareCurrentInputs(Seq) const noexcept { + STATIC_ASSERT(TypeListAllAppTuple>::Value, "not tuple types"); STATIC_ASSERT(sizeof...(As) == sizeof...(S0), "inconsistent type arguments"); ASSERT(inv() && inputTypesMatch>()); return std::make_tuple(std::make_pair( - prepareInputValueAtPos(typename UnwrapDeluxeTuple::Type(), + prepareInputValueAtPos(typename UnwrapAppTuple::Type(), seq_t()), InputChanged[S0])...); } template -std::tuple, Optional...> DeluxeAgent::invokeWithTuple( +std::tuple, Optional...> AppAgent::invokeWithTuple( std::function< std::tuple, Optional...>(std::pair...)> F, const std::tuple...> Args, Seq) noexcept { STATIC_ASSERT(sizeof...(As) == sizeof...(S0), "wrong number of type parameters"); return F(std::get(Args)...); } template -void DeluxeAgent::handleMasterOutputAtPos( - const Optional> &Value) noexcept { - using MOT = DeluxeTuple; +void AppAgent::handleMasterOutputAtPos( + const Optional> &Value) noexcept { + using MOT = AppTuple; ASSERT(inv() && Pos < NumberOfMasterOutputs && MOT::TT == MasterOutputTypes[Pos]); // Do not do anything for master-output of type \c - // rosa::deluxe::EmptyDeluxeTuple and when \p Value is empty. - if - constexpr(!std::is_same::value) { - if (Value) { - sendToSlave(Pos, *Value, seq_t()); - } + // rosa::app::EmptyAppTuple and when \p Value is empty. + if constexpr (!std::is_same::value) { + if (Value) { + sendToSlave(Pos, *Value, seq_t()); } - else { + } else { (void)Value; } ASSERT(inv()); } template -void DeluxeAgent::handleMasterOutputs(const std::tuple...> &Output, - Seq) noexcept { +void AppAgent::handleMasterOutputs(const std::tuple...> &Output, + Seq) noexcept { using MOTs = typename TypeListDrop>::Type; - STATIC_ASSERT(TypeListAllDeluxeTuple::Value, - "not tuple type arguments"); + STATIC_ASSERT(TypeListAllAppTuple::Value, "not tuple type arguments"); STATIC_ASSERT(sizeof...(Ts) == Offset + sizeof...(S0), "inconsistent arguments"); ASSERT(inv() && masterOutputTypesMatch() && sizeof...(S0) == NumberOfMasterOutputs); // Handle each master-output position in a fold expression. (handleMasterOutputAtPos(std::get(Output)), ...); ASSERT(inv()); } template -DeluxeAgent::H DeluxeAgent::triggerHandlerFromProcessingFunctions( +AppAgent::H AppAgent::triggerHandlerFromProcessingFunctions( std::function< - std::tuple...>(std::pair, bool>)> &&MF, + std::tuple...>(std::pair, bool>)> &&MF, std::function< std::tuple, Optional...>(std::pair...)> &&F, Seq) noexcept { - using MT = DeluxeTuple; - STATIC_ASSERT((TypeListAllDeluxeTuple>::Value), + using MT = AppTuple; + STATIC_ASSERT((TypeListAllAppTuple>::Value), "not tuple type arguments"); STATIC_ASSERT(sizeof...(MTs) == sizeof...(S0), "inconsistent arguments"); ASSERT(MasterInputType == MT::TT && OutputType == T::TT && inputTypesMatch>() && masterOutputTypesMatch>()); return [ this, MF, F ]() noexcept { // \note These indices work for both inputs and master-outputs. using SlaveIndices = seq_t; // Handle master-input. // Do not do anything for master-input type \c - // rosa::deluxe::EmptyDeluxeTuple. - if (!std::is_same::value) { - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << " handles master-input." + // rosa::app::EmptyAppTuple. + if (!std::is_same::value) { + LOG_TRACE_STREAM << "AppAgent " << FullName << " handles master-input." << std::endl; // The assert must hold if \p this object was successfully constructed. - STATIC_ASSERT((true && ... && (static_cast( - static_cast(S0)) == S0)), - "Unexpected error"); + STATIC_ASSERT( + (true && ... && + (static_cast(static_cast(S0)) == S0)), + "Unexpected error"); const auto MasterInputArg = std::make_pair( // Get all elements of the tuple in a fold expression. MT(*static_cast( MasterInputValue->pointerTo(static_cast(S0)))...), MasterInputChanged); MasterInputChanged = false; const std::tuple...> MasterOutput = MF(MasterInputArg); handleMasterOutputs<0>(MasterOutput, SlaveIndices()); } // Handle inputs. // Call the processing function only if \p ExecutionPolicy allows. if (ExecutionPolicy->shouldProcess(InputChanged)) { - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << " handles input." + LOG_TRACE_STREAM << "AppAgent " << FullName << " handles input." << std::endl; const auto InputArgs = prepareCurrentInputs(SlaveIndices()); std::fill(InputChanged.begin(), InputChanged.end(), false); const std::tuple, Optional...> Output = invokeWithTuple(F, InputArgs, SlaveIndices()); const auto OutputToMaster = std::get<0>(Output); if (OutputToMaster) { sendToMaster(*OutputToMaster, seq_t()); } handleMasterOutputs<1>(Output, SlaveIndices()); } else { - LOG_TRACE_STREAM << "DeluxeAgent " << Name << " skips input." - << std::endl; + LOG_TRACE_STREAM << "AppAgent " << Name << " skips input." << std::endl; } }; } template -DeluxeAgent::DeluxeAgent( +AppAgent::AppAgent( const AtomValue Kind, const id_t Id, const std::string &Name, MessagingSystem &S, std::function...>(std::pair)> &&MF, std::function, Optional...>( std::pair...)> &&F) noexcept : Agent(Kind, Id, Name, S, THISMEMBER(handleTrigger), - DASLAVEHANDLERREF(AtomValue), DASLAVEHANDLERREF(int16_t), - DASLAVEHANDLERREF(int32_t), DASLAVEHANDLERREF(int64_t), - DASLAVEHANDLERREF(int8_t), DASLAVEHANDLERREF(long_double), - DASLAVEHANDLERREF(std__string), DASLAVEHANDLERREF(uint16_t), - DASLAVEHANDLERREF(uint32_t), DASLAVEHANDLERREF(uint64_t), - DASLAVEHANDLERREF(uint8_t), DASLAVEHANDLERREF(unit_t), - DASLAVEHANDLERREF(bool), DASLAVEHANDLERREF(double), - DASLAVEHANDLERREF(float), DAMASTERHANDLERREF(AtomValue), - DAMASTERHANDLERREF(int16_t), DAMASTERHANDLERREF(int32_t), - DAMASTERHANDLERREF(int64_t), DAMASTERHANDLERREF(int8_t), - DAMASTERHANDLERREF(long_double), DAMASTERHANDLERREF(std__string), - DAMASTERHANDLERREF(uint16_t), DAMASTERHANDLERREF(uint32_t), - DAMASTERHANDLERREF(uint64_t), DAMASTERHANDLERREF(uint8_t), - DAMASTERHANDLERREF(unit_t), DAMASTERHANDLERREF(bool), - DAMASTERHANDLERREF(double), DAMASTERHANDLERREF(float)), - ExecutionPolicy(DeluxeExecutionPolicy::decimation(1)), OutputType(T::TT), + AASLAVEHANDLERREF(AtomValue), AASLAVEHANDLERREF(int16_t), + AASLAVEHANDLERREF(int32_t), AASLAVEHANDLERREF(int64_t), + AASLAVEHANDLERREF(int8_t), AASLAVEHANDLERREF(long_double), + AASLAVEHANDLERREF(std__string), AASLAVEHANDLERREF(uint16_t), + AASLAVEHANDLERREF(uint32_t), AASLAVEHANDLERREF(uint64_t), + AASLAVEHANDLERREF(uint8_t), AASLAVEHANDLERREF(unit_t), + AASLAVEHANDLERREF(bool), AASLAVEHANDLERREF(double), + AASLAVEHANDLERREF(float), AAMASTERHANDLERREF(AtomValue), + AAMASTERHANDLERREF(int16_t), AAMASTERHANDLERREF(int32_t), + AAMASTERHANDLERREF(int64_t), AAMASTERHANDLERREF(int8_t), + AAMASTERHANDLERREF(long_double), AAMASTERHANDLERREF(std__string), + AAMASTERHANDLERREF(uint16_t), AAMASTERHANDLERREF(uint32_t), + AAMASTERHANDLERREF(uint64_t), AAMASTERHANDLERREF(uint8_t), + AAMASTERHANDLERREF(unit_t), AAMASTERHANDLERREF(bool), + AAMASTERHANDLERREF(double), AAMASTERHANDLERREF(float)), + ExecutionPolicy(AppExecutionPolicy::decimation(1)), OutputType(T::TT), NumberOfInputs(sizeof...(As)), MasterInputType(MT::TT), NumberOfMasterOutputs(NumberOfInputs), InputTypes({As::TT...}), InputNextPos(NumberOfInputs, 0), InputChanged(NumberOfInputs, false), InputValues(makeInputStorages()), MasterInputNextPos(0), MasterInputChanged(false), MasterInputValue(new typename TokenizedStorageForTypeList< - typename UnwrapDeluxeTuple::Type>::Type()), + typename UnwrapAppTuple::Type>::Type()), MasterOutputTypes({Ts::TT...}), FP(triggerHandlerFromProcessingFunctions(std::move(MF), std::move(F), seq_t())), Slaves(NumberOfInputs) { ASSERT(Kind == atoms::AgentKind); - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << " is created." << std::endl; + LOG_TRACE_STREAM << "AppAgent " << FullName << " is created." << std::endl; ASSERT(inv()); } template -void DeluxeAgent::sendToMaster(const DeluxeTuple &Value, - Seq) noexcept { +void AppAgent::sendToMaster(const AppTuple &Value, Seq) noexcept { STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent arguments"); ASSERT(inv() && OutputType == TypeToken::Value); // The assert must hold if \p this object was successfully constructed. STATIC_ASSERT((true && ... && (static_cast(static_cast(S0)) == S0)), "Unexpected error"); // Create a static constant array for these indices to be available as lvalue // references when creating messages below. \c S0... when used directly in a // fold expression is a temporary value, which would result in \c // rosa::Message instances being created with rvalue references. Further, all // other values would to copied into a temporary variable for making them /// available as rvalue references (they are constant lvalue references here). static constexpr std::array Indices{{S0...}}; - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppAgent " << FullName << "(" << Id << ") sends to master (" << static_cast(Master && *Master) << "): " << Value << " (" << sizeof...(S0) << ")" << std::endl; // There is a handle and the referred *master* is in a valid state. if (Master && *Master) { // Handle each element of the tuple in a fold expression. (Master->sendMessage(Message::create(atoms::Slave::Value, Id, Indices[S0], std::get(Value))), ...); } ASSERT(inv()); } template -void DeluxeAgent::sendToSlave(const size_t Pos, const DeluxeTuple &Value, - Seq) noexcept { +void AppAgent::sendToSlave(const size_t Pos, const AppTuple &Value, + Seq) noexcept { STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent arguments"); ASSERT(inv() && Pos < NumberOfMasterOutputs && MasterOutputTypes[Pos] == TypeToken::Value); // The assert must hold if \p this object was successfully constructed. STATIC_ASSERT((true && ... && (static_cast(static_cast(S0)) == S0)), "Unexpected error"); // Create a static constant array for these indices to be available as lvalue // references when creating messages below. \c S0... when used directly in a // fold expression is a temporary value, which would result in \c // rosa::Message instances being created with rvalue references. Further, all // other values would to copied into a temporary variable for making them /// available as rvalue references (they are constant lvalue references here). static constexpr std::array Indices{{S0...}}; // There is a handle and the referred *slave* is in a valid state. auto Slave = Slaves[Pos]; - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppAgent " << FullName << "(" << Id << ") sends to slave (" << static_cast(Slave && *Slave) << ") at position " << Pos << ": " << Value << " (" << sizeof...(S0) << ")" << std::endl; if (Slave && *Slave) { // Handle each element of the tuple in a fold expression. (Slave->sendMessage(Message::create(atoms::Master::Value, Id, Indices[S0], std::get(Value))), ...); } } template -void DeluxeAgent::saveInput(id_t Id, token_size_t Pos, T Value) noexcept { +void AppAgent::saveInput(id_t Id, token_size_t Pos, T Value) noexcept { ASSERT(inv() && SlaveIds.find(Id) != SlaveIds.end() && Pos == InputNextPos[SlaveIds.find(Id)->second] && typeAtPositionOfToken(InputTypes[SlaveIds.find(Id)->second], Pos) == TypeNumberOf::Value); const size_t SlavePos = SlaveIds.at(Id); - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppAgent " << FullName << "(" << Id << ") saves value from slave at position " << SlavePos << ": (" << static_cast(Pos) << ") " << Value << std::endl; // Save value. *static_cast(InputValues[SlavePos]->pointerTo(Pos)) = Value; // Update position of next value. if (++InputNextPos[SlavePos] == lengthOfToken(InputTypes[SlavePos])) { InputNextPos[SlavePos] = 0; } // Set flag. InputChanged[SlavePos] = true; ASSERT(inv()); } template -void DeluxeAgent::saveMasterInput(id_t Id, token_size_t Pos, T Value) noexcept { +void AppAgent::saveMasterInput(id_t Id, token_size_t Pos, T Value) noexcept { ASSERT(inv() && Master && masterId() == Id && Pos == MasterInputNextPos && typeAtPositionOfToken(MasterInputType, Pos) == TypeNumberOf::Value); - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppAgent " << FullName << "(" << Id << ") saves value from master: (" << static_cast(Pos) << ") " << Value << std::endl; // Save value. *static_cast(MasterInputValue->pointerTo(Pos)) = Value; // Update position of next value. if (++MasterInputNextPos == lengthOfToken(MasterInputType)) { MasterInputNextPos = 0; } // Set flag. MasterInputChanged = true; ASSERT(inv()); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa -#undef DASLAVEHANDLEREF -#undef DAMASTERHANDLEREF -#undef DASLAVEHANDLEDEF -#undef DAMASTERHANDLEDEF -#undef DASLAVEHANDLEDEFN -#undef DAMASTERHANDLEDEFN -#undef DASLAVEHANDLENAME -#undef DAMASTERHANDLENAME +#undef AASLAVEHANDLEREF +#undef AAMASTERHANDLEREF +#undef AASLAVEHANDLEDEF +#undef AAMASTERHANDLEDEF +#undef AASLAVEHANDLEDEFN +#undef AAMASTERHANDLEDEFN +#undef AASLAVEHANDLENAME +#undef AAMASTERHANDLENAME -#endif // ROSA_DELUXE_DELUXEAGENT_HPP +#endif // ROSA_APP_APPAGENT_HPP diff --git a/include/rosa/deluxe/DeluxeAtoms.hpp b/include/rosa/app/AppAtoms.hpp old mode 100755 new mode 100644 similarity index 60% rename from include/rosa/deluxe/DeluxeAtoms.hpp rename to include/rosa/app/AppAtoms.hpp index 23b8ade..6f4c1ce --- a/include/rosa/deluxe/DeluxeAtoms.hpp +++ b/include/rosa/app/AppAtoms.hpp @@ -1,65 +1,65 @@ -//===-- rosa/deluxe/DeluxeAtoms.hpp -----------------------------*- C++ -*-===// +//===-- rosa/app/AppAtoms.hpp -----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeAtoms.hpp +/// \file rosa/app/AppAtoms.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// /// \brief Definition of \c rosa::AtomValue values and \c rosa::AtomConstant -/// types for the implementation of the *deluxe interface*. +/// types for the implementation of the *application interface*. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXEATOMS_HPP -#define ROSA_DELUXE_DELUXEATOMS_HPP +#ifndef ROSA_APP_APPATOMS_HPP +#define ROSA_APP_APPATOMS_HPP #include "rosa/support/atom.hpp" namespace rosa { -namespace deluxe { +namespace app { -/// Contains some definitions used in the implementation of the *deluxe +/// Contains some definitions used in the implementation of the *application /// interface* to denote various roles and events /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// /// \note Do not apply `using namespace` to this namespace as that may result in /// some identifiers in the original namespace being hidden by those of -/// \c rosa::deluxe::atoms. +/// \c rosa::app::atoms. namespace atoms { -/// Value to be used as the *kind* of \c rosa::deluxe::DeluxeSensor. +/// Value to be used as the *kind* of \c rosa::app::AppSensor. /// /// \see \c rosa::Unit::Kind -constexpr AtomValue SensorKind = atom("dl_sensor"); +constexpr AtomValue SensorKind = atom("ap_sensor"); -/// Value to be used as the *kind* of \c rosa::deluxe::DeluxeAgent. +/// Value to be used as the *kind* of \c rosa::app::AppAgent. /// /// \see \c rosa::Unit::Kind -constexpr AtomValue AgentKind = atom("dl_agent"); +constexpr AtomValue AgentKind = atom("ap_agent"); /// Type alias denoting system trigger messages. -using Trigger = AtomConstant; +using Trigger = AtomConstant; /// Type alias denoting messages from a slave. -using Slave = AtomConstant; +using Slave = AtomConstant; /// Type alias denoting messages from a master. -using Master = AtomConstant; +using Master = AtomConstant; } // End namespace atoms -} // End namespace deluxe +} // End namespace app } // End namespace rosa -#endif // ROSA_DELUXE_DELUXEATOMS_HPP +#endif // ROSA_APP_APPATOMS_HPP diff --git a/include/rosa/deluxe/DeluxeExecutionPolicy.h b/include/rosa/app/AppExecutionPolicy.h similarity index 65% rename from include/rosa/deluxe/DeluxeExecutionPolicy.h rename to include/rosa/app/AppExecutionPolicy.h index 223ca13..94b2152 100644 --- a/include/rosa/deluxe/DeluxeExecutionPolicy.h +++ b/include/rosa/app/AppExecutionPolicy.h @@ -1,201 +1,204 @@ -//===-- rosa/deluxe/DeluxeExecutionPolicy.h ---------------------*- C++ -*-===// +//===-- rosa/app/AppExecutionPolicy.h ---------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeExecutionPolicy.h +/// \file rosa/app/AppExecutionPolicy.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Public interface of *execution policies* in the *deluxe interface*. +/// \brief Public interface of *execution policies* in the *application +/// interface*. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H -#define ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H +#ifndef ROSA_APP_APPEXECUTIONPOLICY_H +#define ROSA_APP_APPEXECUTIONPOLICY_H #include "rosa/core/AgentHandle.hpp" #include #include #include #include namespace rosa { -namespace deluxe { +namespace app { -// Forward declaration of DeluxeSystem. Do not include the corresponding header +// Forward declaration of AppSystem. Do not include the corresponding header // in this file because of cyclic dependency. -class DeluxeSystem; +class AppSystem; /// *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 +/// An *execution policy* can be applied to a application *unit* only if \c +/// rosa::app::AppExecutionPolicy::canHandle() allows it. Each application /// *unit* must have a compatible *execution policy* associated to it, and the -/// *unit* queries \c rosa::deluxe::DeluxeExecutionPolicy::shouldProcess() on each +/// *unit* queries \c rosa::app::AppExecutionPolicy::shouldProcess() 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() +/// \see rosa::app::AppExecutionPolicy::decimation() +/// \see rosa::app::AppExecutionPolicy::awaitAll() +/// \see rosa::app::AppExecutionPolicy::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 { +class AppExecutionPolicy { protected: - /// Protected constructor, only implementations can instantiate the class. - DeluxeExecutionPolicy(void) noexcept = default; + AppExecutionPolicy(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; + AppExecutionPolicy(const AppExecutionPolicy &) = delete; + AppExecutionPolicy(AppExecutionPolicy &&) = delete; + AppExecutionPolicy &operator=(const AppExecutionPolicy &) = delete; + AppExecutionPolicy &operator=(AppExecutionPolicy &&) = delete; ///@} public: /// Virtual destructor for subclasses. - virtual ~DeluxeExecutionPolicy(void) noexcept = default; + virtual ~AppExecutionPolicy(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); + 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 + 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 + static std::unique_ptr awaitAny(const std::set &S); - /// Tells if \p this object can handle the deluxe *unit* referred by \p H. + /// Tells if \p this object can handle the application *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. + /// given application *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 + virtual bool canHandle(const AgentHandle H, const AppSystem &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*. + /// The function is to be called on each triggering of the application *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 shouldProcess(const std::vector &InputChanged) noexcept = 0; + virtual bool + shouldProcess(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. + /// rosa::app::AppAgent. /// /// \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; + /// \return if the *unit* referred by \p H is a \c rosa::app::AppAgent + bool isAppAgent(const AgentHandle H, const AppSystem &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 + /// If \p H refers to a \c rosa::app::AppAgent, 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; + size_t numberOfAppAgentInputs(const AgentHandle H, const AppSystem &S) const + noexcept; }; -} // End namespace deluxe +} // End namespace app } // End namespace rosa namespace std { -/// Converts a \c rosa::deluxe::DeluxeExecutionPolicy into \c std::string. +/// Converts a \c rosa::app::AppExecutionPolicy into \c std::string. /// -/// \param EP \c rosa::deluxe::DeluxeExecutionPolicy to convert +/// \param EP \c rosa::app::AppExecutionPolicy to convert /// /// \return \c std::string representing \p EP -string to_string(const rosa::deluxe::DeluxeExecutionPolicy &EP); +string to_string(const rosa::app::AppExecutionPolicy &EP); -/// Dumps a \c rosa::deluxe::DeluxeExecutionPolicy to a given \c std::ostream. +/// Dumps a \c rosa::app::AppExecutionPolicy to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to -/// \param EP \c rosa::deluxe::DeluxeExecutionPolicy to dump +/// \param EP \c rosa::app::AppExecutionPolicy to dump /// /// \return \p OS after dumping \p EP to it -ostream &operator<<(ostream &OS, const rosa::deluxe::DeluxeExecutionPolicy &EP); +ostream &operator<<(ostream &OS, const rosa::app::AppExecutionPolicy &EP); } // End namespace std -#endif // ROSA_DELUXE_DELUXEEXECUTIONPOLICY_H +#endif // ROSA_APP_APPEXECUTIONPOLICY_H diff --git a/include/rosa/deluxe/DeluxeSensor.hpp b/include/rosa/app/AppSensor.hpp similarity index 59% rename from include/rosa/deluxe/DeluxeSensor.hpp rename to include/rosa/app/AppSensor.hpp index c4846a6..14417ed 100644 --- a/include/rosa/deluxe/DeluxeSensor.hpp +++ b/include/rosa/app/AppSensor.hpp @@ -1,676 +1,671 @@ -//===-- rosa/deluxe/DeluxeSensor.hpp ----------------------------*- C++ -*-===// +//===-- rosa/app/AppSensor.hpp ----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeSensor.hpp +/// \file rosa/app/AppSensor.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017-2020 /// -/// \brief Specialization of \c rosa::Agent for *sensor* role of the the *deluxe -/// interface*. +/// \brief Specialization of \c rosa::Agent for *sensor* role of the the +/// *application interface*. /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXESENSOR_HPP -#define ROSA_DELUXE_DELUXESENSOR_HPP +#ifndef ROSA_APP_APPSENSOR_HPP +#define ROSA_APP_APPSENSOR_HPP #include "rosa/core/Agent.hpp" -#include "rosa/deluxe/DeluxeAtoms.hpp" -#include "rosa/deluxe/DeluxeExecutionPolicy.h" -#include "rosa/deluxe/DeluxeTuple.hpp" +#include "rosa/app/AppAtoms.hpp" +#include "rosa/app/AppExecutionPolicy.h" +#include "rosa/app/AppTuple.hpp" #include "rosa/support/diagnostics.h" /// Local helper macros to deal with built-in types. /// ///@{ -/// Creates function name for member functions in \c rosa::deluxe::DeluxeSensor. +/// Creates function name for member functions in \c rosa::app::AppSensor. /// /// \param N name suffix to use -#define DSMASTERHANDLERNAME(N) handleMaster_##N +#define ASMASTERHANDLERNAME(N) handleMaster_##N /// Defines member functions for handling messages from *master* in -/// \c rosa::deluxe::DeluxeSensor. +/// \c rosa::app::AppSensor. /// -/// \see \c DeluxeSensorMasterInputHandlers +/// \see \c AppSensorMasterInputHandlers /// /// \note No pre- and post-conditions are validated directly by these functions, -/// they rather rely on \c rosa::deluxe::DeluxeSensor::saveMasterInput to do +/// they rather rely on \c rosa::app::AppSensor::saveMasterInput to do /// that. /// /// \param T the type of input to handle /// \param N name suffix for the function identifier -#define DSMASTERHANDLERDEFN(T, N) \ - void DSMASTERHANDLERNAME(N)(atoms::Master, id_t MasterId, token_size_t Pos, \ +#define ASMASTERHANDLERDEFN(T, N) \ + void ASMASTERHANDLERNAME(N)(atoms::Master, id_t MasterId, token_size_t Pos, \ T Value) noexcept { \ saveMasterInput(MasterId, Pos, Value); \ } -/// Convenience macro for \c DSMASTERHANDLERDEFN with identical arguments. +/// Convenience macro for \c ASMASTERHANDLERDEFN with identical arguments. /// -/// \see \c DSMASTERHANDLERDEFN +/// \see \c ASMASTERHANDLERDEFN /// -/// This macro can be used instead of \c DSMASTERHANDLERDEFN if the actual value +/// This macro can be used instead of \c ASMASTERHANDLERDEFN if the actual value /// of \p T can be used as a part of a valid identifier. /// /// \param T the type of input to handle -#define DSMASTERHANDLERDEF(T) DSMASTERHANDLERDEFN(T, T) +#define ASMASTERHANDLERDEF(T) ASMASTERHANDLERDEFN(T, T) /// Results in a \c THISMEMBER reference to a member function defined by -/// \c DSMASTERHANDLERDEFN. +/// \c ASMASTERHANDLERDEFN. /// -/// Used in the constructor of \c rosa::deluxe::DeluxeSensor to initialize super -/// class \c rosa::Agent with member function defined by \c DSMASTERHANDLERDEFN. +/// Used in the constructor of \c rosa::app::AppSensor to initialize super +/// class \c rosa::Agent with member function defined by \c ASMASTERHANDLERDEFN. /// -/// \see \c DSMASTERHANDLERDEFN, \c THISMEMBER +/// \see \c ASMASTERHANDLERDEFN, \c THISMEMBER /// /// \param N name suffix for the function identifier -#define DSMASTERHANDLERREF(N) THISMEMBER(DSMASTERHANDLERNAME(N)) +#define ASMASTERHANDLERREF(N) THISMEMBER(ASMASTERHANDLERNAME(N)) ///@} namespace rosa { -namespace deluxe { +namespace app { -/// Specialization of \c rosa::Agent for *sensor* role of the *deluxe +/// Specialization of \c rosa::Agent for *sensor* role of the *application /// interface*. /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// /// \invariant There is a compatible *execution policy* set; the actual value in -/// \c rosa::deluxe::DeluxeSensor::MasterInputNextPos is valid with respect to +/// \c rosa::app::AppSensor::MasterInputNextPos is valid with respect to /// the corresponding types. /// -/// \see Definition of \c rosa::deluxe::DeluxeSensor::inv on the class invariant +/// \see Definition of \c rosa::app::AppSensor::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 { +class AppSensor : public Agent { /// Checks whether \p this object holds the class invariant. /// - /// \see Invariant of the class \c rosa::deluxe::DeluxeSensor + /// \see Invariant of the class \c rosa::app::AppSensor /// /// \return if \p this object holds the class invariant bool inv(void) const noexcept; - /// The \c rosa::deluxe::DeluxeExecutionPolicy that controls the execution of + /// The \c rosa::app::AppExecutionPolicy that controls the execution of /// \c this object. - std::unique_ptr ExecutionPolicy; + std::unique_ptr ExecutionPolicy; public: /// The type of values produced by \p this object. /// /// That is the types of values \p this object sends to its *master* in a - /// \c rosa::deluxe::DeluxeTuple. + /// \c rosa::app::AppTuple. /// - /// \see \c rosa::deluxe::DeluxeSensor::master + /// \see \c rosa::app::AppSensor::master const Token OutputType; /// The type of values \p this object processes from its *master*. /// /// That is the types of values \p this object receives from its *master* in a - /// \c rosa::deluxe::DeluxeTuple. + /// \c rosa::app::AppTuple. /// - /// \see \c rosa::deluxe::DeluxeSensor::master + /// \see \c rosa::app::AppSensor::master const Token MasterInputType; private: /// Indicates which element of the master-input is expected from the *master*. /// - /// The *master* is supposed to send one \c rosa::deluxe::DeluxeTuple value + /// The *master* is supposed to send one \c rosa::app::AppTuple value /// element by element in their order of definition. This member field tells /// the element at which position should be received next. /// /// \p this object is supposed to be triggered only when a complete /// master-input has been received, that is the field should hold the value /// `0`. /// - /// \see \c rosa::deluxe::DeluxeSensor::handleTrigger - /// \c rosa::deluxe::DeluxeSensor::saveMasterInput + /// \see \c rosa::app::AppSensor::handleTrigger + /// \c rosa::app::AppSensor::saveMasterInput token_size_t MasterInputNextPos; /// Indicates whether the input value from the *master* has been changed since /// the last trigger received from the system. /// /// The flag is reset to \c false upon handling a trigger and then set to \c - /// true by \c rosa::deluxe::DeluxeSensor::saveMasterInput when storig a new - /// input value in \c rosa::deluxe::DeluxeSensor::MasterInputValue. + /// true by \c rosa::app::AppSensor::saveMasterInput when storig a new + /// input value in \c rosa::app::AppSensor::MasterInputValue. bool MasterInputChanged; /// Stores the actual input value from *master*. /// /// \note The type of the stored value matches the types indicated by \c - /// rosa::deluxe::DeluxeSensor::MasterInputType. + /// rosa::app::AppSensor::MasterInputType. const std::unique_ptr MasterInputValue; /// Alias for function objects used as trigger handler for - /// \c rosa::deluxe::DeluxeSensor. + /// \c rosa::app::AppSensor. /// /// \note The function used for \c H is to be \c noexcept. /// - /// \see \c DeluxeSensorTriggerHandlers + /// \see \c AppSensorTriggerHandlers using H = std::function; - /// \defgroup DeluxeSensorTriggerHandlers Trigger handlers of - /// rosa::deluxe::DeluxeSensor + /// \defgroup AppSensorTriggerHandlers Trigger handlers of + /// rosa::app::AppSensor /// - /// \brief Trigger handler functions of \c rosa::deluxe::DeluxeSensor + /// \brief Trigger handler functions of \c rosa::app::AppSensor /// /// The actual data source functions and master-input processing function are /// captured in lambda expressions that are in turn wrapped in \c /// std::function objects. The lambda expression calls a processing function, /// either to handle master-input or obtain the next sensory value from data /// source. The next sensory value is sent it to *master* by calling \c - /// rosa::deluxe::DeluxeSensor::sendToMaster. Also, the flag \c - /// rosa::deluxe::DeluxeSensor::MasterInputChanged is reset when the current + /// rosa::app::AppSensor::sendToMaster. Also, the flag \c + /// rosa::app::AppSensor::MasterInputChanged is reset when the current /// value is passed to the master-input processing function. The function \c - /// rosa::deluxe::DeluxeSensor::handleTrigger needs only to call the proper + /// rosa::app::AppSensor::handleTrigger needs only to call the proper /// function object. /// Processes master-input. /// - /// \ingroup DeluxeSensorTriggerHandlers + /// \ingroup AppSensorTriggerHandlers /// /// The function is called upon the sensor is trigged by the system. const H MFP; /// Produces the next sensory value during normal execution. /// - /// \ingroup DeluxeSensorTriggerHandlers + /// \ingroup AppSensorTriggerHandlers /// /// 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. + /// simulation environment sets \c rosa::app::AppSensor::SFP, which is + /// used instead of \c rosa::app::AppSensor::FP. const H FP; /// Produces the next sensory value during simulation. /// - /// \ingroup DeluxeSensorTriggerHandlers + /// \ingroup AppSensorTriggerHandlers /// /// 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 + /// \c rosa::app::AppSensor instance does not have any *master* at a /// given moment. Optional Master; /// Tells the unique identifier of the *master* of \p this object, if any /// registered. /// /// \return the unique identifier of the *master* /// /// \pre A *master* is registered for \p this object: \code /// Master /// \endcode id_t masterId(void) const noexcept; /// Wraps a master-input processing function into a trigger handler. /// - /// \see \c rosa::deluxe::DeluxeSensor::MFP and \c DeluxeSensorTriggerHandlers + /// \see \c rosa::app::AppSensor::MFP and \c AppSensorTriggerHandlers /// /// \tparam Ts types of elements of master-input processed by \p MF /// \tparam S0 indices for accessing master-input values /// /// \param MF function that processes master-input /// /// \note The second argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// - /// \note A master-input type of \c rosa::deluxe::EmptyDeluxeTuple indicates + /// \note A master-input type of \c rosa::app::EmptyAppTuple indicates /// that \p this object does not receive master-input, \p MF is never called /// if \p Ts is empty. /// /// \return trigger handler function based on \p MF /// /// \pre Statically, the indices match the elements: \code /// sizeof...(Ts) == sizeof...(S0) /// \endcode Dynamically, \p Ts... match \c - /// rosa::deluxe::DeluxeSensor::MasterInputType: \code - /// MasterInputType == DeluxeTuple::TT + /// rosa::app::AppSensor::MasterInputType: \code + /// MasterInputType == AppTuple::TT /// \endcode template H triggerHandlerFromProcessingFunction( - std::function, bool>)> &&MF, + std::function, bool>)> &&MF, Seq) noexcept; /// Wraps a data source function into a trigger handler. /// - /// \see \c rosa::deluxe::DeluxeSensor::FP, \c - /// rosa::deluxe::DeluxeSensor::SFP, and \c DeluxeSensorTriggerHandlers + /// \see \c rosa::app::AppSensor::FP, \c + /// rosa::app::AppSensor::SFP, and \c AppSensorTriggerHandlers /// /// \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 /// /// \return trigger handler function based on \p F /// /// \pre Statically, the type agument \p T is an instance of \c - /// rosa::deluxe::DeluxeTuple: \code - /// IsDeluxeTuple::Value + /// rosa::app::AppTuple: \code + /// IsAppTuple::Value /// \endcode Dynamically, \p T matches \c - /// rosa::deluxe::DeluxeSensor::OutputType: \code + /// rosa::app::AppSensor::OutputType: \code /// OutputType == T::TT /// \endcode template H triggerHandlerFromDataSource(std::function &&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*. + /// messages as defined for the *application interface*. /// /// \todo Enforce \p F and \p MF do not potentially throw exception. /// /// \tparam MT type of master-input handled by \p MF /// \tparam T type of data to operate on /// /// \note Instantiation fails if any of the type arguments \p MT and \p T is - /// not an instance of \c rosa::deluxe::DeluxeTuple or \p T is \c - /// rosa::deluxe::EmptyDeluxeTuple. + /// not an instance of \c rosa::app::AppTuple or \p T is \c + /// rosa::app::EmptyAppTuple. /// - /// \note If \p MT is \c rosa::deluxe::EmptyDeluxeTuple, the constructed + /// \note If \p MT is \c rosa::app::EmptyAppTuple, the constructed /// object does not receive master-input. /// /// \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 MF function to process master-input values with /// \param F function to generate the next value with during normal operation /// /// \pre Statically, \p MT and \p T are instances of \c - /// rosa::deluxe::DeluxeTuple and \p T contains at least one element:\code - /// TypeListAllDeluxeTuple>::Value && T::Length > 0 + /// rosa::app::AppTuple and \p T contains at least one element:\code + /// TypeListAllAppTuple>::Value && T::Length > 0 /// \endcode /// Dynamically, the instance is created as of kind - /// \c rosa::deluxe::atoms::SensorKind: + /// \c rosa::app::atoms::SensorKind: /// \code - /// Kind == rosa::deluxe::atoms::SensorKind + /// Kind == rosa::app::atoms::SensorKind /// \endcode /// - /// \see \c rosa::deluxe::DeluxeTuple - template < - typename MT, typename T, - typename = std::enable_if_t< - TypeListAllDeluxeTuple>::Value && (T::Length > 0)>> - DeluxeSensor(const AtomValue Kind, const id_t Id, const std::string &Name, - MessagingSystem &S, - std::function)> &&MF, - std::function &&F) noexcept; + /// \see \c rosa::app::AppTuple + template >::Value && (T::Length > 0)>> + AppSensor(const AtomValue Kind, const id_t Id, const std::string &Name, + MessagingSystem &S, std::function)> &&MF, + std::function &&F) noexcept; /// Destroys \p this object. - ~DeluxeSensor(void) noexcept; + ~AppSensor(void) noexcept; /// Returns the current execution policy of \p this object. /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \note The returned reference is valid only as long as \c - /// rosa::deluxe::DeluxeSensor::setExecutionPolicy() is not called and \p this + /// rosa::app::AppSensor::setExecutionPolicy() is not called and \p this /// object is not destroyed. /// - /// \return \c rosa::deluxe::DeluxeSensor::ExecutionPolicy - const DeluxeExecutionPolicy &executionPolicy(void) const noexcept; + /// \return \c rosa::app::AppSensor::ExecutionPolicy + const AppExecutionPolicy &executionPolicy(void) const noexcept; /// Sets the current execution policy of \p this object to \p EP. /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \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 &&EP) noexcept; + bool setExecutionPolicy(std::unique_ptr &&EP) noexcept; /// The *master* of \p this object, if any. /// - /// \see \c rosa::deluxe::DeluxeSensor::registerMaster + /// \see \c rosa::app::AppSensor::registerMaster /// /// \return the *master* registered for \p this object Optional 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*. /// - /// \note Any call to \c rosa::deluxe::DeluxeSensor::registerMaster should be + /// \note Any call to \c rosa::app::AppSensor::registerMaster should be /// paired with a corresponding call of \c - /// rosa::deluxe::DeluxeAgent::registerSlave, which validates that + /// rosa::app::AppAgent::registerSlave, which validates that /// input/output types of master and slave matches. /// /// \param _Master the *master* to register /// - /// \pre \p Master is empty or of kind \c rosa::deluxe::atoms::AgentKind: + /// \pre \p Master is empty or of kind \c rosa::app::atoms::AgentKind: /// \code - /// !_Master || unwrapAgent(*_Master).Kind == rosa::deluxe::atoms::AgentKind + /// !_Master || unwrapAgent(*_Master).Kind == rosa::app::atoms::AgentKind /// \endcode void registerMaster(const Optional _Master) noexcept; /// Clears the simulation trigger handler of \p this object. /// - /// The function assigns \c rosa::deluxe::DeluxeSensor::SFP with \c nullptr. + /// The function assigns \c rosa::app::AppSensor::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 + /// The function returns whether \c rosa::app::AppSensor::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 + /// \c rosa::app::AppSensor::SFP by overwriting any already registered /// simulation data source. /// /// \todo Enforce SF does not potentially throw exception. /// /// \tparam Ts types of elements of values provided by \p SF /// /// \param SF function to generate value with /// - /// \pre \p Ts... match \c rosa::deluxe::DeluxeSensor::OutputType: \code + /// \pre \p Ts... match \c rosa::app::AppSensor::OutputType: \code /// OutputType == TypeToken::Value /// \endcode template void registerSimulationDataSource( - std::function(void)> &&SF) noexcept; + std::function(void)> &&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 + /// \p Value is getting sent to \c rosa::app::AppSensor::Master if it + /// contains a valid handle for a \c rosa::app::AppAgent. The function /// does nothing otherwise. /// /// The elements from \p Value are sent one by one in separate messages to the /// *master*. /// /// \tparam Ts types of the elements in \p Value /// \tparam S0 indices for accessing elements of \p Value /// /// \param Value value to send /// /// \note The second argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// /// \pre Statically, the indices match the elements: \code /// sizeof...(Ts) == sizeof...(S0) /// \endcode Dynamically, \p Ts match \c - /// rosa::deluxe::DeluxeSensor::OutputType: \code + /// rosa::app::AppSensor::OutputType: \code /// OutputType == TypeToken::Value /// \endcode template - void sendToMaster(const DeluxeTuple &Value, Seq) noexcept; + void sendToMaster(const AppTuple &Value, Seq) noexcept; /// Handles master-input and generates the next sensory value upon trigger /// from the system. /// - /// Executes \c rosa::deluxe::DeluxeSensor::MFP for processing master-input - /// and data generating function \c rosa::deluxe::DeluxeSensor::FP or \c - /// rosa::deluxe::DeluxeSensor::SFP if set. + /// Executes \c rosa::app::AppSensor::MFP for processing master-input + /// and data generating function \c rosa::app::AppSensor::FP or \c + /// rosa::app::AppSensor::SFP if set. /// /// \note The only argument is a \c rosa::AtomConstant, hence its actual /// value is ignored. /// /// \pre Master-input is supposed to be completely received upon triggering: /// \code /// MasterInputNextPos == 0 /// \endcode void handleTrigger(atoms::Trigger) noexcept; /// Stores a new input value from the *master*. /// /// The function stores \p Value at position \p Pos in \c - /// rosa::deluxe::DeluxeSensor::MasterInputValue and also sets the - /// flag \c rosa::deluxe::DeluxeSensor::MasterInputChanged. The function also + /// rosa::app::AppSensor::MasterInputValue and also sets the + /// flag \c rosa::app::AppSensor::MasterInputChanged. The function also /// takes care of checking and updating \c - /// rosa::deluxe::DeluxeSensor::MasterInputNextPos: increments its value and + /// rosa::app::AppSensor::MasterInputNextPos: increments its value and /// resets it to `0` when the last element is received. /// /// \note Utilized by member functions of group \c - /// DeluxeSensorMasterInputHandlers. + /// AppSensorMasterInputHandlers. /// /// \tparam T type of input to store /// /// \param Id unique identifier of the *master* - /// \param Pos position of the value in the \c rosa::deluxe::DeluxeTuple + /// \param Pos position of the value in the \c rosa::app::AppTuple /// \param Value the input value to store /// /// \pre The *master* with \p Id is registered, \p Pos is the expected /// position of master-input, and the input from the *master* at position \p /// Pos is expected to be of type \p T: \code /// Master && masterId() == Id && Pos == MasterInputNextPos && /// typeAtPositionOfToken(MasterInputType, Pos) == TypeNumberOf::Value /// \endcode template void saveMasterInput(id_t Id, token_size_t Pos, T Value) noexcept; - /// \defgroup DeluxeSensorMasterInputHandlers Master-input handlers of - /// rosa::deluxe::DeluxeSensor + /// \defgroup AppSensorMasterInputHandlers Master-input handlers of + /// rosa::app::AppSensor /// /// Definition of member functions handling messages from the *master* with /// different types of input /// /// A *slave* generally needs to be prepared to deal with values of any /// built-in type to handle messages from its *master*. Each type requires a /// separate message handler, which are implemented by these functions. The - /// functions instantiate \c rosa::deluxe::DeluxeSensor::saveMasterInput with + /// functions instantiate \c rosa::app::AppSensor::saveMasterInput with /// the proper template argument and pass the content of the message on for /// processing. /// /// \note The member functions in this group are defined by \c - /// DSMASTERHANDLERDEF. + /// ASMASTERHANDLERDEF. /// /// \note Keep these definitions in sync with \c rosa::BuiltinTypes. /// ///@{ - DSMASTERHANDLERDEF(AtomValue) - DSMASTERHANDLERDEF(int16_t) - DSMASTERHANDLERDEF(int32_t) - DSMASTERHANDLERDEF(int64_t) - DSMASTERHANDLERDEF(int8_t) - DSMASTERHANDLERDEFN(long double, long_double) - DSMASTERHANDLERDEFN(std::string, std__string) - DSMASTERHANDLERDEF(uint16_t) - DSMASTERHANDLERDEF(uint32_t) - DSMASTERHANDLERDEF(uint64_t) - DSMASTERHANDLERDEF(uint8_t) - DSMASTERHANDLERDEF(unit_t) - DSMASTERHANDLERDEF(bool) - DSMASTERHANDLERDEF(double) - DSMASTERHANDLERDEF(float) + ASMASTERHANDLERDEF(AtomValue) + ASMASTERHANDLERDEF(int16_t) + ASMASTERHANDLERDEF(int32_t) + ASMASTERHANDLERDEF(int64_t) + ASMASTERHANDLERDEF(int8_t) + ASMASTERHANDLERDEFN(long double, long_double) + ASMASTERHANDLERDEFN(std::string, std__string) + ASMASTERHANDLERDEF(uint16_t) + ASMASTERHANDLERDEF(uint32_t) + ASMASTERHANDLERDEF(uint64_t) + ASMASTERHANDLERDEF(uint8_t) + ASMASTERHANDLERDEF(unit_t) + ASMASTERHANDLERDEF(bool) + ASMASTERHANDLERDEF(double) + ASMASTERHANDLERDEF(float) /// @} }; template -DeluxeSensor::H DeluxeSensor::triggerHandlerFromProcessingFunction( - std::function, bool>)> &&MF, +AppSensor::H AppSensor::triggerHandlerFromProcessingFunction( + std::function, bool>)> &&MF, Seq) noexcept { - using MT = DeluxeTuple; + using MT = AppTuple; STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent arguments"); ASSERT(MasterInputType == MT::TT); -// NOTE: Clang 6 warns about unused lambda captures; we suppress that -// warning (those variables need to be captured). -ROSA_DISABLE_WARNING_PUSH; -ROSA_DISABLE_WARNING_UNUSED_LAMBDA_CAPTURE; + // NOTE: Clang 6 warns about unused lambda captures; we suppress that + // warning (those variables need to be captured). + ROSA_DISABLE_WARNING_PUSH; + ROSA_DISABLE_WARNING_UNUSED_LAMBDA_CAPTURE; return [ this, MF ](void) noexcept { // Do not do anything for master-input type \c - // rosa::deluxe::EmptyDeluxeTuple. - if - constexpr(!std::is_same::value) { - LOG_TRACE_STREAM << "DeluxeSensor " << FullName - << " handles master-input." << std::endl; - // The assert must hold if \p this object was successfully constructed. - STATIC_ASSERT( - (true && ... && - (static_cast(static_cast(S0)) == S0)), - "Unexpected error"); - const auto MasterInputArg = std::make_pair( - // Get all elements of the tuple in a fold expression. - DeluxeTuple(*static_cast( - MasterInputValue->pointerTo(static_cast(S0)))...), - MasterInputChanged); - MasterInputChanged = false; - MF(MasterInputArg); - } + // rosa::app::EmptyAppTuple. + if constexpr (!std::is_same::value) { + LOG_TRACE_STREAM << "AppSensor " << FullName << " handles master-input." + << std::endl; + // The assert must hold if \p this object was successfully constructed. + STATIC_ASSERT( + (true && ... && + (static_cast(static_cast(S0)) == S0)), + "Unexpected error"); + const auto MasterInputArg = std::make_pair( + // Get all elements of the tuple in a fold expression. + AppTuple(*static_cast( + MasterInputValue->pointerTo(static_cast(S0)))...), + MasterInputChanged); + MasterInputChanged = false; + MF(MasterInputArg); + } }; -ROSA_DISABLE_WARNING_POP; + ROSA_DISABLE_WARNING_POP; } template -DeluxeSensor::H -DeluxeSensor::triggerHandlerFromDataSource(std::function &&F, - bool inSimulation) noexcept { - STATIC_ASSERT(IsDeluxeTuple::Value, "not tuple type argument"); +AppSensor::H +AppSensor::triggerHandlerFromDataSource(std::function &&F, + bool inSimulation) noexcept { + STATIC_ASSERT(IsAppTuple::Value, "not tuple type argument"); ASSERT(OutputType == T::TT); return [ this, F, inSimulation ](void) noexcept { // Get value and send it to master only if \p ExecutionPolicy allows it. if (ExecutionPolicy->shouldProcess({})) { - LOG_TRACE_STREAM << "DeluxeSensor " << Name << " obtains next value." + LOG_TRACE_STREAM << "AppSensor " << Name << " obtains next value." << std::endl; sendToMaster(F(), seq_t()); } else { - LOG_TRACE_STREAM << "DeluxeSensor " << Name << " skips next value." + LOG_TRACE_STREAM << "AppSensor " << Name << " skips next value." << std::endl; if (inSimulation) { // But read input value in Simulation anyway as input values are // provided for the highest execution frequency for simulation (void)F(); } } }; } template -DeluxeSensor::DeluxeSensor(const AtomValue Kind, const id_t Id, - const std::string &Name, MessagingSystem &S, - std::function)> &&MF, - std::function &&F) noexcept +AppSensor::AppSensor(const AtomValue Kind, const id_t Id, + const std::string &Name, MessagingSystem &S, + std::function)> &&MF, + std::function &&F) noexcept : Agent(Kind, Id, Name, S, THISMEMBER(handleTrigger), - DSMASTERHANDLERREF(AtomValue), DSMASTERHANDLERREF(int16_t), - DSMASTERHANDLERREF(int32_t), DSMASTERHANDLERREF(int64_t), - DSMASTERHANDLERREF(int8_t), DSMASTERHANDLERREF(long_double), - DSMASTERHANDLERREF(std__string), DSMASTERHANDLERREF(uint16_t), - DSMASTERHANDLERREF(uint32_t), DSMASTERHANDLERREF(uint64_t), - DSMASTERHANDLERREF(uint8_t), DSMASTERHANDLERREF(unit_t), - DSMASTERHANDLERREF(bool), DSMASTERHANDLERREF(double), - DSMASTERHANDLERREF(float)), - ExecutionPolicy(DeluxeExecutionPolicy::decimation(1)), OutputType(T::TT), + ASMASTERHANDLERREF(AtomValue), ASMASTERHANDLERREF(int16_t), + ASMASTERHANDLERREF(int32_t), ASMASTERHANDLERREF(int64_t), + ASMASTERHANDLERREF(int8_t), ASMASTERHANDLERREF(long_double), + ASMASTERHANDLERREF(std__string), ASMASTERHANDLERREF(uint16_t), + ASMASTERHANDLERREF(uint32_t), ASMASTERHANDLERREF(uint64_t), + ASMASTERHANDLERREF(uint8_t), ASMASTERHANDLERREF(unit_t), + ASMASTERHANDLERREF(bool), ASMASTERHANDLERREF(double), + ASMASTERHANDLERREF(float)), + ExecutionPolicy(AppExecutionPolicy::decimation(1)), OutputType(T::TT), MasterInputType(MT::TT), MasterInputNextPos(0), MasterInputChanged(false), MasterInputValue(new typename TokenizedStorageForTypeList< - typename UnwrapDeluxeTuple::Type>::Type()), + typename UnwrapAppTuple::Type>::Type()), MFP(triggerHandlerFromProcessingFunction(std::move(MF), seq_t())), FP(triggerHandlerFromDataSource(std::move(F), false)), SFP(nullptr) { ASSERT(Kind == atoms::SensorKind); - LOG_TRACE_STREAM << "DeluxeSensor " << FullName << " is created." - << std::endl; + LOG_TRACE_STREAM << "AppSensor " << FullName << " is created." << std::endl; ASSERT(inv()); } template -void DeluxeSensor::registerSimulationDataSource( - std::function(void)> &&SF) noexcept { +void AppSensor::registerSimulationDataSource( + std::function(void)> &&SF) noexcept { ASSERT(OutputType == TypeToken::Value); SFP = triggerHandlerFromDataSource(std::move(SF), true); ASSERT(inv()); } template -void DeluxeSensor::sendToMaster(const DeluxeTuple &Value, - Seq) noexcept { +void AppSensor::sendToMaster(const AppTuple &Value, + Seq) noexcept { STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent arguments"); ASSERT(OutputType == TypeToken::Value); // The assert must hold if \p this object was successfully constructed. STATIC_ASSERT((true && ... && (static_cast(static_cast(S0)) == S0)), "Unexpected error"); // Create a static constant array for these indices to be available as lvalue // references when creating messages below. \c S0... when used directly in a // fold expression is a temporary value, which would result in \c // rosa::Message instances being created with rvalue references. Further, all // other values would to copied into a temporary variable for making them /// available as rvalue references (they are constant lvalue references here). static constexpr std::array Indices{{S0...}}; - LOG_TRACE_STREAM << "DeluxeSensor " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppSensor " << FullName << "(" << Id << ") sends to master(" << static_cast(Master && *Master) << "): " << Value << std::endl; // There is a handle and the referred *master* is in a valid state. if (Master && *Master) { // Handle each element of the tuple in a fold expression. (Master->sendMessage(Message::create(atoms::Slave::Value, Id, Indices[S0], std::get(Value))), ...); } ASSERT(inv()); } template -void DeluxeSensor::saveMasterInput(id_t Id, token_size_t Pos, - T Value) noexcept { +void AppSensor::saveMasterInput(id_t Id, token_size_t Pos, T Value) noexcept { ASSERT(Master && masterId() == Id && Pos == MasterInputNextPos && typeAtPositionOfToken(MasterInputType, Pos) == TypeNumberOf::Value); - LOG_TRACE_STREAM << "DeluxeSensor " << FullName << "(" << Id + LOG_TRACE_STREAM << "AppSensor " << FullName << "(" << Id << ") saves value from master: (" << static_cast(Pos) << ") " << Value << std::endl; // Save value. *static_cast(MasterInputValue->pointerTo(Pos)) = Value; // Update position of next value. if (++MasterInputNextPos == lengthOfToken(MasterInputType)) { MasterInputNextPos = 0; } // Set flag. MasterInputChanged = true; } -} // End namespace deluxe +} // End namespace app } // End namespace rosa -#undef DSMASTERHANDLEREF -#undef DSMASTERHANDLEDEF -#undef DSMASTERHANDLEDEFN -#undef DSMASTERHANDLENAME +#undef ASMASTERHANDLEREF +#undef ASMASTERHANDLEDEF +#undef ASMASTERHANDLEDEFN +#undef ASMASTERHANDLENAME -#endif // ROSA_DELUXE_DELUXESENSOR_HPP +#endif // ROSA_APP_APPSENSOR_HPP diff --git a/include/rosa/app/AppSystem.hpp b/include/rosa/app/AppSystem.hpp new file mode 100644 index 0000000..fb8b859 --- /dev/null +++ b/include/rosa/app/AppSystem.hpp @@ -0,0 +1,243 @@ +//===-- rosa/app/AppSystem.hpp ----------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +// Distributed under the terms and conditions of the Boost Software License 1.0. +// See accompanying file LICENSE. +// +// If you did not receive a copy of the license file, see +// http://www.boost.org/LICENSE_1_0.txt. +// +//===----------------------------------------------------------------------===// +/// +/// \file rosa/app/AppSystem.hpp +/// +/// \author David Juhasz (david.juhasz@tuwien.ac.at) +/// +/// \date 2017-2020 +/// +/// \brief Specialization of \c rosa::MessagingSystem for the *application +/// interface*. +/// +/// \see \c rosa::app::Application +/// +//===----------------------------------------------------------------------===// + +#ifndef ROSA_APP_APPSYSTEM_HPP +#define ROSA_APP_APPSYSTEM_HPP + +#include "rosa/core/MessagingSystem.hpp" + +#include "rosa/app/AppAgent.hpp" +#include "rosa/app/AppSensor.hpp" + +namespace rosa { +namespace app { + +/// Implements and extends the \c rosa::MessagingSystem interface to be +/// used by \c rosa::app::Application. +/// +/// The class is a specialization of \c rosa::MessagingSystem, where objects +/// of two specialized subtypes of \c rosa::Agent, \c rosa::app::AppSensor +/// and \c rosa::app::AppAgent, constitute a system. The class extends the +/// \c rosa::MessagingSystem interface with features required to implement the +/// *application interface*. +/// +/// \see rosa::app::Application +class AppSystem : public MessagingSystem { + + friend class Application; + friend class AppExecutionPolicy; + +public: + /// Returns an object implementing the \c rosa::app::AppSystem + /// interface. + /// + /// \param Name name of the new instance + /// + /// \return \c std::unique_ptr for the new instance of + /// \c rosa::AppSystem + static std::unique_ptr + createSystem(const std::string &Name) noexcept; + +protected: + /// Creates a new instance. + /// + /// \note Protected constructor restricts instantiation for subclasses. + AppSystem(void) noexcept = default; + +public: + /// Creates a \c rosa::app::AppSensor instance owned by \p this object + /// and returns a \p rosa::AgentHandle for it. + /// + /// \tparam MT type of master-input the new \c rosa::app::AppSensor + /// receives + /// \tparam T type of data the new \c rosa::app::AppSensor operates on + /// + /// \note Type arguments \p MT and \p T must be instances of \c + /// rosa::app::AppTuple. + /// + /// \param Name name of the new \c rosa::app::AppSensor + /// \param MF function to process master-input values + /// \param F function to generate the next value with during normal operation + /// + /// \see \c rosa::app::AppSensor::AppSensor. + /// + /// \return \c rosa::AgentHandle for new \c rosa::app::AppSensor + template + AgentHandle createSensor(const std::string &Name, + std::function)> &&MF, + std::function &&F) noexcept; + + /// Creates a \c rosa::app::AppAgent instance owned by \p this object + /// and returns a \c rosa::AgentHandle for it. + /// + /// \tparam MT type of master-input the new \c rosa::app::AppAgent + /// receives + /// \tparam T type of data the new \c rosa::app::AppAgent outputs + /// \tparam Ts types of master-output the new \c rosa::app::AppAgent + /// produces + /// \tparam As types of inputs the new \c rosa::app::AppAgent takes + /// + /// \note Type arguments \p MT, \p T, \p Ts..., and \p As... must be + /// instances of \c rosa::app::AppTuple. + /// + /// \param Name name of the new \c rosa::app::AppAgent + /// \param MF function for the new \c rosa::app::AppAgent to process + /// master-input values and generate master-output with + /// \param F function for the new \c rosa::app::AppAgent to process + /// input values and generate output and master-output with + /// + /// \see \c rosa::app::AppAgent::AppAgent. + /// + /// \return \c rosa::AgentHandle for new \c rosa::app::AppAgent + template + AgentHandle createAgent( + const std::string &Name, + std::function...>(std::pair)> &&MF, + std::function, Optional...>( + std::pair...)> &&F) noexcept; + +protected: + /// Tells whether a \c rosa::AgentHandle refers to a + /// \c rosa::app::AppSensor owned by \p this object. + /// + /// \param H \c rosa::AgentHandle to check + /// + /// \return whether \p H refers to a \c rosa::app::AppSensor owned by + /// \p this object + virtual bool isAppSensor(const AgentHandle &H) const noexcept = 0; + + /// Extracts a const qualified \c rosa::app::AppSensor reference from a + /// const qualified \c rosa::AgentHandle if possible. + /// + /// The function returns a \c rosa::Optional object containing a const + /// qualified reference to a \c rosa::app::AppSensor object extracted + /// from a const qualified \c rosa::AgentHandle instance if the referred + /// object is of type \c rosa::appAppSensor and owned by \p this object. + /// The returned \c rosa::Optional object is empty otherwise. + /// + /// \see rosa::app::AppSystem::isAppSensor + /// + /// \param H \c rosa::AgentHandle to extract a \c rosa::app::AppSensor + /// from + /// + /// \return const qualified reference to \c rosa::app::AppSensor if + /// \p H refers to an object which is of that type and is owned by \p this + /// object + Optional getAppSensor(const AgentHandle &H) const noexcept; + + /// Extracts a \c rosa::app::AppSensor reference from a + /// \c rosa::AgentHandle if possible. + /// + /// The function returns a \c rosa::Optional object containing a reference to + /// a \c rosa::app::AppSensor object extracted from a + /// \c rosa::AgentHandle instance if the referred object is of type + /// \c rosa::appAppSensor and owned by \p this object. The returned + /// \c rosa::Optional object is empty otherwise. + /// + /// \see rosa::app::AppSystem::isAppSensor + /// + /// \param H \c rosa::AgentHandle to extract a \c rosa::app::AppSensor + /// from + /// + /// \return reference to \c rosa::app::AppSensor if \p H refers to an + /// object which is of that type and is owned by \p this object + Optional getAppSensor(AgentHandle &H) const noexcept; + + /// Tells whether a \c rosa::AgentHandle refers to a + /// \c rosa::app::AppAgent owned by \p this object. + /// + /// \param H \c rosa::AgentHandle to check + /// + /// \return whether \p H refers to a \c rosa::app::AppAgent owned by + /// \p this object + virtual bool isAppAgent(const AgentHandle &H) const noexcept = 0; + + /// Extracts a const qualified \c rosa::app::AppAgent reference from a + /// const qualified \c rosa::AgentHandle if possible. + /// + /// The function returns a \c rosa::Optional object containing a const + /// qualified reference to a \c rosa::app::AppAgent object extracted + /// from a const qualified \c rosa::AgentHandle instance if the referred + /// object is of type \c rosa::appAppAgent and owned by \p this object. + /// The returned \c rosa::Optional object is empty otherwise. + /// + /// \see rosa::app::AppSystem::isAppAgent + /// + /// \param H \c rosa::AgentHandle to extract a \c rosa::app::AppAgent + /// from + /// + /// \return const qualified reference to \c rosa::app::AppAgent if \p H + /// refers to an object which is of that type and is owned by \p this object + Optional getAppAgent(const AgentHandle &H) const noexcept; + + /// Extracts a \c rosa::app::AppAgent reference from a + /// \c rosa::AgentHandle if possible. + /// + /// The function returns a \c rosa::Optional object containing a reference to + /// a \c rosa::app::AppAgent object extracted from a + /// \c rosa::AgentHandle instance if the referred object is of type + /// \c rosa::app::AppAgent and owned by \p this object. The returned + /// \c rosa::Optional object is empty otherwise. + /// + /// \see rosa::app::AppSystem::isAppAgent + /// + /// \param H \c rosa::AgentHandle to extract a \c rosa::app::AppAgent + /// from + /// + /// \return reference to \c rosa::app::AppAgent if \p H refers to an + /// object which is of that type and is owned by \p this object + Optional getAppAgent(AgentHandle &H) const noexcept; +}; + +template +AgentHandle +AppSystem::createSensor(const std::string &Name, + std::function)> &&MF, + std::function &&F) noexcept { + Agent &AS = createUnit( + [&](const id_t Id, MessagingSystem &S) { + return new AppSensor(atoms::SensorKind, Id, Name, S, std::move(MF), + std::move(F)); + }); + return {AS}; +} + +template +AgentHandle AppSystem::createAgent( + const std::string &Name, + std::function...>(std::pair)> &&MF, + std::function, Optional...>( + std::pair...)> &&F) noexcept { + Agent &AA = createUnit([&](const id_t Id, AppSystem &S) { + return new AppAgent(atoms::AgentKind, Id, Name, S, std::move(MF), + std::move(F)); + }); + return {AA}; +} + +} // End namespace app +} // End namespace rosa + +#endif // ROSA_APP_APPSYSTEM_HPP diff --git a/include/rosa/deluxe/DeluxeTuple.hpp b/include/rosa/app/AppTuple.hpp similarity index 55% rename from include/rosa/deluxe/DeluxeTuple.hpp rename to include/rosa/app/AppTuple.hpp index 5e999e0..e6f133b 100644 --- a/include/rosa/deluxe/DeluxeTuple.hpp +++ b/include/rosa/app/AppTuple.hpp @@ -1,425 +1,421 @@ -//===-- rosa/deluxe/DeluxeTuple.hpp -----------------------------*- C++ -*-===// +//===-- rosa/app/AppTuple.hpp -----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeTuple.hpp +/// \file rosa/app/AppTuple.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \brief Facilities for handling multiple input/output values for connections -/// in the *deluxe interface*. +/// in the *application interface*. /// -/// \see \c rosa::deluxe::DeluxeContext +/// \see \c rosa::app::Application /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXETUPLE_HPP -#define ROSA_DELUXE_DELUXETUPLE_HPP +#ifndef ROSA_APP_APPTUPLE_HPP +#define ROSA_APP_APPTUPLE_HPP #include "rosa/support/sequence.hpp" #include "rosa/support/type_token.hpp" #include #include namespace rosa { -namespace deluxe { +namespace app { -/// A tuple to manage multiple input/output values in the *deluxe interface*. +/// A tuple to manage multiple input/output values in the *application +/// interface*. /// /// \tparam Ts types of elements of the tuple /// /// \note The template may be instantiated only with built-in types and the /// number of those type may not exceed the capacity of a \c rosa::Token. -template -struct DeluxeTuple : public std::tuple { +template struct AppTuple : public std::tuple { // Statically enforce that the class template is instantiated only with // built-in types. STATIC_ASSERT((TypeListSubsetOf, BuiltinTypes>::Value), "not built-in types"); // Statically enforce that the class template is instantiated with not too // many types. - // \note Instantiation would fail on \c rosa::deluxe::DeluxeTuple::TT if there + // \note Instantiation would fail on \c rosa::app::AppTuple::TT if there // are too many types; this assertion is for more readable error reporting. STATIC_ASSERT(sizeof...(Ts) <= token::MaxTokenizableListSize, "Too many types"); /// How many elements the instance has. static constexpr token_size_t Length = sizeof...(Ts); /// What types the class contains. /// /// Type information encoded as \c rosa::Token. static constexpr Token TT = TypeToken::Value; /// Default constructor, zero-initializes elements. - DeluxeTuple(void) = default; + AppTuple(void) = default; /// Constructor, initializes the underlying \c std::tuple with lvalue /// references. /// /// \param Args value references to the values to store - DeluxeTuple(const std::decay_t &... Args) : std::tuple(Args...) {} + AppTuple(const std::decay_t &... Args) : std::tuple(Args...) {} /// Constructor, initializes the underlying \c std::tuple with rvalue /// references. /// /// \param Args rvalue references to the values to store - DeluxeTuple(std::decay_t &&... Args) + AppTuple(std::decay_t &&... Args) : std::tuple(std::move(Args)...) {} /// Contructor, initializes the underlying \c std::tuple from another matching /// \c std::tuple. - DeluxeTuple(const std::tuple &Args) : std::tuple(Args) {} + AppTuple(const std::tuple &Args) : std::tuple(Args) {} /// Default copy-constructor. - DeluxeTuple(const DeluxeTuple &) = default; + AppTuple(const AppTuple &) = default; /// Default move-constructor. - DeluxeTuple(DeluxeTuple &&) = default; + AppTuple(AppTuple &&) = default; /// Default copy-assignment. - DeluxeTuple &operator=(const DeluxeTuple &) = default; + AppTuple &operator=(const AppTuple &) = default; /// Default move-assignment. - DeluxeTuple &operator=(DeluxeTuple &&) = default; + AppTuple &operator=(AppTuple &&) = default; private: /// Dumps \p this object to a given \c std::ostream. /// - /// \note Provides implementation for \c rosa::deluxe::DeluxeTuple::dump. + /// \note Provides implementation for \c rosa::app::AppTuple::dump. /// /// \tparam S0 Indices for accessing elements. /// /// \param [in,out] OS output stream to dump to /// /// \note The second argument provides indices statically as template /// arguments \p S0..., so its actual value is ignored. /// /// \pre Statically, \p S0... matches number of types \p this object was /// created: \code /// sizeof...(S0) == sizeof...(Ts) /// \endcode template void dump(std::ostream &OS, Seq) const noexcept; public: /// Dumps \p this object to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to void dump(std::ostream &OS) const noexcept; }; template template -void DeluxeTuple::dump(std::ostream &OS, Seq) const noexcept { +void AppTuple::dump(std::ostream &OS, Seq) const noexcept { STATIC_ASSERT(sizeof...(S0) == sizeof...(Ts), "inconsistent type arguments"); // Convert value to std::string with std::to_string except for a value of // std::string that does not need conversion. auto dump_to_string = [](const auto &V) { if constexpr (std::is_same, std::string>::value) { return V; } else { return std::to_string(V); } }; OS << "{"; (OS << ... << (" " + dump_to_string(std::get(*this)))); OS << " }"; } template -void DeluxeTuple::dump(std::ostream &OS) const noexcept { +void AppTuple::dump(std::ostream &OS) const noexcept { dump(OS, seq_t()); } -/// Type alias for a \c rosa::deluxe::DeluxeTuple that contains no elements. -using EmptyDeluxeTuple = DeluxeTuple<>; +/// Type alias for a \c rosa::app::AppTuple that contains no elements. +using EmptyAppTuple = AppTuple<>; -/// Template specialization for \c rosa::deluxe::EmptyDeluxeTuple. -template <> struct DeluxeTuple<> : public std::tuple<> { +/// Template specialization for \c rosa::app::EmptyAppTuple. +template <> struct AppTuple<> : public std::tuple<> { /// How many elements the instance has. static constexpr token_size_t Length = 0; /// What types the class contains. /// /// Type information encoded as \c rosa::Token. static constexpr Token TT = TypeToken<>::Value; /// Constructor, initializes the underlying \c std::tuple. - DeluxeTuple(void) : std::tuple<>() {} + AppTuple(void) : std::tuple<>() {} /// Default copy-constructor. - DeluxeTuple(const DeluxeTuple &) = default; + AppTuple(const AppTuple &) = default; // Default move-constructor. - DeluxeTuple(DeluxeTuple &&) = default; + AppTuple(AppTuple &&) = default; /// Default copy-assignment. - DeluxeTuple &operator=(const DeluxeTuple &) = default; + AppTuple &operator=(const AppTuple &) = default; // Default move-assignment, - DeluxeTuple &operator=(DeluxeTuple &&) = default; + AppTuple &operator=(AppTuple &&) = default; /// Dumps \p this object to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to static void dump(std::ostream &OS) noexcept; }; -/// Creates a \c rosa::deluxe::DeluxeTuple instance from the given lvalues +/// Creates a \c rosa::app::AppTuple instance from the given lvalues /// references. /// /// \tparam Ts types of elements of the tuple /// -/// \see \c rosa::deluxe::DeluxeTuple +/// \see \c rosa::app::AppTuple /// /// \param Args values to store in the tuple /// -/// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as +/// \return an instance of \c rosa::app::AppTuple with \p Args as /// elements template -inline DeluxeTuple make_deluxe_tuple(const Ts &... Args) noexcept { - return DeluxeTuple(Args...); +inline AppTuple make_app_tuple(const Ts &... Args) noexcept { + return AppTuple(Args...); } -/// Creates a \c rosa::deluxe::DeluxeTuple instance from the given rvalue +/// Creates a \c rosa::app::AppTuple instance from the given rvalue /// references. /// /// \tparam Ts types of elements of the tuple /// -/// \see \c rosa::deluxe::DeluxeTuple +/// \see \c rosa::app::AppTuple /// /// \param Args values to store in the tuple /// -/// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as +/// \return an instance of \c rosa::app::AppTuple with \p Args as /// elements template -inline DeluxeTuple make_deluxe_tuple(Ts&&... Args) noexcept { - return DeluxeTuple(std::move(Args)...); +inline AppTuple make_app_tuple(Ts &&... Args) noexcept { + return AppTuple(std::move(Args)...); } -/// Creates a \c rosa::deluxe::DeluxeTuple instance from the given \c std::tuple +/// Creates a \c rosa::app::AppTuple instance from the given \c std::tuple /// reference. /// /// \tparam Ts types of elements of the tuple /// -/// \see \c rosa::deluxe::DeluxeTuple +/// \see \c rosa::app::AppTuple /// /// \param Args values to store in the tuple /// -/// \return an instance of \c rosa::deluxe::DeluxeTuple with \p Args as +/// \return an instance of \c rosa::app::AppTuple with \p Args as /// elements template -inline DeluxeTuple -make_deluxe_tuple(const std::tuple &Args) noexcept { - return DeluxeTuple(Args); +inline AppTuple make_app_tuple(const std::tuple &Args) noexcept { + return AppTuple(Args); } -/// \defgroup UnwrapDeluxeTuple Implementation of -/// rosa::deluxe::UnwrapDeluxeTuple +/// \defgroup UnwrapAppTuple Implementation of +/// rosa::app::UnwrapAppTuple /// /// \brief Unwraps element types from an instance of \c -/// rosa::deluxe::DeluxeTuple into a \c rosa::TypeList +/// rosa::app::AppTuple into a \c rosa::TypeList /// -/// Types can be unwrapped from a \c rosa::deluxe::DeluxeTuple instance as \code -/// typename UnwrapDeluxeTuple::Type +/// Types can be unwrapped from a \c rosa::app::AppTuple instance as \code +/// typename UnwrapAppTuple::Type /// \endcode /// /// For example, the following expression evaluates to `true`: \code -/// std::is_same>::Type, +/// std::is_same>::Type, /// TypeList>::value /// \endcode ///@{ /// Declaration of the template. /// -/// \tparam Tuple \c rosa::deluxe::DeluxeTuple to unwrap -template struct UnwrapDeluxeTuple; +/// \tparam Tuple \c rosa::app::AppTuple to unwrap +template struct UnwrapAppTuple; -/// Implementation of the template for \c rosa::deluxe::DeluxeTuple instances. -template struct UnwrapDeluxeTuple> { +/// Implementation of the template for \c rosa::app::AppTuple instances. +template struct UnwrapAppTuple> { using Type = TypeList; }; ///@} ///@} -/// \defgroup IsTuple Implementation of \c rosa::deluxe::IsTuple +/// \defgroup IsTuple Implementation of \c rosa::app::IsTuple /// /// \brief Tells if a type is a tuple as in it can be converted to \c -/// rosa::deluxe::DeluxeTuple. +/// rosa::app::AppTuple. /// -/// \see \c rosa::deluxe::MatchingDeluxeTuple +/// \see \c rosa::app::MatchingAppTuple /// /// Whether a type \c T is a tuple can be checked as \code /// IsTuple::Value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam T type to check template struct IsTuple; /// Specialization for the case when the type is an instance of \c std::tuple. template struct IsTuple> { static constexpr bool Value = true; }; /// Specialization for the case when the type is an instance of \c std::tuple. -template struct IsTuple> { +template struct IsTuple> { static constexpr bool Value = true; }; /// Implementation for a general case of type \p T. template struct IsTuple { static constexpr bool Value = false; }; ///@} -/// \defgroup IsDeluxeTuple Implementation of \c rosa::deluxe::IsDeluxeTuple +/// \defgroup IsAppTuple Implementation of \c rosa::app::IsAppTuple /// -/// \brief Tells if a type is an instance of \c rosa::deluxe::DeluxeTuple. +/// \brief Tells if a type is an instance of \c rosa::app::AppTuple. /// -/// Whether a type \c T is an instance of \c rosa::deluxe::DeluxeTuple can be +/// Whether a type \c T is an instance of \c rosa::app::AppTuple can be /// checked as \code -/// IsDeluxeTuple::Value +/// IsAppTuple::Value /// \endcode /// -/// \note `!IsDeluxeTuple::Value || IsTuple::Value` +/// \note `!IsAppTuple::Value || IsTuple::Value` ///@{ /// Declaration of the template. /// /// \tparam T type to check -template struct IsDeluxeTuple; +template struct IsAppTuple; /// Specialization for the case when the type is an instance of \c -/// rosa::deluxe::DeluxeTuple. -template -struct IsDeluxeTuple> { +/// rosa::app::AppTuple. +template struct IsAppTuple> { static constexpr bool Value = true; }; /// Implementation for a general case of type \p T. -template -struct IsDeluxeTuple { +template struct IsAppTuple { static constexpr bool Value = false; }; ///@} -/// \defgroup MatchingDeluxeTuple Implementation of \c -/// rosa::deluxe::MatchingDeluxeTuple +/// \defgroup MatchingAppTuple Implementation of \c +/// rosa::app::MatchingAppTuple /// -/// \brief Gives the \c rosa::deluxe::DeluxeTuple type that matches a given +/// \brief Gives the \c rosa::app::AppTuple type that matches a given /// tuple type. /// -/// The matching \c rosa::deluxe::DeluxeTuple type for a tuple type \p T can be +/// The matching \c rosa::app::AppTuple type for a tuple type \p T can be /// obtained as \code -/// typename MatchingDeluxeTuple::Type +/// typename MatchingAppTuple::Type /// \endcode -/// If \p T is \c rosa::deluxe::DeluxeTuple, the matching type is \p T itself. -/// If \p T is \c std::tuple, the matching type if \c rosa::deluxe::DeluxeTuple +/// If \p T is \c rosa::app::AppTuple, the matching type is \p T itself. +/// If \p T is \c std::tuple, the matching type if \c rosa::app::AppTuple /// with the same type parameters as \p T. -/// \c rosa::deluxe::MatchingDeluxeTuple is not defined for other type +/// \c rosa::app::MatchingAppTuple is not defined for other type /// parameters. /// /// \note The template is defined for type \p T only if -/// `rosa::deluxe::IsTuple::Value`. Values of such types can be used to -/// construct a new instance of the class \c rosa::deluxe::DeluxeTuple. +/// `rosa::app::IsTuple::Value`. Values of such types can be used to +/// construct a new instance of the class \c rosa::app::AppTuple. /// -///\see \c rosa::deluxe::IsTuple +///\see \c rosa::app::IsTuple ///@{ /// Declaration of the template. /// /// \tparam T type to check -template struct MatchingDeluxeTuple; +template struct MatchingAppTuple; /// Specialization for the case when the type is an instance of \c -/// rosa::deluxe::DeluxeTuple. -template struct MatchingDeluxeTuple> { - using Type = DeluxeTuple; +/// rosa::app::AppTuple. +template struct MatchingAppTuple> { + using Type = AppTuple; }; /// Specialization for the case when the type is an instance of \c /// std::tuple. -template struct MatchingDeluxeTuple> { - using Type = DeluxeTuple; +template struct MatchingAppTuple> { + using Type = AppTuple; }; ///@} /// Convenience template type alias for easy use of \c -/// rosa::deluxe::MatchingDeluxeTuple. +/// rosa::app::MatchingAppTuple. /// -/// Converts a tuple type to the matching \c rosa::deluxe::DeluxeTuple type. +/// Converts a tuple type to the matching \c rosa::app::AppTuple type. /// /// \tparam Tuple type to convert template -using matching_deluxe_tuple_t = typename MatchingDeluxeTuple::Type; +using matching_app_tuple_t = typename MatchingAppTuple::Type; -/// \defgroup TypeListAllDeluxeTuple Implementation of -/// \c rosa::deluxe::TypeListAllDeluxeTuple +/// \defgroup TypeListAllAppTuple Implementation of +/// \c rosa::app::TypeListAllAppTuple /// /// \brief Tells if all types in a \c rosa::TypeList is an instance of \c -/// rosa::deluxe::DeluxeTuple. +/// rosa::app::AppTuple. /// /// Whether a \c rosa::TypeList \c List contains instances of \c -/// rosa::deluxe::DeluxeTuple only can be checked as \code -/// TypeListAllDeluxeTuple::Value +/// rosa::app::AppTuple only can be checked as \code +/// TypeListAllAppTuple::Value /// \endcode ///@{ /// Declaration of the template. /// /// \tparam List \c rosa::TypeList to check -template struct TypeListAllDeluxeTuple; +template struct TypeListAllAppTuple; /// Specialization for \c rosa::EmptyTypeList. -template <> struct TypeListAllDeluxeTuple { +template <> struct TypeListAllAppTuple { static constexpr bool Value = true; }; /// Implementation for the general case when there is at leasst one element in /// the list. template -struct TypeListAllDeluxeTuple> { +struct TypeListAllAppTuple> { static constexpr bool Value = - IsDeluxeTuple::Value && TypeListAllDeluxeTuple>::Value; + IsAppTuple::Value && TypeListAllAppTuple>::Value; }; ///@} -} // End namespace deluxe +} // End namespace app } // End namespace rosa namespace std { -/// Dumps a \c rosa::deluxe::Deluxe instance to a given \c std::ostream. +/// Dumps a \c rosa::app::App instance to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to -/// \param Tuple \c rosa::deluxe::Deluxe to dump +/// \param Tuple \c rosa::app::App to dump /// /// \return \p OS after dumping \p Tuple to it template -ostream &operator<<(ostream &OS, - const rosa::deluxe::DeluxeTuple &Tuple) { +ostream &operator<<(ostream &OS, const rosa::app::AppTuple &Tuple) { Tuple.dump(OS); return OS; } } // End namespace std -#endif // ROSA_DELUXE_DELUXETUPLE_HPP +#endif // ROSA_APP_APPTUPLE_HPP diff --git a/include/rosa/deluxe/DeluxeContext.hpp b/include/rosa/app/Application.hpp similarity index 63% rename from include/rosa/deluxe/DeluxeContext.hpp rename to include/rosa/app/Application.hpp index f2e8340..08afd6b 100644 --- a/include/rosa/deluxe/DeluxeContext.hpp +++ b/include/rosa/app/Application.hpp @@ -1,941 +1,931 @@ -//===-- rosa/deluxe/DeluxeContext.hpp ---------------------------*- C++ -*-===// +//===-- rosa/app/Application.hpp --------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/DeluxeContext.hpp +/// \file rosa/app/Application.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// -/// \brief Public interface for the *deluxe interface* for working with agent +/// \brief Public interface for the *application interface* for working with +/// agent /// systems. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_DELUXECONTEXT_HPP -#define ROSA_DELUXE_DELUXECONTEXT_HPP +#ifndef ROSA_APP_APPLICATION_HPP +#define ROSA_APP_APPLICATION_HPP -#include "rosa/deluxe/DeluxeSystem.hpp" +#include "rosa/app/AppSystem.hpp" #include "rosa/support/types.hpp" #include #include #include /// Local helper macro to log and return a -/// \c rosa::deluxe::DeluxeContext::ErrorCode value. +/// \c rosa::app::Application::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 +/// \param Err \c rosa::app::Application::ErrorCode value to log and /// return -#define DCRETERROR(Err) \ +#define APPRETERROR(Err) \ { \ LOG_DEBUG(#Err); \ return Err; \ } namespace rosa { -namespace deluxe { +namespace app { -/// Defines the *deluxe interface*. +/// Defines the *application interface*. /// -/// \todo The classes \c rosa::deluxe::DeluxeSensor and \c -/// rosa::deluxe::DeluxeAgent share some common features in relation to their -/// *slave* role in the *deluxe interface*. But their definitions are completely -/// independent. It could be investigated how to lift their common parts into a -/// new *deluxe slave* class, which would serve as base for both, to avoid code -/// duplication. -class DeluxeContext { +/// \todo The classes \c rosa::app::AppSensor and \c +/// rosa::app::AppAgent share some common features in relation to their +/// *slave* role in the *application interface*. But their definitions are +/// completely independent. It could be investigated how to lift their common +/// parts into a new *application slave* class, which would serve as base for +/// both, to avoid code duplication. +class Application { /// 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 System; + /// function \c rosa::app::Application::getSystem. + std::shared_ptr System; /// References to all *sensors* and *agents* created by \p this object. - std::set DeluxeUnits; + std::set AppUnits; public: - /// Errors that may be resulted by some of the member functions of the class. enum struct ErrorCode { NoError, TypeMismatch, NotSensor, NotAgent, NotUnit, WrongPosition, AlreadyHasSlave, AlreadyHasMaster, AlreadyHasValueStream, UnsuitableExecutionPolicy }; - /// Returns a new instance of \c rosa::deluxe::DeluxeContext. + /// Returns a new instance of \c rosa::app::Application. /// - /// \param Name name of the underlying \c rosa::DeluxeSystem + /// \param Name name of the underlying \c rosa::AppSystem /// /// \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 - create(const std::string &Name) noexcept; + /// \c rosa::app::Application with a new, empty \c rosa::AppSystem + static std::unique_ptr 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; + Application(const std::string &Name) noexcept; public: /// Destroys \p this object. - ~DeluxeContext(void) noexcept; + ~Application(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 getSystem(void) const noexcept; private: /// Creates a new *sensor* in the context of \p this object. /// /// The new *sensor* handles master-input by \p MF. /// /// \tparam MT type of master-input the new *sensor* handles /// \tparam T type of data the new *sensor* operates on /// /// \note Instantiation fails if any of the type arguments \p MT and \p T - /// is not an instance of \c rosa::deluxe::DeluxeTuple or \p T is \c - /// rosa::deluxe::EmptyDeluxeTuple. + /// is not an instance of \c rosa::app::AppTuple or \p T is \c + /// rosa::app::EmptyAppTuple. /// /// \param Name name of the new *sensor* /// \param MF function for the new *sensors* to process master-input /// values with /// \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 + /// \c rosa::app::Application::registerSensorValues is used to /// register an alternative simulation data source with \c - /// rosa::deluxe::DeluxeSensor::registerSimulationDataSource. One may + /// rosa::app::AppSensor::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. /// - /// \see \c rosa::deluxe::DeluxeSensor::DeluxeSensor. + /// \see \c rosa::app::AppSensor::AppSensor. /// /// \return \c rosa::AgentHandle for the new *sensor* - template >::Value && - !std::is_same::value>> + template < + typename MT, typename T, + typename = std::enable_if>::Value && + !std::is_same::value>> AgentHandle createSensorImpl(const std::string &Name, std::function)> &&MF, std::function &&F) noexcept; public: /// Creates a new *sensor* in the context of \p this object. /// /// The new *sensor* does not receive master-input. /// /// \tparam T type of data the new *sensor* operates on /// /// \note Instantiation fails if type argument \p T is neither a built-in type - /// nor an instance of \c rosa::deluxe::DeluxeTuple with at least one element. + /// nor an instance of \c rosa::app::AppTuple with at least one element. /// /// \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 + /// \c rosa::app::Application::registerSensorValues is used to register /// an alternative simulation data source with - /// \c rosa::deluxe::DeluxeSensor::registerSimulationDataSource. One may + /// \c rosa::app::AppSensor::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. /// - /// \see \c rosa::deluxe::DeluxeSensor::DeluxeSensor. + /// \see \c rosa::app::AppSensor::AppSensor. /// /// \return \c rosa::AgentHandle for the new *sensor* template ::Value || - (IsDeluxeTuple::Value && - !std::is_same::value)>> + (IsAppTuple::Value && + !std::is_same::value)>> AgentHandle createSensor( const std::string &Name, std::function &&F = [](void) { return T(); }) noexcept; /// Creates a new *sensor* in the context of \p this object. /// /// The new *sensor* handles master-input by \p MF. /// /// \tparam MT type of master-input the new *sensor* handles /// \tparam T type of data the new *sensor* operates on /// /// \note The type arguments \p MT and \p T must be either all built-in types - /// or all instances of \c rosa::deluxe::DeluxeTuple. Moreover, \p T cannot be - /// \c rosa::deluxe::EmptyDeluxeTuple. Instantiation fails if these conditions + /// or all instances of \c rosa::app::AppTuple. Moreover, \p T cannot be + /// \c rosa::app::EmptyAppTuple. Instantiation fails if these conditions /// do not hold. /// /// \param Name name of the new *sensor* /// \param MF function for the new *sensors* to process master-input /// values with \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 + /// \c rosa::app::Application::registerSensorValues is used to /// register an alternative simulation data source with \c - /// rosa::deluxe::DeluxeSensor::registerSimulationDataSource. One may + /// rosa::app::AppSensor::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. /// - /// \see \c rosa::deluxe::DeluxeSensor::DeluxeSensor. + /// \see \c rosa::app::AppSensor::AppSensor. /// /// \return \c rosa::AgentHandle for the new *sensor* template , BuiltinTypes>::Value || - (TypeListAllDeluxeTuple>::Value && - !std::is_same::value)>> + (TypeListAllAppTuple>::Value && + !std::is_same::value)>> AgentHandle createSensor( const std::string &Name, std::function)> &&MF, std::function &&F = [](void) { return T(); }) noexcept; private: /// Creates a new *agent* in the context of \p this object. /// /// The new *agent* receives master-input by \p MF and produces /// master-output. /// /// \tparam MT type of master-input the new *agent* handles /// \tparam T type of data the new *agent* outputs /// \tparam Ts types of master-output the new *agent* produces /// \tparam As types of inputs the new *agent* takes /// /// \note Instantiation fails if any of the type arguments \p MT, \p T, \p - /// Ts..., and \p As... is not an instance of \c rosa::deluxe::DeluxeTuple or - /// any of \p T and \p As... is \c rosa::deluxe::EmptyDeluxeTuple. + /// Ts..., and \p As... is not an instance of \c rosa::app::AppTuple or + /// any of \p T and \p As... is \c rosa::app::EmptyAppTuple. /// /// \param Name name of the new *agent* /// \param MF function for the new *agent* to process master-input /// values with \param F function for the new *agent* to process /// input values and generate output with /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \see \c rosa::app::AppAgent::AppAgent. /// /// \return \c rosa::AgentHandle for the new *agent* template >::Value && - !std::is_same::value && - (true && ... && (!std::is_same::value))>> + TypeListAllAppTuple>::Value && + !std::is_same::value && + (true && ... && (!std::is_same::value))>> AgentHandle createAgentImpl( const std::string &Name, std::function...>(std::pair)> &&MF, std::function, Optional...>( std::pair...)> &&F) noexcept; public: /// Creates a new *agent* in the context of \p this object. /// /// The new *agent* neither receives master-input nor produces /// master-output. /// /// \tparam T type of data the new *agent* outputs /// \tparam As types of inputs the new *agent* takes /// /// \note The type arguments \p T and \p As... must be either all built-in - /// types or all instances of \c rosa::deluxe::DeluxeTuple. Moreover, none of - /// them can be \c rosa::deluxe::EmptyDeluxeTuple. Instantiation fails if + /// types or all instances of \c rosa::app::AppTuple. Moreover, none of + /// them can be \c rosa::app::EmptyAppTuple. Instantiation fails if /// these conditions do not hold. /// /// \param Name name of the new *agent* /// \param F function for the new *agent* to process input values and /// generate output with /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \see \c rosa::app::AppAgent::AppAgent. /// /// \return \c rosa::AgentHandle for the new *agent* - template < - typename T, typename... As, - typename = std::enable_if_t< - TypeListSubsetOf, BuiltinTypes>::Value || - (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && - (true && ... && (!std::is_same::value)))>> + template , BuiltinTypes>::Value || + (TypeListAllAppTuple>::Value && + !std::is_same::value && + (true && ... && (!std::is_same::value)))>> AgentHandle createAgent(const std::string &Name, std::function(std::pair...)> &&F) noexcept; /// Creates a new *agent* in the context of \p this object. /// /// The new *agent* receives master-input by \p MF but does not /// produce master-output. /// /// \tparam MT type of master-input the new *agent* handles /// \tparam T type of data the new *agent* outputs /// \tparam As types of inputs the new *agent* takes /// /// \note The type arguments \p MT, \p T, and \p As... must be either all - /// built-in types or all instances of \c rosa::deluxe::DeluxeTuple. Moreover, - /// none of \p T and \p As... can be \c rosa::deluxe::EmptyDeluxeTuple. + /// built-in types or all instances of \c rosa::app::AppTuple. Moreover, + /// none of \p T and \p As... can be \c rosa::app::EmptyAppTuple. /// Instantiation fails if these conditions do not hold. /// /// \param Name name of the new *agent* /// \param MF function for the new *agent* to process master-input /// values with /// \param F function for the new *agent* to process input values and /// generate output with /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \see \c rosa::app::AppAgent::AppAgent. /// /// \return \c rosa::AgentHandle for the new *agent* - template < - typename MT, typename T, typename... As, - typename = std::enable_if_t< - TypeListSubsetOf, BuiltinTypes>::Value || - (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && - (true && ... && (!std::is_same::value)))>> + template , BuiltinTypes>::Value || + (TypeListAllAppTuple>::Value && + !std::is_same::value && + (true && ... && (!std::is_same::value)))>> AgentHandle createAgent(const std::string &Name, std::function)> &&MF, std::function(std::pair...)> &&F) noexcept; /// Creates a new *agent* in the context of \p this object. /// /// The new *agent* does not receive master-input but produces /// master-output. /// /// \tparam T type of data the new *agent* outputs /// \tparam Ts types of master-output the new *agent* produces /// \tparam As types of inputs the new *agent* takes /// /// \note The type arguments \p T, \p Ts, and \p As... must be either all - /// built-in types or all instances of \c rosa::deluxe::DeluxeTuple. Moreover, - /// none of \p T and \p As... can be \c rosa::deluxe::EmptyDeluxeTuple. + /// built-in types or all instances of \c rosa::app::AppTuple. Moreover, + /// none of \p T and \p As... can be \c rosa::app::EmptyAppTuple. /// Instantiation fails if these conditions do not hold. /// /// \param Name name of the new *agent* /// \param F function for the new *agent* to process input values and /// generate output with /// /// \note \p F does not produce master-output for a given position if the - /// corresponding type is \c rosa::deluxe::EmptyDeluxeTuple. It is not + /// corresponding type is \c rosa::app::EmptyAppTuple. It is not /// possible to disable master-output at any position by using built-in types. /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \see \c rosa::app::AppAgent::AppAgent. /// /// \return \c rosa::AgentHandle for the new *agent* template < typename T, typename... Ts, typename... As, typename = std::enable_if_t< TypeListSubsetOf, BuiltinTypes>::Value || - (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && - (true && ... && (!std::is_same::value)))>> + (TypeListAllAppTuple>::Value && + !std::is_same::value && + (true && ... && (!std::is_same::value)))>> AgentHandle createAgent(const std::string &Name, std::function, Optional...>( std::pair...)> &&F) noexcept; /// Creates a new *agent* in the context of \p this object. /// /// The new *agent* receives master-input by \p MF and produces /// master-output. /// /// \tparam MT type of master-input the new *agent* handles /// \tparam T type of data the new *agent* outputs /// \tparam Ts types of master-output the new *agent* produces /// \tparam As types of inputs the new *agent* takes /// /// \note The type arguments \p MT, \p T, \p Ts, and \p As... must be either - /// all built-in types or all instances of \c rosa::deluxe::DeluxeTuple. + /// all built-in types or all instances of \c rosa::app::AppTuple. /// Moreover, none of \p T and \p As... can be \c - /// rosa::deluxe::EmptyDeluxeTuple. Instantiation fails if these conditions + /// rosa::app::EmptyAppTuple. Instantiation fails if these conditions /// do not hold. /// /// \param Name name of the new *agent* /// \param MF function for the new *agent* to process master-input /// values with /// \param F function for the new *agent* to process input values and /// generate output with /// /// \note \p F does not produce master-output for a given position if the - /// corresponding type is \c rosa::deluxe::EmptyDeluxeTuple. It is not + /// corresponding type is \c rosa::app::EmptyAppTuple. It is not /// possible to disable master-output at any position by using built-in types. /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. + /// \see \c rosa::app::AppAgent::AppAgent. /// /// \return \c rosa::AgentHandle for the new *agent* - template < - typename MT, typename T, typename... Ts, typename... As, - typename = std::enable_if_t< - TypeListSubsetOf, - BuiltinTypes>::Value || - (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && - (true && ... && (!std::is_same::value)))>> + template , + BuiltinTypes>::Value || + (TypeListAllAppTuple>::Value && + !std::is_same::value && + (true && ... && (!std::is_same::value)))>> AgentHandle createAgent( const std::string &Name, std::function...>(std::pair)> &&MF, std::function, Optional...>( std::pair...)> &&F) noexcept; /// Returns the current execution policy of the referred \p Unit /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \note The referred \p Unit is either *sensor* or *agent*. /// /// \note The returned reference is valid only as long as \c - /// rosa::deluxe::DeluxeContext::setExecutionPolicy() is not called with the + /// rosa::app::Application::setExecutionPolicy() is not called with the /// *unit* referred by \p Unit and the *unit* is not destroyed. /// /// \param Unit the *unit* whose execution policy is to be obtained /// - /// \return the \c rosa::deluxe::DeluxeExecutionPolicy from \p Unit if \p Unit + /// \return the \c rosa::app::AppExecutionPolicy from \p Unit if \p Unit /// is valid - Optional + Optional getExecutionPolicy(AgentHandle Unit) const noexcept; /// Sets the current execution policy of the referred \p Unit to \p /// ExecutionPolicy. /// - /// \see \c rosa::deluxe::DeluxeExecutionPolicy + /// \see \c rosa::app::AppExecutionPolicy /// /// \note The referred \p Unit is either *sensor* or *agent*. /// /// \param Unit the *unit* whose execution policy is to be set /// \param ExecutionPolicy the new execution policy for \p Unit /// /// \return how successful setting \p ExecutionPolicy for \p Unit was /// /// \note The function may return the following - /// \c rosa::deluxe::DeluxeContext::ErrorCode values: + /// \c rosa::app::Application::ErrorCode values: /// `ErrorCode` | Comment /// ----------- | ------- /// `NoError` | Success /// `NotUnit` | Referred \p Unit is not valid /// `UnsuitableExecutionPolicy` | \p ExecutionPolicy cannot handle \p Unit ErrorCode setExecutionPolicy( AgentHandle Unit, - std::unique_ptr &&ExecutionPolicy) noexcept; + std::unique_ptr &&ExecutionPolicy) noexcept; /// Connects 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: + /// \c rosa::app::Application::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 + /// `NotAgent` | Referred \p Agent is not \c rosa::app::AppAgent + /// `NotSensor` | Referred \p Sensor is not \c rosa::app::AppSensor /// `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 thanthe output type of \p Sensor or expected master-input of \p Sensor is other than master-output at position \p Pos of \p Agent if any - /// `AlreadyHasSlave` | \p Agent at position \p Pos already has a *slave* registered - /// `AlreadyHasMaster` | \p Sensor already has a *master* registered + /// `TypeMismatch` | Expected input type at position \p Pos of \p Agent is + /// other thanthe output type of \p Sensor or expected master-input of \p + /// Sensor is other than master-output at position \p Pos of \p Agent if any + /// `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: + /// \c rosa::app::Application::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 or expected master-input of \p Slave is other than master-output at position \p Pos of \p Master if any - /// `AlreadyHasSlave` | \p Master at position \p Pos already has a *slave* registered - /// `AlreadyHasMaster` | \p Slave already has a *master* registered + /// `NotAgent` | Referred \p Master or \p Slave is not \c + /// rosa::app::AppAgent `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 or expected + /// master-input of \p Slave is other than master-output at position \p Pos of + /// \p Master if any `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 + /// \see \c rosa::app::Application::registerSensorValues, + /// \c rosa::app::Application::simulate /// /// Need to clear simulation data sources from all the *sensors*. void initializeSimulation(void) noexcept; public: /// Registers a stream providing values for a *sensor* during /// simulation. /// /// \tparam Iterator type of iterator providing values for \p Sensor /// \tparam T type that can be matched to values \p Sensor is operating on, /// always use default! /// /// \note Instantiation fails if type argument \p T is neither a built-in type - /// nor a tuple (i.e., can be converted to \c rosa::deluxe::DeluxeTuple). + /// nor a tuple (i.e., can be converted to \c rosa::app::AppTuple). /// /// \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: + /// \c rosa::app::Application::ErrorCode values: /// `ErrorCode` | Comment /// ----------- | ------- /// `NoError` | Success /// `TypeMismatch` | \p T does not match the type of values /// generated by \p Sensor /// `NotSensor` | Referred \p Sensor is not \c - /// rosa::deluxe::DeluxeSensor + /// rosa::app::AppSensor /// `AlreadyHasValueStream` | \p Sensor already has simulation data source set template ::Value || IsTuple::Value>> 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 + /// rosa::app::Application::AppUnits 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; }; /// Anonymous namespace with helper features for implementing -/// \c rosa::deluxe::DeluxeContext, consider it private. +/// \c rosa::app::Application, consider it private. namespace { -/// Maps any type \p T to \c rosa::deluxe::EmptyDeluxeTuple. -template struct MapToEmptyDeluxeTuple { - using Type = EmptyDeluxeTuple; -}; +/// Maps any type \p T to \c rosa::app::EmptyAppTuple. +template struct MapToEmptyAppTuple { using Type = EmptyAppTuple; }; -/// Convenience template alias for \c MapToEmptyDeluxeTuple. -template -using empty_deluxe_t = typename MapToEmptyDeluxeTuple::Type; +/// Convenience template alias for \c MapToEmptyAppTuple. +template using empty_app_t = typename MapToEmptyAppTuple::Type; /// Converts a \c std::tuple of \c rosa::Optional built-in types into a /// corresponding \c std::tuple of \c rosa::Optional with each actual value -/// wrapped in \c rosa::deluxe::DeluxeTuple. +/// wrapped in \c rosa::app::AppTuple. /// /// \tparam Ts types of the values /// \tparam S0 indices for accessing values in \p Values /// /// \param Values the \c std::tuple of \c rosa::Optional with built-in values /// /// \note The second argument provides indices statically as template arguments /// \p S0..., so its actual value is ignored. /// /// \return a \c std::tuple of \c rosa::Optional corresponding to \p Values -/// with each actual value wrapped in \c rosa::deluxe::DeluxeTuple +/// with each actual value wrapped in \c rosa::app::AppTuple /// /// \pre Statically, all type arguments \p Ts... are built-in types and the /// provided indices \p S0... match the length of \p Ts...: \code /// TypeListSubsetOf, BuiltinTypes>::Value && /// sizeof...(Ts) == sizeof...(S0) /// \endcode template -std::tuple>...> -wrapBuiltinInDeluxeTuple(const std::tuple...> &Values, - Seq) noexcept { +std::tuple>...> +wrapBuiltinInAppTuple(const std::tuple...> &Values, + Seq) noexcept { STATIC_ASSERT((TypeListSubsetOf, BuiltinTypes>::Value), "not built-in types"); STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0), "inconsistent type arguments"); - return std::make_tuple(std::get(Values) - ? Optional>( - make_deluxe_tuple(*std::get(Values))) - : Optional>()...); + return std::make_tuple( + std::get(Values) + ? Optional>(make_app_tuple(*std::get(Values))) + : Optional>()...); } } // End namespace template AgentHandle -DeluxeContext::createSensorImpl(const std::string &Name, - std::function)> &&MF, - std::function &&F) noexcept { +Application::createSensorImpl(const std::string &Name, + std::function)> &&MF, + std::function &&F) noexcept { AgentHandle H = System->createSensor(Name, std::move(MF), std::move(F)); - DeluxeUnits.emplace(H); + AppUnits.emplace(H); return H; } template -AgentHandle DeluxeContext::createSensor(const std::string &Name, - std::function &&F) noexcept { - auto EmptyMF = std::function)>( - [](std::pair) {}); +AgentHandle Application::createSensor(const std::string &Name, + std::function &&F) noexcept { + auto EmptyMF = std::function)>( + [](std::pair) {}); if constexpr (TypeListContains::Value) { - using OutputType = DeluxeTuple; + using OutputType = AppTuple; return createSensorImpl( Name, std::move(EmptyMF), std::function( [F{std::move(F)}](void) { return OutputType(F()); })); - } else if constexpr (IsDeluxeTuple::Value && - !std::is_same::value) { + } else if constexpr (IsAppTuple::Value && + !std::is_same::value) { return createSensorImpl(Name, std::move(EmptyMF), std::move(F)); } else { ASSERT(false && "Unexpected type argument"); } } template AgentHandle -DeluxeContext::createSensor(const std::string &Name, - std::function)> &&MF, - std::function &&F) noexcept { +Application::createSensor(const std::string &Name, + std::function)> &&MF, + std::function &&F) noexcept { if constexpr (TypeListSubsetOf, BuiltinTypes>::Value) { - using MasterInputType = DeluxeTuple; - using OutputType = DeluxeTuple; + using MasterInputType = AppTuple; + using OutputType = AppTuple; return createSensorImpl( Name, std::function)>( [MF{std::move(MF)}](std::pair Arg) { MF({std::get<0>(Arg.first), Arg.second}); }), std::function( [F{std::move(F)}](void) { return OutputType(F()); })); - } else if constexpr (TypeListAllDeluxeTuple>::Value && - !std::is_same::value) { + } else if constexpr (TypeListAllAppTuple>::Value && + !std::is_same::value) { return createSensorImpl(Name, std::move(MF), std::move(F)); } else { ASSERT(false && "Unexpected type arguments"); } } template -AgentHandle DeluxeContext::createAgentImpl( +AgentHandle Application::createAgentImpl( const std::string &Name, std::function...>(std::pair)> &&MF, std::function, Optional...>( std::pair...)> &&F) noexcept { AgentHandle H = System->createAgent(Name, std::move(MF), std::move(F)); - DeluxeUnits.emplace(H); + AppUnits.emplace(H); return H; } template -AgentHandle DeluxeContext::createAgent( +AgentHandle Application::createAgent( const std::string &Name, std::function(std::pair...)> &&F) noexcept { - using NoMasterOutputType = std::tuple>...>; + using NoMasterOutputType = std::tuple>...>; auto EmptyMF = - std::function)>( - [](std::pair) { - return NoMasterOutputType(); - }); + std::function)>( + [](std::pair) { return NoMasterOutputType(); }); if constexpr (TypeListSubsetOf, BuiltinTypes>::Value) { - using OutputType = DeluxeTuple; + using OutputType = AppTuple; return createAgentImpl( Name, std::move(EmptyMF), std::function< - std::tuple, Optional>...>( - std::pair, bool>...)>( - [F{std::move(F)}](std::pair, bool>... Args) { + std::tuple, Optional>...>( + std::pair, bool>...)>( + [F{std::move(F)}](std::pair, bool>... Args) { const auto Result = F({std::get<0>(Args.first), Args.second}...); return std::tuple_cat( - wrapBuiltinInDeluxeTuple(std::tuple(Result), seq_t<1>()), + wrapBuiltinInAppTuple(std::tuple(Result), seq_t<1>()), NoMasterOutputType()); })); - } else if constexpr (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && + } else if constexpr (TypeListAllAppTuple>::Value && + !std::is_same::value && (true && ... && - (!std::is_same::value))) { + (!std::is_same::value))) { return createAgentImpl( Name, std::move(EmptyMF), - std::function, Optional>...>( + std::function, Optional>...>( std::pair...)>( [F{std::move(F)}](std::pair... Args) { const auto Result = F(Args...); return std::tuple_cat(std::tuple(Result), NoMasterOutputType()); })); } else { ASSERT(false && "Unexpected type arguments"); } } template -AgentHandle DeluxeContext::createAgent( +AgentHandle Application::createAgent( const std::string &Name, std::function)> &&MF, std::function(std::pair...)> &&F) noexcept { - using NoMasterOutputType = std::tuple>...>; + using NoMasterOutputType = std::tuple>...>; if constexpr (TypeListSubsetOf, BuiltinTypes>::Value) { - using MasterInputType = DeluxeTuple; - using OutputType = DeluxeTuple; + using MasterInputType = AppTuple; + using OutputType = AppTuple; return createAgentImpl( Name, std::function)>( [MF{std::move(MF)}](std::pair Arg) { MF({std::get<0>(Arg.first), Arg.second}); return NoMasterOutputType(); }), std::function< - std::tuple, Optional>...>( - std::pair, bool>...)>( - [F{std::move(F)}](std::pair, bool>... Args) { + std::tuple, Optional>...>( + std::pair, bool>...)>( + [F{std::move(F)}](std::pair, bool>... Args) { const auto Result = F({std::get<0>(Args.first), Args.second}...); return std::tuple_cat( - wrapBuiltinInDeluxeTuple(std::tuple(Result), seq_t<1>()), + wrapBuiltinInAppTuple(std::tuple(Result), seq_t<1>()), NoMasterOutputType()); })); - } else if constexpr (TypeListAllDeluxeTuple>::Value && - !std::is_same::value && + } else if constexpr (TypeListAllAppTuple>::Value && + !std::is_same::value && (true && ... && - (!std::is_same::value))) { + (!std::is_same::value))) { return createAgentImpl( Name, std::function)>( [MF{std::move(MF)}](std::pair Arg) { MF(Arg); return NoMasterOutputType(); }), - std::function, Optional>...>( + std::function, Optional>...>( std::pair...)>( [F{std::move(F)}](std::pair... Args) { const auto Result = F(Args...); return std::tuple_cat(std::tuple(Result), NoMasterOutputType()); })); } else { ASSERT(false && "Unexpected type arguments"); } } template -AgentHandle DeluxeContext::createAgent( - const std::string &Name, - std::function, Optional...>( - std::pair...)> &&F) noexcept { +AgentHandle +Application::createAgent(const std::string &Name, + std::function, Optional...>( + std::pair...)> &&F) noexcept { if constexpr (TypeListSubsetOf, BuiltinTypes>::Value) { - using MasterOutputType = std::tuple>...>; - using OutputType = DeluxeTuple; + using MasterOutputType = std::tuple>...>; + using OutputType = AppTuple; return createAgentImpl( Name, - std::function)>( - [](std::pair) { - return MasterOutputType(); - }), + std::function)>( + [](std::pair) { return MasterOutputType(); }), std::function< - std::tuple, Optional>...>( - std::pair, bool>...)>( - [F{std::move(F)}](std::pair, bool>... Args) { + std::tuple, Optional>...>( + std::pair, bool>...)>( + [F{std::move(F)}](std::pair, bool>... Args) { const auto Result = F({std::get<0>(Args.first), Args.second}...); - return wrapBuiltinInDeluxeTuple(Result, - seq_t<1 + sizeof...(Ts)>()); + return wrapBuiltinInAppTuple(Result, seq_t<1 + sizeof...(Ts)>()); })); - } else if constexpr (TypeListAllDeluxeTuple< - TypeList>::Value && - !std::is_same::value && + } else if constexpr (TypeListAllAppTuple>::Value && + !std::is_same::value && (true && ... && - (!std::is_same::value))) { + (!std::is_same::value))) { using MasterOutputType = std::tuple...>; return createAgentImpl( Name, - std::function)>( - [](std::pair) { - return MasterOutputType(); - }), + std::function)>( + [](std::pair) { return MasterOutputType(); }), std::function, Optional...>( std::pair...)>( [F{std::move(F)}](std::pair... Args) { const auto Output = F(Args...); return Output; })); } else { ASSERT(false && "Unexpected type arguments"); } } template -AgentHandle DeluxeContext::createAgent( +AgentHandle Application::createAgent( const std::string &Name, std::function...>(std::pair)> &&MF, std::function, Optional...>( std::pair...)> &&F) noexcept { if constexpr (TypeListSubsetOf, BuiltinTypes>::Value) { - using MasterInputType = DeluxeTuple; - using MasterOutputType = std::tuple>...>; - using OutputType = DeluxeTuple; + using MasterInputType = AppTuple; + using MasterOutputType = std::tuple>...>; + using OutputType = AppTuple; return createAgentImpl( Name, std::function)>( [MF{std::move(MF)}](std::pair Arg) { const auto Result = MF({std::get<0>(Arg.first), Arg.second}); - return wrapBuiltinInDeluxeTuple(Result, seq_t()); + return wrapBuiltinInAppTuple(Result, seq_t()); }), std::function< - std::tuple, Optional>...>( - std::pair, bool>...)>( - [F{std::move(F)}](std::pair, bool>... Args) { + std::tuple, Optional>...>( + std::pair, bool>...)>( + [F{std::move(F)}](std::pair, bool>... Args) { const auto Result = F({std::get<0>(Args.first), Args.second}...); - return wrapBuiltinInDeluxeTuple(Result, - seq_t<1 + sizeof...(Ts)>()); + return wrapBuiltinInAppTuple(Result, seq_t<1 + sizeof...(Ts)>()); })); - } else if constexpr (TypeListAllDeluxeTuple< + } else if constexpr (TypeListAllAppTuple< TypeList>::Value && - !std::is_same::value && + !std::is_same::value && (true && ... && - (!std::is_same::value))) { + (!std::is_same::value))) { using MasterOutputType = std::tuple...>; return createAgentImpl( Name, std::function)>( [MF{std::move(MF)}](std::pair Arg) { const auto Output = MF(Arg); return Output; }), std::function, Optional...>( std::pair...)>( [F{std::move(F)}](std::pair... Args) { const auto Output = F(Args...); return Output; })); } else { ASSERT(false && "Unexpected type arguments"); } } template -DeluxeContext::ErrorCode -DeluxeContext::registerSensorValues(AgentHandle Sensor, Iterator &&Start, - const Iterator &End, T Default) noexcept { +Application::ErrorCode +Application::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::value), "type mismatch"); // Make sure preconditions are met. - if (!System->isDeluxeSensor(Sensor)) { - DCRETERROR(ErrorCode::NotSensor); + if (!System->isAppSensor(Sensor)) { + APPRETERROR(ErrorCode::NotSensor); } - auto S = System->getDeluxeSensor(Sensor); + auto S = System->getAppSensor(Sensor); ASSERT(S); // Sanity check. if (S->simulationDataSourceIsSet()) { - DCRETERROR(ErrorCode::AlreadyHasValueStream); + APPRETERROR(ErrorCode::AlreadyHasValueStream); } if constexpr (TypeListContains::Value) { if (S->OutputType != TypeToken::Value) { - DCRETERROR(ErrorCode::TypeMismatch); + APPRETERROR(ErrorCode::TypeMismatch); } // Register input stream. // \note Need to capture parameters by value so having local copies. - S->registerSimulationDataSource(std::function(void)>([= - ](void) mutable noexcept->DeluxeTuple { + S->registerSimulationDataSource(std::function(void)>([= + ](void) mutable noexcept->AppTuple { if (Start != End) { LOG_TRACE_STREAM << "Reading next value for sensor '" << S->FullName << "': " << *Start << '\n'; - return make_deluxe_tuple(*Start++); + return make_app_tuple(*Start++); } else { LOG_TRACE_STREAM << "Providing default value for sensor '" << S->FullName << "': " << Default << '\n'; - return make_deluxe_tuple(Default); + return make_app_tuple(Default); } })); } else if constexpr (IsTuple::Value) { - using TT = matching_deluxe_tuple_t; - if (std::is_same::value || S->OutputType != TT::TT) { - DCRETERROR(ErrorCode::TypeMismatch); + using TT = matching_app_tuple_t; + if (std::is_same::value || S->OutputType != TT::TT) { + APPRETERROR(ErrorCode::TypeMismatch); } // Register input stream. // \note Need to capture parameters by value so having local copies. S->registerSimulationDataSource( std::function([=](void) mutable noexcept->TT { if (Start != End) { - const TT DV(*Start++); + const TT AV(*Start++); LOG_TRACE_STREAM << "Reading next value for sensor '" << S->FullName - << "': " << DV << '\n'; - return DV; + << "': " << AV << '\n'; + return AV; } else { - static const TT DD(Default); + static const TT AD(Default); LOG_TRACE_STREAM << "Providing default value for sensor '" - << S->FullName << "': " << DD << '\n'; - return DD; + << S->FullName << "': " << AD << '\n'; + return AD; } })); } else { ASSERT(false && "Unexpected type argument"); } return ErrorCode::NoError; } -} // End namespace deluxe +} // End namespace app } // End namespace rosa // Undef local macro if not used in the corresponding implementation. -#ifndef ROSA_LIB_DELUXE_DELUXECONTEXT_CPP -#undef DCRETERROR +#ifndef ROSA_LIB_APP_APPLICATION_CPP +#undef APPRETERROR #endif -#endif // ROSA_DELUXE_DELUXECONTEXT_HPP +#endif // ROSA_APP_APPLICATION_HPP diff --git a/include/rosa/deluxe/namespace.h b/include/rosa/app/namespace.h similarity index 64% rename from include/rosa/deluxe/namespace.h rename to include/rosa/app/namespace.h index d28e32c..e7dc313 100755 --- a/include/rosa/deluxe/namespace.h +++ b/include/rosa/app/namespace.h @@ -1,38 +1,39 @@ -//===-- rosa/deluxe/namespace.h ---------------------------------*- C++ -*-===// +//===-- rosa/app/namespace.h ------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file rosa/deluxe/namespace.h +/// \file rosa/app/namespace.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017 +/// \date 2017-2020 /// -/// \brief Documentation for the namespace \c rosa::deluxe. +/// \brief Documentation for the namespace \c rosa::app. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_DELUXE_NAMESPACE_H -#define ROSA_DELUXE_NAMESPACE_H +#ifndef ROSA_APP_NAMESPACE_H +#define ROSA_APP_NAMESPACE_H namespace rosa { /// Contains a simplified, limited in functionality but flexible in modularity, -/// interface to define and easily reconfigure agent systems. +/// interface to define and easily reconfigure appliations based on agent +/// systems. /// -/// **Deluxe Interface** +/// **Application Interface** /// /// TODO write this description here! -namespace deluxe {} +namespace app {} } // End namespace rosa -#endif // ROSA_DELUXE_NAMESPACE_H +#endif // ROSA_APP_NAMESPACE_H diff --git a/include/rosa/deluxe/DeluxeSystem.hpp b/include/rosa/deluxe/DeluxeSystem.hpp deleted file mode 100644 index 2364d2b..0000000 --- a/include/rosa/deluxe/DeluxeSystem.hpp +++ /dev/null @@ -1,246 +0,0 @@ -//===-- rosa/deluxe/DeluxeSystem.hpp ----------------------------*- C++ -*-===// -// -// The RoSA Framework -// -// Distributed under the terms and conditions of the Boost Software License 1.0. -// See accompanying file LICENSE. -// -// If you did not receive a copy of the license file, see -// http://www.boost.org/LICENSE_1_0.txt. -// -//===----------------------------------------------------------------------===// -/// -/// \file rosa/deluxe/DeluxeSystem.hpp -/// -/// \author David Juhasz (david.juhasz@tuwien.ac.at) -/// -/// \date 2017-2019 -/// -/// \brief Specialization of \c rosa::MessagingSystem for the *deluxe -/// interface*. -/// -/// \see \c rosa::deluxe::DeluxeContext -/// -//===----------------------------------------------------------------------===// - -#ifndef ROSA_DELUXE_DELUXESYSTEM_HPP -#define ROSA_DELUXE_DELUXESYSTEM_HPP - -#include "rosa/core/MessagingSystem.hpp" - -#include "rosa/deluxe/DeluxeAgent.hpp" -#include "rosa/deluxe/DeluxeSensor.hpp" - -namespace rosa { -namespace deluxe { - -/// Implements and extends the \c rosa::MessagingSystem interface to be -/// used by \c rosa::deluxe::DeluxeContext. -/// -/// The class is a specialization of \c rosa::MessagingSystem, where objects -/// of two specialized subtypes of \c rosa::Agent, \c rosa::deluxe::DeluxeSensor -/// and \c rosa::deluxe::DeluxeAgent, constitute a system. The class extends the -/// \c rosa::MessagingSystem interface with features required to implement the -/// *deluxe interface*. -/// -/// \see rosa::deluxe::DeluxeContext -class DeluxeSystem : public MessagingSystem { - - friend class DeluxeContext; - friend class DeluxeExecutionPolicy; - -public: - /// Returns an object implementing the \c rosa::deluxe::DeluxeSystem - /// interface. - /// - /// \param Name name of the new instance - /// - /// \return \c std::unique_ptr for the new instance of - /// \c rosa::DeluxeSystem - static std::unique_ptr - createSystem(const std::string &Name) noexcept; - -protected: - /// Creates a new instance. - /// - /// \note Protected constructor restricts instantiation for subclasses. - DeluxeSystem(void) noexcept = default; - -public: - /// Creates a \c rosa::deluxe::DeluxeSensor instance owned by \p this object - /// and returns a \p rosa::AgentHandle for it. - /// - /// \tparam MT type of master-input the new \c rosa::deluxe::DeluxeSensor - /// receives - /// \tparam T type of data the new \c rosa::deluxe::DeluxeSensor operates on - /// - /// \note Type arguments \p MT and \p T must be instances of \c - /// rosa::deluxe::DeluxeTuple. - /// - /// \param Name name of the new \c rosa::deluxe::DeluxeSensor - /// \param MF function to process master-input values - /// \param F function to generate the next value with during normal operation - /// - /// \see \c rosa::deluxe::DeluxeSensor::DeluxeSensor. - /// - /// \return \c rosa::AgentHandle for new \c rosa::deluxe::DeluxeSensor - template - AgentHandle createSensor(const std::string &Name, - std::function)> &&MF, - std::function &&F) noexcept; - - /// Creates a \c rosa::deluxe::DeluxeAgent instance owned by \p this object - /// and returns a \c rosa::AgentHandle for it. - /// - /// \tparam MT type of master-input the new \c rosa::deluxe::DeluxeAgent - /// receives - /// \tparam T type of data the new \c rosa::deluxe::DeluxeAgent outputs - /// \tparam Ts types of master-output the new \c rosa::deluxe::DeluxeAgent - /// produces - /// \tparam As types of inputs the new \c rosa::deluxe::DeluxeAgent takes - /// - /// \note Type arguments \p MT, \p T, \p Ts..., and \p As... must be - /// instances of \c rosa::deluxe::DeluxeTuple. - /// - /// \param Name name of the new \c rosa::deluxe::DeluxeAgent - /// \param MF function for the new \c rosa::deluxe::DeluxeAgent to process - /// master-input values and generate master-output with - /// \param F function for the new \c rosa::deluxe::DeluxeAgent to process - /// input values and generate output and master-output with - /// - /// \see \c rosa::deluxe::DeluxeAgent::DeluxeAgent. - /// - /// \return \c rosa::AgentHandle for new \c rosa::deluxe::DeluxeAgent - template - AgentHandle createAgent( - const std::string &Name, - std::function...>(std::pair)> &&MF, - std::function, Optional...>( - std::pair...)> &&F) noexcept; - -protected: - /// Tells whether a \c rosa::AgentHandle refers to a - /// \c rosa::deluxe::DeluxeSensor owned by \p this object. - /// - /// \param H \c rosa::AgentHandle to check - /// - /// \return whether \p H refers to a \c rosa::deluxe::DeluxeSensor owned by - /// \p this object - virtual bool isDeluxeSensor(const AgentHandle &H) const noexcept = 0; - - /// Extracts a const qualified \c rosa::deluxe::DeluxeSensor reference from a - /// const qualified \c rosa::AgentHandle if possible. - /// - /// The function returns a \c rosa::Optional object containing a const - /// qualified reference to a \c rosa::deluxe::DeluxeSensor object extracted - /// from a const qualified \c rosa::AgentHandle instance if the referred - /// object is of type \c rosa::deluxeDeluxeSensor and owned by \p this object. - /// The returned \c rosa::Optional object is empty otherwise. - /// - /// \see rosa::deluxe::DeluxeSystem::isDeluxeSensor - /// - /// \param H \c rosa::AgentHandle to extract a \c rosa::deluxe::DeluxeSensor - /// from - /// - /// \return const qualified reference to \c rosa::deluxe::DeluxeSensor if - /// \p H refers to an object which is of that type and is owned by \p this - /// object - Optional getDeluxeSensor(const AgentHandle &H) const - noexcept; - - /// Extracts a \c rosa::deluxe::DeluxeSensor reference from a - /// \c rosa::AgentHandle if possible. - /// - /// The function returns a \c rosa::Optional object containing a reference to - /// a \c rosa::deluxe::DeluxeSensor object extracted from a - /// \c rosa::AgentHandle instance if the referred object is of type - /// \c rosa::deluxeDeluxeSensor and owned by \p this object. The returned - /// \c rosa::Optional object is empty otherwise. - /// - /// \see rosa::deluxe::DeluxeSystem::isDeluxeSensor - /// - /// \param H \c rosa::AgentHandle to extract a \c rosa::deluxe::DeluxeSensor - /// from - /// - /// \return reference to \c rosa::deluxe::DeluxeSensor if \p H refers to an - /// object which is of that type and is owned by \p this object - Optional getDeluxeSensor(AgentHandle &H) const noexcept; - - /// Tells whether a \c rosa::AgentHandle refers to a - /// \c rosa::deluxe::DeluxeAgent owned by \p this object. - /// - /// \param H \c rosa::AgentHandle to check - /// - /// \return whether \p H refers to a \c rosa::deluxe::DeluxeAgent owned by - /// \p this object - virtual bool isDeluxeAgent(const AgentHandle &H) const noexcept = 0; - - /// Extracts a const qualified \c rosa::deluxe::DeluxeAgent reference from a - /// const qualified \c rosa::AgentHandle if possible. - /// - /// The function returns a \c rosa::Optional object containing a const - /// qualified reference to a \c rosa::deluxe::DeluxeAgent object extracted - /// from a const qualified \c rosa::AgentHandle instance if the referred - /// object is of type \c rosa::deluxeDeluxeAgent and owned by \p this object. - /// The returned \c rosa::Optional object is empty otherwise. - /// - /// \see rosa::deluxe::DeluxeSystem::isDeluxeAgent - /// - /// \param H \c rosa::AgentHandle to extract a \c rosa::deluxe::DeluxeAgent - /// from - /// - /// \return const qualified reference to \c rosa::deluxe::DeluxeAgent if \p H - /// refers to an object which is of that type and is owned by \p this object - Optional getDeluxeAgent(const AgentHandle &H) const - noexcept; - - /// Extracts a \c rosa::deluxe::DeluxeAgent reference from a - /// \c rosa::AgentHandle if possible. - /// - /// The function returns a \c rosa::Optional object containing a reference to - /// a \c rosa::deluxe::DeluxeAgent object extracted from a - /// \c rosa::AgentHandle instance if the referred object is of type - /// \c rosa::deluxeDeluxeAgent and owned by \p this object. The returned - /// \c rosa::Optional object is empty otherwise. - /// - /// \see rosa::deluxe::DeluxeSystem::isDeluxeAgent - /// - /// \param H \c rosa::AgentHandle to extract a \c rosa::deluxe::DeluxeAgent - /// from - /// - /// \return reference to \c rosa::deluxe::DeluxeAgent if \p H refers to an - /// object which is of that type and is owned by \p this object - Optional getDeluxeAgent(AgentHandle &H) const noexcept; -}; - -template -AgentHandle -DeluxeSystem::createSensor(const std::string &Name, - std::function)> &&MF, - std::function &&F) noexcept { - Agent &DS = createUnit( - [&](const id_t Id, MessagingSystem &S) { - return new DeluxeSensor(atoms::SensorKind, Id, Name, S, std::move(MF), - std::move(F)); - }); - return {DS}; -} - -template -AgentHandle DeluxeSystem::createAgent( - const std::string &Name, - std::function...>(std::pair)> &&MF, - std::function, Optional...>( - std::pair...)> &&F) noexcept { - Agent &DA = createUnit( - [&](const id_t Id, DeluxeSystem &S) { - return new DeluxeAgent(atoms::AgentKind, Id, Name, S, std::move(MF), - std::move(F)); - }); - return {DA}; -} - -} // End namespace deluxe -} // End namespace rosa - -#endif // ROSA_DELUXE_DELUXESYSTEM_HPP diff --git a/include/rosa/support/type_numbers.hpp b/include/rosa/support/type_numbers.hpp index 99bf92b..024b147 100644 --- a/include/rosa/support/type_numbers.hpp +++ b/include/rosa/support/type_numbers.hpp @@ -1,245 +1,245 @@ //===-- rosa/support/type_numbers.hpp ---------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file rosa/support/type_numbers.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017-2019 /// /// \brief Facilities for registering supported types and representing them with /// numbers. /// /// \note This implementation is partially based on the \c type_number /// implementation of CAF. /// //===----------------------------------------------------------------------===// #ifndef ROSA_SUPPORT_TYPE_NUMBERS_HPP #define ROSA_SUPPORT_TYPE_NUMBERS_HPP #include "rosa/support/atom.hpp" #include "rosa/support/math.hpp" #include "rosa/support/squashed_int.hpp" #include "rosa/support/type_helper.hpp" #include "rosa/support/types.hpp" #include #include namespace rosa { /// Compile-time list of all built-in types. /// \note Appending new types to the end of this list maintains backward /// compatibility in the sense that old builtin types have the same type number /// associated to them in both the old and new versions. But changing any of /// the already present types in the list breaks that backward compatibility. /// Should compatibility be broken, step \c rosa::TypeNumberVersion below! /// \note Keep this list in sync with the definition of /// \c rosa::NumberedTypeNames. /// \note The built-in types are explicitly listed in the definition of -/// rosa::deluxe::DeluxeAgent. Keep those definitions in sync with this list. +/// rosa::app::AppAgent. Keep those definitions in sync with this list. using BuiltinTypes = TypeList; /// Indicates the version number of \c rosa::BuiltinTypes. /// /// Software with the same version number are supposed to have backward /// compatible type numbering. /// /// \sa \c rosa::BultinTypes on backward compatibility. constexpr size_t TypeNumberVersion = 0; /// The number of built-in types. static constexpr size_t NumberOfBuiltinTypes = TypeListSize::Value; /// Anonymous namespace for helper facilities, consider it private. namespace { /// Tells if a type is not \c rosa::NoneType. /// /// \tparam T the type to check template struct IsNotNoneType { /// Denotes if \p T is the \c rosa::NoneType or not. static constexpr bool Value = !std::is_same::value; }; } // End namespace /// Integer type to store type numbers. /// \note The narrowest unsigned integer type that is wide enough to represent /// \c NumberOfBuiltinTypes different values. using type_nr_t = typename TypeListFind< typename TypeListDrop::Type, IsNotNoneType>::Type::Second; /// Turn \c rosa::type_nr_t into a strongly typed enumeration. /// /// Values of \c rosa::type_nr_t casted to \c rosa::TypeNumbers can be used in a /// type-safe way. enum class TypeNumber : type_nr_t {}; /// A type to cast type numbers into in order to output them to streams as /// numbers and not ASCII-codes. /// /// \note Use it for safety, necessary for printing \c uint8_t values. using printable_tn_t = printable_t; /// Casts a \c rosa::TypeNumber into \c rosa::printable_tn_t. /// /// \param TN \c rosa::TypeNumber to cast. #define PRINTABLE_TN(TN) static_cast(TN) /// \name TypeNumberOf /// \brief Computes \c rosa::TypeNumber for a type. /// /// The \c rosa::TypeNumber for a type \c T can be obtained as \code /// TypeNumberOf::Value /// \endcode /// /// \note \c rosa::TypeNumber for a type is based on the corresponding squashed /// type, except for \c rosa::AtomConstant types. /// /// \sa \c rosa::SquashedType /// /// \note \c rosa::TypeNumber is the index of the type in \c rosa::BuiltinTypes /// starting from \c 1; index \c 0 indicates a non-builtin type. ///@{ /// Definition of the template for the general case. /// /// \tparam T type to get \c rosa::TypeNumber for template struct TypeNumberOf { static constexpr TypeNumber Value = static_cast( TypeListIndexOf>::Value + 1); }; /// Specialization for \c rosa::AtomConstant. /// /// \note For a \c rosa::AtomConstant type, \c rosa::TypeNumber is based on the /// \c rosa::AtomValue wrapped into the actual \c rosa::AtomConstant. template struct TypeNumberOf> { static constexpr TypeNumber Value = TypeNumberOf::Value; }; ///@} // clang-format off /// List of type names for all builtin-types, indexed via \c rosa::TypeNumber. /// /// \note Keep this definition in sync with \c rosa::BuiltinTypes. constexpr std::array NumberedTypeNames {{ "atom", "i16", "i32", "i64", "i8", "ldouble", "str", "u16", "u32", "u64", "u8", "unit", "bool", "double", "float" }}; // clang-format on /// Tells if a \c rosa::TypeNumber is valid in the software. /// /// \note A \c rosa::TypeNumber generated by an incompatible version may be /// valid but may denote a type that is different from the \c rosa::TypeNumber /// denotes in the current software. That is why this validation needs to be /// done in connection to checking \c rosa::TypeNumberVersion as well. /// /// \param TN \c rosa::TypeNumber to validate in the context of the current /// software /// /// \return Whether \p TN is valid in the current software constexpr bool validTypeNumber(const TypeNumber TN) { // \todo Duplication of static_cast into a const variable would be // possible in C++14. return 0 < static_cast(TN) && static_cast(TN) <= NumberOfBuiltinTypes; } /// Provides information about the type corresponding to a \c rosa::TypeNumber. /// /// \tparam TN \c rosa::TypeNumber to get information for /// /// \pre Statically, \p TN is a valid \c rosa::TypeNumber: /// \code /// validTypeNumber(TN) /// \endcode template struct TypeForNumber { STATIC_ASSERT(validTypeNumber(TN), "not a valid type number"); /// \p TN as \c rosa::type_nr_t. static constexpr type_nr_t TNI = static_cast(TN); /// The builtin-type corresponding to \p TN. using Type = typename TypeListAt::Type; /// The size of \c Type. static constexpr size_t Size = sizeof(Type); /// Textual representation of the builtin-type. static constexpr const char *Name = NumberedTypeNames[TNI - 1]; }; } // End namespace rosa namespace std { /// Converts a \c rosa::TypeNumber into \c std::string. /// /// \param TN \c rosa::TypeNumber to convert /// /// \return \c std::string representing \p TN inline string to_string(const rosa::TypeNumber TN) { return to_string(static_cast(TN)); } /// Dumps a \c rosa::TypeNumber to a given \c std::ostream. /// /// \param [in,out] OS output stream to dump to /// \param TN \c rosa::TypeNumber to dump /// /// \return \p OS after dumping \p TN to it inline ostream &operator<<(ostream &OS, const rosa::TypeNumber &TN) { OS << to_string(TN); return OS; } } // End namespace std #endif // ROSA_SUPPORT_TYPE_NUMBERS_HPP diff --git a/lib/deluxe/DeluxeAgent.cpp b/lib/app/AppAgent.cpp similarity index 66% rename from lib/deluxe/DeluxeAgent.cpp rename to lib/app/AppAgent.cpp index 47685c6..4e1bbc3 100644 --- a/lib/deluxe/DeluxeAgent.cpp +++ b/lib/app/AppAgent.cpp @@ -1,304 +1,305 @@ -//===-- deluxe/DeluxeAgent.cpp ----------------------------------*- C++ -*-===// +//===-- app/AppAgent.cpp ----------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeAgent.cpp +/// \file app/AppAgent.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// -/// \brief Implementation of rosa/deluxe/DeluxeAgent.hpp. +/// \brief Implementation of rosa/app/AppAgent.hpp. /// //===----------------------------------------------------------------------===// -#include "rosa/deluxe/DeluxeAgent.hpp" +#include "rosa/app/AppAgent.hpp" -#include "rosa/deluxe/DeluxeSystem.hpp" +#include "rosa/app/AppSystem.hpp" #include namespace rosa { -namespace deluxe { +namespace app { -bool DeluxeAgent::inv(void) const noexcept { +bool AppAgent::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(Unit::system()); + // \c rosa::AppSystem. + const AppSystem &DS = static_cast(Unit::system()); if (!ExecutionPolicy || !ExecutionPolicy->canHandle(Self, DS)) { return false; } // Check number of inputs and master-outputs. if (NumberOfInputs != NumberOfMasterOutputs) { return false; } // Check container sizes. if (!(InputTypes.size() == NumberOfInputs && InputNextPos.size() == NumberOfInputs && InputChanged.size() == NumberOfInputs && InputValues.size() == NumberOfInputs && MasterOutputTypes.size() == NumberOfInputs // == NumberOfMasterOutputs && Slaves.size() == NumberOfInputs)) { return false; } // Check *slave* types and validate *slave* registrations and reverse lookup // information. std::map RefIds; // Build up a reference of SlaveIds in this. for (size_t I = 0; I < NumberOfInputs; ++I) { // Fetch type-related information for the input position. const Token T = InputTypes[I]; const token_size_t TL = lengthOfToken(T); // Validate size of storage at position \c I. if (InputValues[I]->size() != TL) { return false; } // Validate input types at position \c I. for (token_size_t TI = 0; TI < TL; ++TI) { if (InputValues[I]->typeAt(static_cast(TI)) != typeAtPositionOfToken(T, TI)) { return false; } } // Check the index of next expected element for position \c I. if (InputNextPos[I] >= TL) { 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; // Prepare master-output related info for the *slave*. const Token MT = MasterOutputTypes[I]; const bool hasMT = !emptyToken(MT); // \c Slave is not empty here. // Check the `OutputType` and `MasterInputType` of the registered *slave*. const auto &A = unwrapAgent(*Slave); if (!((A.Kind == atoms::SensorKind && - static_cast(A).OutputType == T && + static_cast(A).OutputType == T && (!hasMT || - static_cast(A).MasterInputType == MT)) || + static_cast(A).MasterInputType == MT)) || (A.Kind == atoms::AgentKind && - static_cast(A).OutputType == T && + static_cast(A).OutputType == T && (!hasMT || - static_cast(A).MasterInputType == MT)))) { + static_cast(A).MasterInputType == MT)))) { 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 &O) { return O && *Slave == *O; })) { + if (std::any_of(Slaves.begin() + I + 1, Slaves.end(), + [&Slave](const Optional &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; } // Check the size of the master-input storage. if (MasterInputValue->size() != lengthOfToken(MasterInputType)) { return false; } // Check the index of next expected element from the *master*. const token_size_t MITL = lengthOfToken(MasterInputType); if ((MITL != 0 && MasterInputNextPos >= MITL) || (MITL == 0 && MasterInputNextPos != 0)) { return false; } // All checks were successful, the invariant is held. return true; } -DeluxeAgent::~DeluxeAgent(void) noexcept { +AppAgent::~AppAgent(void) noexcept { ASSERT(inv()); - LOG_TRACE_STREAM << "Destroying DeluxeAgent " << FullName << "..." - << std::endl; + LOG_TRACE_STREAM << "Destroying AppAgent " << FullName << "..." << std::endl; // Make sure \p this object is not a registered *slave*. if (Master) { ASSERT(unwrapAgent(*Master).Kind == atoms::AgentKind); // Sanity check. - DeluxeAgent &M = static_cast(unwrapAgent(*Master)); + AppAgent &M = static_cast(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. } -id_t DeluxeAgent::masterId(void) const noexcept { +id_t AppAgent::masterId(void) const noexcept { ASSERT(inv() && Master); return unwrapAgent(*Master).Id; } -const DeluxeExecutionPolicy &DeluxeAgent::executionPolicy(void) const noexcept { +const AppExecutionPolicy &AppAgent::executionPolicy(void) const noexcept { ASSERT(inv()); return *ExecutionPolicy; } -bool DeluxeAgent::setExecutionPolicy( - std::unique_ptr &&EP) noexcept { +bool AppAgent::setExecutionPolicy( + std::unique_ptr &&EP) noexcept { ASSERT(inv()); - LOG_TRACE_STREAM << "DeluxeAgent " << FullName << " setting execution policy " + LOG_TRACE_STREAM << "AppAgent " << 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(Unit::system()); + // \c rosa::AppSystem. + const AppSystem &DS = static_cast(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; + LOG_TRACE_STREAM << "Execution policy " << *EP << " cannot handle AppAgent " + << FullName << std::endl; } ASSERT(inv()); return Success; } -Optional DeluxeAgent::master(void) const noexcept { +Optional AppAgent::master(void) const noexcept { ASSERT(inv()); return Master; } -void DeluxeAgent::registerMaster(const Optional _Master) noexcept { +void AppAgent::registerMaster(const Optional _Master) noexcept { ASSERT(inv() && (!_Master || unwrapAgent(*_Master).Kind == atoms::AgentKind)); Master = _Master; ASSERT(inv()); } -Token DeluxeAgent::inputType(const size_t Pos) const noexcept { +Token AppAgent::inputType(const size_t Pos) const noexcept { ASSERT(inv() && Pos < NumberOfInputs); return InputTypes[Pos]; } -Token DeluxeAgent::masterOutputType(const size_t Pos) const noexcept { +Token AppAgent::masterOutputType(const size_t Pos) const noexcept { ASSERT(inv() && Pos < NumberOfMasterOutputs); return MasterOutputTypes[Pos]; } -Optional DeluxeAgent::slave(const size_t Pos) const noexcept { +Optional AppAgent::slave(const size_t Pos) const noexcept { ASSERT(inv() && Pos < NumberOfInputs); return Slaves[Pos]; } -void DeluxeAgent::registerSlave(const size_t Pos, - const Optional Slave) noexcept { - ASSERT(inv() && Pos < NumberOfInputs && - (!Slave || - (unwrapAgent(*Slave).Kind == atoms::SensorKind && - static_cast(unwrapAgent(*Slave)).OutputType == - InputTypes[Pos] && - (emptyToken(MasterOutputTypes[Pos]) || - static_cast(unwrapAgent(*Slave)) - .MasterInputType == MasterOutputTypes[Pos])) || - (unwrapAgent(*Slave).Kind == atoms::AgentKind && - static_cast(unwrapAgent(*Slave)).OutputType == - InputTypes[Pos] && - (emptyToken(MasterOutputTypes[Pos]) || - static_cast(unwrapAgent(*Slave)) - .MasterInputType == MasterOutputTypes[Pos])))); +void AppAgent::registerSlave(const size_t Pos, + const Optional Slave) noexcept { + ASSERT( + inv() && Pos < NumberOfInputs && + (!Slave || + (unwrapAgent(*Slave).Kind == atoms::SensorKind && + static_cast(unwrapAgent(*Slave)).OutputType == + InputTypes[Pos] && + (emptyToken(MasterOutputTypes[Pos]) || + static_cast(unwrapAgent(*Slave)).MasterInputType == + MasterOutputTypes[Pos])) || + (unwrapAgent(*Slave).Kind == atoms::AgentKind && + static_cast(unwrapAgent(*Slave)).OutputType == + InputTypes[Pos] && + (emptyToken(MasterOutputTypes[Pos]) || + static_cast(unwrapAgent(*Slave)).MasterInputType == + MasterOutputTypes[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(); + Slaves[It->second] = {}; // Optional(); 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(A).registerMaster({}); + static_cast(A).registerMaster({}); } else { ASSERT(A.Kind == atoms::SensorKind); // Sanity check. - static_cast(A).registerMaster({}); + static_cast(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 { +size_t AppAgent::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 { +void AppAgent::handleTrigger(atoms::Trigger) noexcept { ASSERT(inv()); FP(); ASSERT(inv()); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/namespace.cpp b/lib/app/AppAtoms.cpp old mode 100755 new mode 100644 similarity index 71% rename from lib/deluxe/namespace.cpp rename to lib/app/AppAtoms.cpp index 3d8e057..5840e92 --- a/lib/deluxe/namespace.cpp +++ b/lib/app/AppAtoms.cpp @@ -1,26 +1,26 @@ -//===-- deluxe/namespace.cpp ------------------------------------*- C++ -*-===// +//===-- app/AppAtoms.cpp ----------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/namespace.cpp +/// \file app/AppAtoms.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017 +/// \date 2017-2020 /// -/// \brief Implementation for rosa/deluxe/namespace.h. +/// \brief Implementation of rosa/app/AppAtoms.hpp. /// /// \note Empty implementation, source file here to have a compile database -/// entry for rosa/deluxe/namespace.h. +/// entry for rosa/app/AppAtoms.hpp. /// //===----------------------------------------------------------------------===// -#include "rosa/deluxe/namespace.h" +#include "rosa/app/AppAtoms.hpp" diff --git a/lib/app/AppExecutionPolicy.cpp b/lib/app/AppExecutionPolicy.cpp new file mode 100644 index 0000000..4ca83f9 --- /dev/null +++ b/lib/app/AppExecutionPolicy.cpp @@ -0,0 +1,72 @@ +//===-- app/AppExecutionPolicy.cpp ------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +// Distributed under the terms and conditions of the Boost Software License 1.0. +// See accompanying file LICENSE. +// +// If you did not receive a copy of the license file, see +// http://www.boost.org/LICENSE_1_0.txt. +// +//===----------------------------------------------------------------------===// +/// +/// \file app/AppExecutionPolicy.cpp +/// +/// \author David Juhasz (david.juhasz@tuwien.ac.at) +/// +/// \date 2019-2020 +/// +/// \brief Implementation for rosa/app/AppExecutionPolicy.h. +/// +//===----------------------------------------------------------------------===// + +#include "rosa/app/AppExecutionPolicy.h" +#include "rosa/app/AppSystem.hpp" + +#include "executionpolicies/AwaitAll.h" +#include "executionpolicies/AwaitAny.h" +#include "executionpolicies/Decimation.h" + +namespace rosa { +namespace app { + +std::unique_ptr +AppExecutionPolicy::decimation(const size_t D) { + return std::unique_ptr(new Decimation(D)); +} + +std::unique_ptr +AppExecutionPolicy::awaitAll(const std::set &S) { + return std::unique_ptr(new AwaitAll(S)); +} + +std::unique_ptr +AppExecutionPolicy::awaitAny(const std::set &S) { + return std::unique_ptr(new AwaitAny(S)); +} + +bool AppExecutionPolicy::isAppAgent(const AgentHandle H, + const AppSystem &S) const noexcept { + return S.isAppAgent(H); +} + +size_t AppExecutionPolicy::numberOfAppAgentInputs(const AgentHandle H, + const AppSystem &S) const + noexcept { + auto A = S.getAppAgent(H); + return A ? A->NumberOfInputs : 0; +} + +} // End namespace app +} // End namespace rosa + +namespace std { + +string to_string(const rosa::app::AppExecutionPolicy &EP) { return EP.dump(); } + +ostream &operator<<(ostream &OS, const rosa::app::AppExecutionPolicy &EP) { + OS << to_string(EP); + return OS; +} + +} // End namespace std diff --git a/lib/deluxe/DeluxeSensor.cpp b/lib/app/AppSensor.cpp similarity index 58% rename from lib/deluxe/DeluxeSensor.cpp rename to lib/app/AppSensor.cpp index 0906948..cf0f83d 100644 --- a/lib/deluxe/DeluxeSensor.cpp +++ b/lib/app/AppSensor.cpp @@ -1,138 +1,136 @@ -//===-- deluxe/DeluxeSensor.cpp ---------------------------------*- C++ -*-===// +//===-- app/AppSensor.cpp ---------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeSensor.cpp +/// \file app/AppSensor.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017-2019 +/// \date 2017-2020 /// -/// \brief Implementation of rosa/deluxe/DeluxeSensor.hpp. +/// \brief Implementation of rosa/app/AppSensor.hpp. /// //===----------------------------------------------------------------------===// -#include "rosa/deluxe/DeluxeSensor.hpp" +#include "rosa/app/AppSensor.hpp" -#include "rosa/deluxe/DeluxeSystem.hpp" +#include "rosa/app/AppSystem.hpp" namespace rosa { -namespace deluxe { +namespace app { -bool DeluxeSensor::inv(void) const noexcept { +bool AppSensor::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(Unit::system()); + // \c rosa::AppSystem. + const AppSystem &DS = static_cast(Unit::system()); if (!ExecutionPolicy || !ExecutionPolicy->canHandle(Self, DS)) { return false; } // Check the index of next expected element from the *master*. const token_size_t MITL = lengthOfToken(MasterInputType); if ((MITL != 0 && MasterInputNextPos >= MITL) || (MITL == 0 && MasterInputNextPos != 0)) { return false; } // All checks were successful, the invariant is held. return true; } -id_t DeluxeSensor::masterId(void) const noexcept { +id_t AppSensor::masterId(void) const noexcept { ASSERT(Master); return unwrapAgent(*Master).Id; } -DeluxeSensor::~DeluxeSensor(void) noexcept { +AppSensor::~AppSensor(void) noexcept { ASSERT(inv()); - LOG_TRACE_STREAM << "Destroying DeluxeSensor " << FullName << "..." - << std::endl; + LOG_TRACE_STREAM << "Destroying AppSensor " << FullName << "..." << std::endl; // Make sure \p this object is not a registered *slave*. if (Master) { ASSERT(unwrapAgent(*Master).Kind == atoms::AgentKind); // Sanity check. - DeluxeAgent &M = static_cast(unwrapAgent(*Master)); + AppAgent &M = static_cast(unwrapAgent(*Master)); ASSERT(M.positionOfSlave(self()) != M.NumberOfInputs); // Sanity check. M.registerSlave(M.positionOfSlave(self()), {}); Master = {}; } } -const DeluxeExecutionPolicy &DeluxeSensor::executionPolicy(void) const - noexcept { +const AppExecutionPolicy &AppSensor::executionPolicy(void) const noexcept { ASSERT(inv()); return *ExecutionPolicy; } -bool DeluxeSensor::setExecutionPolicy( - std::unique_ptr &&EP) noexcept { +bool AppSensor::setExecutionPolicy( + std::unique_ptr &&EP) noexcept { ASSERT(inv()); - LOG_TRACE_STREAM << "DeluxeSensor " << FullName - << " setting execution policy " << *EP << std::endl; + LOG_TRACE_STREAM << "AppSensor " << 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(Unit::system()); + // \c rosa::AppSystem. + const AppSystem &DS = static_cast(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; + << " cannot handle AppSensor " << FullName << std::endl; } ASSERT(inv()); return Success; } -Optional DeluxeSensor::master(void) const noexcept { +Optional AppSensor::master(void) const noexcept { ASSERT(inv()); return Master; } -void DeluxeSensor::registerMaster(const Optional _Master) noexcept { +void AppSensor::registerMaster(const Optional _Master) noexcept { ASSERT(inv() && (!_Master || unwrapAgent(*_Master).Kind == atoms::AgentKind)); Master = _Master; ASSERT(inv()); } -void DeluxeSensor::clearSimulationDataSource(void) noexcept { +void AppSensor::clearSimulationDataSource(void) noexcept { ASSERT(inv()); SFP = nullptr; ASSERT(inv()); } -bool DeluxeSensor::simulationDataSourceIsSet(void) const noexcept { +bool AppSensor::simulationDataSourceIsSet(void) const noexcept { ASSERT(inv()); return SFP != nullptr; } -void DeluxeSensor::handleTrigger(atoms::Trigger) noexcept { +void AppSensor::handleTrigger(atoms::Trigger) noexcept { ASSERT(inv() && MasterInputNextPos == 0); // Process master-input. MFP(); // Obtain the next sensory value. // \note Execution policy is respected within the data source function. - // Use \c rosa::deluxe::DeluxeSensor::SFP if set, otherwise - // \c rosa::deluxe::DeluxeSensor::FP. + // Use \c rosa::app::AppSensor::SFP if set, otherwise + // \c rosa::app::AppSensor::FP. const H &F = SFP ? SFP : FP; F(); ASSERT(inv()); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/app/AppSystem.cpp b/lib/app/AppSystem.cpp new file mode 100644 index 0000000..93c1619 --- /dev/null +++ b/lib/app/AppSystem.cpp @@ -0,0 +1,70 @@ +//===-- app/AppSystem.cpp ---------------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +// Distributed under the terms and conditions of the Boost Software License 1.0. +// See accompanying file LICENSE. +// +// If you did not receive a copy of the license file, see +// http://www.boost.org/LICENSE_1_0.txt. +// +//===----------------------------------------------------------------------===// +/// +/// \file app/AppSystem.cpp +/// +/// \author David Juhasz (david.juhasz@tuwien.ac.at) +/// +/// \date 2017-2020 +/// +/// \brief Implementation of rosa/app/AppSystem.hpp. +/// +//===----------------------------------------------------------------------===// + +#include "rosa/app/AppSystem.hpp" + +#include "AppSystemImpl.hpp" + +namespace rosa { +namespace app { + +std::unique_ptr +AppSystem::createSystem(const std::string &Name) noexcept { + return std::unique_ptr(new AppSystemImpl(Name)); +} + +Optional AppSystem::getAppSensor(const AgentHandle &H) const + noexcept { + if (isAppSensor(H)) { + return {static_cast(unwrapAgent(H))}; + } else { + return {}; + } +} + +Optional AppSystem::getAppSensor(AgentHandle &H) const noexcept { + if (isAppSensor(H)) { + return {static_cast(unwrapAgent(H))}; + } else { + return {}; + } +} + +Optional AppSystem::getAppAgent(const AgentHandle &H) const + noexcept { + if (isAppAgent(H)) { + return {static_cast(unwrapAgent(H))}; + } else { + return {}; + } +} + +Optional AppSystem::getAppAgent(AgentHandle &H) const noexcept { + if (isAppAgent(H)) { + return {static_cast(unwrapAgent(H))}; + } else { + return {}; + } +} + +} // End namespace app +} // End namespace rosa diff --git a/lib/deluxe/DeluxeSystemImpl.cpp b/lib/app/AppSystemImpl.cpp old mode 100755 new mode 100644 similarity index 53% rename from lib/deluxe/DeluxeSystemImpl.cpp rename to lib/app/AppSystemImpl.cpp index d660441..09c9530 --- a/lib/deluxe/DeluxeSystemImpl.cpp +++ b/lib/app/AppSystemImpl.cpp @@ -1,43 +1,42 @@ -//===-- deluxe/DeluxeSystemImpl.cpp -----------------------------*- C++ -*-===// +//===-- app/AppSystemImpl.cpp -----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeSystemImpl.cpp +/// \file app/AppSystemImpl.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017 +/// \date 2017-2020 /// -/// \brief Implementation of deluxe/DeluxeSystemImpl.hpp. +/// \brief Implementation of app/AppSystemImpl.hpp. /// //===----------------------------------------------------------------------===// -#include "DeluxeSystemImpl.hpp" +#include "AppSystemImpl.hpp" namespace rosa { -namespace deluxe { +namespace app { -DeluxeSystemImpl::DeluxeSystemImpl(const std::string &Name) noexcept - : DeluxeSystem(), - MessagingSystemImpl(Name) { - LOG_TRACE("System '" + Name + "' has a deluxe flavor"); +AppSystemImpl::AppSystemImpl(const std::string &Name) noexcept + : AppSystem(), MessagingSystemImpl(Name) { + LOG_TRACE("System '" + Name + "' has application flavor"); } -bool DeluxeSystemImpl::isDeluxeSensor(const AgentHandle &H) const noexcept { +bool AppSystemImpl::isAppSensor(const AgentHandle &H) const noexcept { return unwrapAgent(H).Kind == atoms::SensorKind; } -bool DeluxeSystemImpl::isDeluxeAgent(const AgentHandle &H) const noexcept { +bool AppSystemImpl::isAppAgent(const AgentHandle &H) const noexcept { return unwrapAgent(H).Kind == atoms::AgentKind; } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/DeluxeSystemImpl.hpp b/lib/app/AppSystemImpl.hpp old mode 100755 new mode 100644 similarity index 66% rename from lib/deluxe/DeluxeSystemImpl.hpp rename to lib/app/AppSystemImpl.hpp index 62c0c59..e6529c2 --- a/lib/deluxe/DeluxeSystemImpl.hpp +++ b/lib/app/AppSystemImpl.hpp @@ -1,120 +1,120 @@ -//===-- deluxe/DeluxeSystemImpl.hpp -----------------------------*- C++ -*-===// +//===-- app/AppSystemImpl.hpp -----------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeSystemImpl.hpp +/// \file app/AppSystemImpl.hpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017 +/// \date 2017-2020 /// /// \brief Declaration of a basic implementation of the -/// \c rosa::deluxe::DeluxeSystem interface. +/// \c rosa::app::AppSystem interface. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_LIB_DELUXE_DELUXESYSTEMIMPL_HPP -#define ROSA_LIB_DELUXE_DELUXESYSTEMIMPL_HPP +#ifndef ROSA_LIB_APP_APPSYSTEMIMPL_HPP +#define ROSA_LIB_APP_APPSYSTEMIMPL_HPP #include "../core/MessagingSystemImpl.hpp" -#include "rosa/deluxe/DeluxeSystem.hpp" +#include "rosa/app/AppSystem.hpp" namespace rosa { -namespace deluxe { +namespace app { -/// Implements \c rosa::deluxe::DeluxeSystem by extending +/// Implements \c rosa::app::AppSystem by extending /// \c rosa::MessagingSystemImpl. -class DeluxeSystemImpl : public DeluxeSystem, public MessagingSystemImpl { +class AppSystemImpl : public AppSystem, public MessagingSystemImpl { /// Alies for the base-class \c rosa::MessagingSystemImpl. using Base = MessagingSystemImpl; public: /// Creates an instance. /// /// \param Name name of the new instance - DeluxeSystemImpl(const std::string &Name) noexcept; + AppSystemImpl(const std::string &Name) noexcept; - /// \defgroup DeluxeSystemImplCallForwardings Call forwardings of rosa::deluxe::DeluxeSystemImpl + /// \defgroup AppSystemImplCallForwardings Call forwardings of + /// rosa::app::AppSystemImpl /// - /// \c rosa::deluxe::DeluxeSystemImpl call forwardings + /// \c rosa::app::AppSystemImpl call forwardings /// /// \note Simply forwarding calls to implementations provided by - /// \c rosa::deluxe::DeluxeSystem::Base for the \c rosa::MessagingSystem + /// \c rosa::app::AppSystem::Base for the \c rosa::MessagingSystem /// interface. /// /// \todo How could we use the inherited implementations in a simpler way? ///@{ bool operator==(const System &Other) const noexcept override { return Base::operator==(Other); } protected: id_t nextId(void) noexcept override { return Base::nextId(); } bool isSystemCleaned(void) const noexcept override { return Base::isSystemCleaned(); } void markCleaned(void) noexcept override { Base::markCleaned(); } void registerUnit(Unit &U) noexcept override { Base::registerUnit(U); } void destroyUnit(Unit &U) noexcept override { Base::destroyUnit(U); } bool isUnitRegistered(const Unit &U) const noexcept override { return Base::isUnitRegistered(U); } public: const std::string &name(void) const noexcept override { return Base::name(); } size_t numberOfConstructedUnits(void) const noexcept override { return Base::numberOfConstructedUnits(); } size_t numberOfLiveUnits(void) const noexcept override { return Base::numberOfLiveUnits(); } bool empty(void) const noexcept override { return Base::empty(); } void send(const AgentHandle &H, message_t &&M) noexcept override { Base::send(H, std::move(M)); } ///@} /// Tells whether a \c rosa::AgentHandle refers to a - /// \c rosa::deluxe::DeluxeSensor owned by \p this object. + /// \c rosa::app::AppSensor owned by \p this object. /// /// \param H \c rosa::AgentHandle to check /// - /// \return whether \p H refers to a \c rosa::deluxe::DeluxeSensor owned by + /// \return whether \p H refers to a \c rosa::app::AppSensor owned by /// \p this object - bool isDeluxeSensor(const AgentHandle &H) const noexcept override; + bool isAppSensor(const AgentHandle &H) const noexcept override; /// Tells whether a \c rosa::AgentHandle refers to a - /// \c rosa::deluxe::DeluxeAgent owned by \p this object. + /// \c rosa::app::AppAgent owned by \p this object. /// /// \param H \c rosa::AgentHandle to check /// - /// \return whether \p H refers to a \c rosa::deluxe::DeluxeAgent owned by + /// \return whether \p H refers to a \c rosa::app::AppAgent owned by /// \p this object - bool isDeluxeAgent(const AgentHandle &H) const noexcept override; - + bool isAppAgent(const AgentHandle &H) const noexcept override; }; -} // End namespace deluxe +} // End namespace app } // End namespace rosa -#endif // ROSA_LIB_DELUXE_DELUXESYSTEMIMPL_HPP +#endif // ROSA_LIB_APP_APPSYSTEMIMPL_HPP diff --git a/lib/deluxe/DeluxeTuple.cpp b/lib/app/AppTuple.cpp similarity index 64% rename from lib/deluxe/DeluxeTuple.cpp rename to lib/app/AppTuple.cpp index 9b8e903..39c43b8 100644 --- a/lib/deluxe/DeluxeTuple.cpp +++ b/lib/app/AppTuple.cpp @@ -1,34 +1,32 @@ -//===-- deluxe/DeluxeTuple.cpp ----------------------------------*- C++ -*-===// +//===-- app/AppTuple.cpp ----------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeTuple.cpp +/// \file app/AppTuple.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Implementation of rosa/deluxe/DeluxeTuple.hpp. +/// \brief Implementation of rosa/app/AppTuple.hpp. /// /// //===----------------------------------------------------------------------===// -#include "rosa/deluxe/DeluxeTuple.hpp" +#include "rosa/app/AppTuple.hpp" namespace rosa { -namespace deluxe { +namespace app { -void DeluxeTuple<>::dump(std::ostream &OS) noexcept { - OS << "{ }"; -} +void AppTuple<>::dump(std::ostream &OS) noexcept { OS << "{ }"; } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/app/Application.cpp b/lib/app/Application.cpp new file mode 100644 index 0000000..38d3b8f --- /dev/null +++ b/lib/app/Application.cpp @@ -0,0 +1,224 @@ +//===-- app/Application.cpp -------------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +// Distributed under the terms and conditions of the Boost Software License 1.0. +// See accompanying file LICENSE. +// +// If you did not receive a copy of the license file, see +// http://www.boost.org/LICENSE_1_0.txt. +// +//===----------------------------------------------------------------------===// +/// +/// \file app/Application.cpp +/// +/// \author David Juhasz (david.juhasz@tuwien.ac.at) +/// +/// \date 2017-2020 +/// +/// \brief Implementation for rosa/app/Application.hpp. +/// +//===----------------------------------------------------------------------===// + +#define ROSA_LIB_APP_APPLICATION_CPP // For including helper macros. + +#include "rosa/app/Application.hpp" + +#include +#include + +namespace rosa { +namespace app { + +std::unique_ptr +Application::create(const std::string &Name) noexcept { + return std::unique_ptr(new Application(Name)); +} + +Application::Application(const std::string &Name) noexcept + : System(AppSystem::createSystem(Name)) { + LOG_TRACE("Application for '" + System->name() + "' is created."); +} + +Application::~Application(void) noexcept { + // \c rosa::app::Application::System is not used outside, just clean it. + for (auto U : AppUnits) { + System->destroyAgent(U); + } + // \note \c System will be marked clean by SystemImpl::~SystemImpl. + LOG_TRACE("Application for '" + System->name() + + "' prepared for destruction."); +} + +Optional +Application::getExecutionPolicy(AgentHandle Unit) const noexcept { + if (System->isAppSensor(Unit)) { + return {System->getAppSensor(Unit)->executionPolicy()}; + } else if (System->isAppAgent(Unit)) { + return {System->getAppAgent(Unit)->executionPolicy()}; + } else { + return {}; + } +} + +Application::ErrorCode Application::setExecutionPolicy( + AgentHandle Unit, + std::unique_ptr &&ExecutionPolicy) noexcept { + // Generate trace log. + auto &Trace = LOG_TRACE_STREAM; + Trace << "Setting execution policy of " << System->unwrapAgent(Unit).FullName + << " to "; + if (ExecutionPolicy) { + Trace << "'" << ExecutionPolicy->dump() << "'\n"; + } else { + Trace << "[]\n"; + APPRETERROR(ErrorCode::UnsuitableExecutionPolicy); + } + + if (System->isAppSensor(Unit)) { + const bool Success = System->getAppSensor(Unit)->setExecutionPolicy( + std::move(ExecutionPolicy)); + if (!Success) { + APPRETERROR(ErrorCode::UnsuitableExecutionPolicy); + } else { + return ErrorCode::NoError; + } + } else if (System->isAppAgent(Unit)) { + const bool Success = System->getAppAgent(Unit)->setExecutionPolicy( + std::move(ExecutionPolicy)); + if (!Success) { + APPRETERROR(ErrorCode::UnsuitableExecutionPolicy); + } else { + return ErrorCode::NoError; + } + } else { + APPRETERROR(ErrorCode::NotUnit); + } +} + +Application::ErrorCode +Application::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"; + + // Make sure preconditions are met. + if (!System->isAppAgent(Agent)) { + APPRETERROR(ErrorCode::NotAgent); + } else if (!System->isAppSensor(Sensor)) { + APPRETERROR(ErrorCode::NotSensor); + } + auto A = System->getAppAgent(Agent); + auto S = System->getAppSensor(Sensor); + ASSERT(A && S); // Sanity check. + if (Pos >= A->NumberOfInputs) { + APPRETERROR(ErrorCode::WrongPosition); + } else if (A->inputType(Pos) != S->OutputType || + (!emptyToken(A->masterOutputType(Pos)) && + A->masterOutputType(Pos) != S->MasterInputType)) { + APPRETERROR(ErrorCode::TypeMismatch); + } else if (A->slave(Pos)) { + APPRETERROR(ErrorCode::AlreadyHasSlave); + } else if (S->master()) { + APPRETERROR(ErrorCode::AlreadyHasMaster); + } + + // Do register. + A->registerSlave(Pos, {Sensor}); + S->registerMaster({Agent}); + + return ErrorCode::NoError; +} + +Application::ErrorCode +Application::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"; + + // Make sure preconditions are met. + if (!(System->isAppAgent(Master) && System->isAppAgent(Slave))) { + APPRETERROR(ErrorCode::NotAgent); + } + auto M = System->getAppAgent(Master); + auto S = System->getAppAgent(Slave); + ASSERT(M && S); // Sanity check. + if (Pos >= M->NumberOfInputs) { + APPRETERROR(ErrorCode::WrongPosition); + } else if (M->inputType(Pos) != S->OutputType || + (!emptyToken(M->masterOutputType(Pos)) && + M->masterOutputType(Pos) != S->MasterInputType)) { + APPRETERROR(ErrorCode::TypeMismatch); + } else if (M->slave(Pos)) { + APPRETERROR(ErrorCode::AlreadyHasSlave); + } else if (S->master()) { + APPRETERROR(ErrorCode::AlreadyHasMaster); + } + + // Do register. + M->registerSlave(Pos, {Slave}); + S->registerMaster({Master}); + + return ErrorCode::NoError; +} + +std::weak_ptr Application::getSystem(void) const noexcept { + return std::weak_ptr(System); +} + +void Application::initializeSimulation(void) noexcept { + LOG_INFO_STREAM << "Initializing simulation for " << System->name() + << ". Clearing all data sources.\n"; + // Clear simulation data sources from sensors. + for (auto U : AppUnits) { + if (auto S = System->getAppSensor(U)) { + S->clearSimulationDataSource(); + } + } +} + +void Application::simulate(const size_t NumCycles) const noexcept { + DEBUG(for (auto H + : AppUnits) { + std::stringstream Message; + Message << System->unwrapAgent(H).FullName << " is an App " + << " " << (System->isAppSensor(H) ? "Sensor" : "Agent"); + if (System->isAppSensor(H)) + Message << " with it's data source " + << (!System->getAppSensor(H)->simulationDataSourceIsSet() + ? "not " + : "set"); + Message << '\n'; + LOG_TRACE_STREAM << Message.str(); + }); + + ASSERT( + std::all_of(AppUnits.begin(), AppUnits.end(), [&](const AgentHandle &H) { + return System->isAppAgent(H) || + System->isAppSensor(H) && + System->getAppSensor(H)->simulationDataSourceIsSet(); + })); + for (size_t I = 1; I <= NumCycles; ++I) { + LOG_TRACE("Simulation cycle: " + std::to_string(I)); + for (auto U : AppUnits) { + U.sendMessage(Message::create(atoms::Trigger::Value)); + } + } +} + +} // End namespace app +} // End namespace rosa diff --git a/lib/app/CMakeLists.txt b/lib/app/CMakeLists.txt new file mode 100644 index 0000000..2fac93a --- /dev/null +++ b/lib/app/CMakeLists.txt @@ -0,0 +1,32 @@ +set(LIB_INCLUDE_DIR ${ROSA_MAIN_INCLUDE_DIR}/rosa/app) + +add_library(ROSAApp + ${LIB_INCLUDE_DIR}/namespace.h + namespace.cpp + ${LIB_INCLUDE_DIR}/AppAtoms.hpp + AppAtoms.cpp + ${LIB_INCLUDE_DIR}/AppTuple.hpp + AppTuple.cpp + executionpolicies/Decimation.h + executionpolicies/Decimation.cpp + executionpolicies/AwaitBase.h + executionpolicies/AwaitBase.cpp + executionpolicies/AwaitAll.h + executionpolicies/AwaitAll.cpp + executionpolicies/AwaitAny.h + executionpolicies/AwaitAny.cpp + ${LIB_INCLUDE_DIR}/AppExecutionPolicy.h + AppExecutionPolicy.cpp + ${LIB_INCLUDE_DIR}/AppSensor.hpp + AppSensor.cpp + ${LIB_INCLUDE_DIR}/AppAgent.hpp + AppAgent.cpp + ${LIB_INCLUDE_DIR}/AppSystem.hpp + AppSystem.cpp + AppSystemImpl.hpp + AppSystemImpl.cpp + ${LIB_INCLUDE_DIR}/Application.hpp + Application.cpp + ) + +ROSA_add_library_dependencies(ROSAApp ROSACore) diff --git a/lib/deluxe/executionpolicies/AwaitAll.cpp b/lib/app/executionpolicies/AwaitAll.cpp similarity index 79% rename from lib/deluxe/executionpolicies/AwaitAll.cpp rename to lib/app/executionpolicies/AwaitAll.cpp index 4d5c449..784266e 100644 --- a/lib/deluxe/executionpolicies/AwaitAll.cpp +++ b/lib/app/executionpolicies/AwaitAll.cpp @@ -1,40 +1,40 @@ -//===-- deluxe/executionpolicies/AwaitAll.cpp -------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitAll.cpp ----------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitAll.cpp +/// \file app/executionpolicies/AwaitAll.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Implementation for deluxe/executionpolicies/AwaitAll.h. +/// \brief Implementation for app/executionpolicies/AwaitAll.h. /// //===----------------------------------------------------------------------===// #include "AwaitAll.h" #include namespace rosa { -namespace deluxe { +namespace app { AwaitAll::AwaitAll(const std::set &S) : AwaitBase(S, CheckerType(std::all_of::const_iterator, std::function>)) {} std::string AwaitAll::dump(void) const noexcept { return "Await all of " + dumpS(); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/executionpolicies/AwaitAll.h b/lib/app/executionpolicies/AwaitAll.h similarity index 70% rename from lib/deluxe/executionpolicies/AwaitAll.h rename to lib/app/executionpolicies/AwaitAll.h index deab70c..f5c485e 100644 --- a/lib/deluxe/executionpolicies/AwaitAll.h +++ b/lib/app/executionpolicies/AwaitAll.h @@ -1,54 +1,54 @@ -//===-- deluxe/executionpolicies/AwaitAll.h ---------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitAll.h ---------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitAll.h +/// \file app/executionpolicies/AwaitAll.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \brief Declaration of the *execution policy* *await all*. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H -#define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H +#ifndef ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITALL_H +#define ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITALL_H #include "AwaitBase.h" namespace rosa { -namespace deluxe { +namespace app { /// Implementation of the *execution policy* *await all*. /// -/// \see \c rosa::deluxe::DeluxeExecutionPolicy::awaitAll() +/// \see \c rosa::app::AppExecutionPolicy::awaitAll() class AwaitAll : public AwaitBase { public: /// Constructor. /// - /// The constructor instatiates \c rosa::deluxe::AwaitBase so that execution + /// The constructor instatiates \c rosa::app::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 app } // End namespace rosa -#endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITALL_H +#endif // ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITALL_H diff --git a/lib/deluxe/executionpolicies/AwaitAny.cpp b/lib/app/executionpolicies/AwaitAny.cpp similarity index 79% rename from lib/deluxe/executionpolicies/AwaitAny.cpp rename to lib/app/executionpolicies/AwaitAny.cpp index 7395d91..e63a5b6 100644 --- a/lib/deluxe/executionpolicies/AwaitAny.cpp +++ b/lib/app/executionpolicies/AwaitAny.cpp @@ -1,40 +1,40 @@ -//===-- deluxe/executionpolicies/AwaitAny.cpp -------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitAny.cpp ----------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitAny.cpp +/// \file app/executionpolicies/AwaitAny.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Implementation for deluxe/executionpolicies/AwaitAny.h. +/// \brief Implementation for app/executionpolicies/AwaitAny.h. /// //===----------------------------------------------------------------------===// #include "AwaitAny.h" #include namespace rosa { -namespace deluxe { +namespace app { AwaitAny::AwaitAny(const std::set &S) : AwaitBase(S, CheckerType(std::any_of::const_iterator, std::function>)) {} std::string AwaitAny::dump(void) const noexcept { return "Await any of " + dumpS(); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/executionpolicies/AwaitAny.h b/lib/app/executionpolicies/AwaitAny.h similarity index 70% rename from lib/deluxe/executionpolicies/AwaitAny.h rename to lib/app/executionpolicies/AwaitAny.h index 2ec8361..2ee34f0 100644 --- a/lib/deluxe/executionpolicies/AwaitAny.h +++ b/lib/app/executionpolicies/AwaitAny.h @@ -1,54 +1,54 @@ -//===-- deluxe/executionpolicies/AwaitAny.h ---------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitAny.h ---------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitAny.h +/// \file app/executionpolicies/AwaitAny.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \brief Declaration of the *execution policy* *await any*. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H -#define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H +#ifndef ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITANY_H +#define ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITANY_H #include "AwaitBase.h" namespace rosa { -namespace deluxe { +namespace app { /// Implementation of the *execution policy* *await any*. /// -/// \see \c rosa::deluxe::DeluxeExecutionPolicy::awaitAny() +/// \see \c rosa::app::AppExecutionPolicy::awaitAny() class AwaitAny : public AwaitBase { public: /// Constructor. /// - /// The constructor instatiates \c rosa::deluxe::AwaitBase so that execution + /// The constructor instatiates \c rosa::app::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 app } // End namespace rosa -#endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITANY_H +#endif // ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITANY_H diff --git a/lib/deluxe/executionpolicies/AwaitBase.cpp b/lib/app/executionpolicies/AwaitBase.cpp similarity index 78% rename from lib/deluxe/executionpolicies/AwaitBase.cpp rename to lib/app/executionpolicies/AwaitBase.cpp index 4e03789..2ed0b09 100644 --- a/lib/deluxe/executionpolicies/AwaitBase.cpp +++ b/lib/app/executionpolicies/AwaitBase.cpp @@ -1,66 +1,66 @@ -//===-- deluxe/executionpolicies/AwaitBase.cpp ------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitBase.cpp ---------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitBase.cpp +/// \file app/executionpolicies/AwaitBase.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Implementation for deluxe/executionpolicies/AwaitBase.h. +/// \brief Implementation for app/executionpolicies/AwaitBase.h. /// //===----------------------------------------------------------------------===// #include "AwaitBase.h" #include "rosa/support/debug.hpp" #include #include namespace rosa { -namespace deluxe { +namespace app { AwaitBase::AwaitBase(const std::set &S, CheckerType &&Checker) : Set(S), Checker(Checker) {} -bool AwaitBase::canHandle(const AgentHandle H, const DeluxeSystem &S) const +bool AwaitBase::canHandle(const AgentHandle H, const AppSystem &S) const noexcept { - return isDeluxeAgent(H, S) && - canHandleNumberOfInputs(numberOfDeluxeAgentInputs(H, S)); + return isAppAgent(H, S) && + canHandleNumberOfInputs(numberOfAppAgentInputs(H, S)); } bool AwaitBase::shouldProcess(const std::vector &InputChanged) noexcept { // Sanity check of usage. ASSERT(canHandleNumberOfInputs(InputChanged.size())); return Checker(Set.begin(), Set.end(), [&InputChanged](const size_t I) { return InputChanged[I]; }); } bool AwaitBase::canHandleNumberOfInputs(const size_t NumberOfInputs) const noexcept { const auto MaxElemIt = std::max_element(Set.begin(), Set.end()); const size_t MaxElem = (MaxElemIt == Set.end()) ? 0 : *MaxElemIt; return MaxElem <= NumberOfInputs; } std::string AwaitBase::dumpS(void) const noexcept { std::stringstream SS; SS << "["; for (const auto &Value : Set) { SS << " " << Value; } SS << " ]"; return SS.str(); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/executionpolicies/AwaitBase.h b/lib/app/executionpolicies/AwaitBase.h similarity index 72% rename from lib/deluxe/executionpolicies/AwaitBase.h rename to lib/app/executionpolicies/AwaitBase.h index 9483c3d..52b774f 100644 --- a/lib/deluxe/executionpolicies/AwaitBase.h +++ b/lib/app/executionpolicies/AwaitBase.h @@ -1,111 +1,112 @@ -//===-- deluxe/executionpolicies/AwaitBase.h --------------------*- C++ -*-===// +//===-- app/executionpolicies/AwaitBase.h --------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/AwaitBase.h +/// \file app/executionpolicies/AwaitBase.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \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 +#ifndef ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITBASE_H +#define ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITBASE_H -#include "rosa/deluxe/DeluxeExecutionPolicy.h" +#include "rosa/app/AppExecutionPolicy.h" #include namespace rosa { -namespace deluxe { +namespace app { /// 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 +/// The class implements the \c rosa::app::AppExecutionPolicy 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 { +/// \see rosa::app::AwaitAll +/// \see rosa::app::AwaitAny +class AwaitBase : public AppExecutionPolicy { protected: /// Set of *slave* positions to check. const std::set Set; /// Type of decision-making function used in \c - /// rosa::deluxe::AwaitBase::shouldProcess(). + /// rosa::app::AwaitBase::shouldProcess(). using CheckerType = std::function::const_iterator, std::set::const_iterator, std::function)>; - // Decision-making function for \c rosa::deluxe::AwaitBase::shouldProcess(). + // Decision-making function for \c rosa::app::AwaitBase::shouldProcess(). 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. + /// Tells if \p this object can handle the application *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. + /// rosa::app::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 + bool canHandle(const AgentHandle H, const AppSystem &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. + /// rosa::app::AwaitBase::Checker evaluates to \c true with respect to \c + /// rosa::app::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 shouldProcess(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 + /// \return textual representation of \c rosa::app::AwaitBase::Set of \p /// this object std::string dumpS(void) const noexcept; }; -} // End namespace deluxe +} // End namespace app } // End namespace rosa -#endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_AWAITBASE_H +#endif // ROSA_LIB_APP_EXECUTIONPOLICIES_AWAITBASE_H diff --git a/lib/deluxe/executionpolicies/Decimation.cpp b/lib/app/executionpolicies/Decimation.cpp similarity index 73% rename from lib/deluxe/executionpolicies/Decimation.cpp rename to lib/app/executionpolicies/Decimation.cpp index b17946c..eb8923d 100644 --- a/lib/deluxe/executionpolicies/Decimation.cpp +++ b/lib/app/executionpolicies/Decimation.cpp @@ -1,47 +1,47 @@ -//===-- deluxe/executionpolicies/Decimation.cpp -----------------*- C++ -*-===// +//===-- app/executionpolicies/Decimation.cpp -----------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/Decimation.cpp +/// \file app/executionpolicies/Decimation.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// -/// \brief Implementation for deluxe/executionpolicies/Decimation.h. +/// \brief Implementation for app/executionpolicies/Decimation.h. /// //===----------------------------------------------------------------------===// #include "Decimation.h" #include namespace rosa { -namespace deluxe { +namespace app { Decimation::Decimation(const size_t D) : Rate(std::max(D, 1)), Cycle(0) {} -bool Decimation::canHandle(const AgentHandle, const DeluxeSystem &) const +bool Decimation::canHandle(const AgentHandle, const AppSystem &) const noexcept { return true; } bool Decimation::shouldProcess(const std::vector &) noexcept { return (Cycle++ % Rate) == 0; } std::string Decimation::dump(void) const noexcept { return "Decimation with rate " + std::to_string(Rate); } -} // End namespace deluxe +} // End namespace app } // End namespace rosa diff --git a/lib/deluxe/executionpolicies/Decimation.h b/lib/app/executionpolicies/Decimation.h similarity index 67% rename from lib/deluxe/executionpolicies/Decimation.h rename to lib/app/executionpolicies/Decimation.h index 14bb954..20b303c 100644 --- a/lib/deluxe/executionpolicies/Decimation.h +++ b/lib/app/executionpolicies/Decimation.h @@ -1,79 +1,80 @@ -//===-- deluxe/executionpolicies/Decimation.h -------------------*- C++ -*-===// +//===-- app/executionpolicies/Decimation.h -------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/executionpolicies/Decimation.h +/// \file app/executionpolicies/Decimation.h /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2019 +/// \date 2019-2020 /// /// \brief Declaration of the *execution policy* *decimation*. /// //===----------------------------------------------------------------------===// -#ifndef ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H -#define ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H +#ifndef ROSA_LIB_APP_EXECUTIONPOLICIES_DECIMATION_H +#define ROSA_LIB_APP_EXECUTIONPOLICIES_DECIMATION_H -#include "rosa/deluxe/DeluxeExecutionPolicy.h" +#include "rosa/app/AppExecutionPolicy.h" namespace rosa { -namespace deluxe { +namespace app { /// Implementation of the *execution policy* *decimation*. /// -/// \see \c rosa::deluxe::DeluxeExecutionPolicy::decimation() -class Decimation : public DeluxeExecutionPolicy { +/// \see \c rosa::app::AppExecutionPolicy::decimation() +class Decimation : public AppExecutionPolicy { /// 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. + /// Tells if \p this object can handle the application *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 + bool canHandle(const AgentHandle H, const AppSystem &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 + /// *Decimation* allows execution on each \c rosa::app::Decimation::Rate /// th triggering (i.e., calling of the function), which is counted - /// by \p this object in \c rosa::deluxe::Decimation::Cycle. + /// by \p this object in \c rosa::app::Decimation::Cycle. /// /// \param InputChanged *ignored* /// /// \return if to execute processing function bool shouldProcess(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 app } // End namespace rosa -#endif // ROSA_LIB_DELUXE_EXECUTIONPOLICIES_DECIMATION_H +#endif // ROSA_LIB_APP_EXECUTIONPOLICIES_DECIMATION_H diff --git a/lib/deluxe/DeluxeAtoms.cpp b/lib/app/namespace.cpp similarity index 68% rename from lib/deluxe/DeluxeAtoms.cpp rename to lib/app/namespace.cpp index ba45b08..af54112 100755 --- a/lib/deluxe/DeluxeAtoms.cpp +++ b/lib/app/namespace.cpp @@ -1,26 +1,26 @@ -//===-- deluxe/DeluxeAtoms.cpp ----------------------------------*- C++ -*-===// +//===-- app/namespace.cpp ------------------------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// -/// \file deluxe/DeluxeAtoms.cpp +/// \file app/namespace.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// -/// \date 2017 +/// \date 2017-2020 /// -/// \brief Implementation of rosa/deluxe/DeluxeAtoms.hpp. +/// \brief Implementation for rosa/app/namespace.h. /// /// \note Empty implementation, source file here to have a compile database -/// entry for rosa/deluxe/DeluxeAtoms.hpp. +/// entry for rosa/app/namespace.h. /// //===----------------------------------------------------------------------===// -#include "rosa/deluxe/DeluxeAtoms.hpp" +#include "rosa/app/namespace.h" diff --git a/lib/deluxe/CMakeLists.txt b/lib/deluxe/CMakeLists.txt deleted file mode 100644 index 56b7af1..0000000 --- a/lib/deluxe/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -set(LIB_INCLUDE_DIR ${ROSA_MAIN_INCLUDE_DIR}/rosa/deluxe) - -add_library(ROSADeluxe - ${LIB_INCLUDE_DIR}/namespace.h - namespace.cpp - ${LIB_INCLUDE_DIR}/DeluxeAtoms.hpp - DeluxeAtoms.cpp - ${LIB_INCLUDE_DIR}/DeluxeTuple.hpp - DeluxeTuple.cpp - executionpolicies/Decimation.h - executionpolicies/Decimation.cpp - executionpolicies/AwaitBase.h - executionpolicies/AwaitBase.cpp - executionpolicies/AwaitAll.h - executionpolicies/AwaitAll.cpp - executionpolicies/AwaitAny.h - executionpolicies/AwaitAny.cpp - ${LIB_INCLUDE_DIR}/DeluxeExecutionPolicy.h - DeluxeExecutionPolicy.cpp - ${LIB_INCLUDE_DIR}/DeluxeSensor.hpp - DeluxeSensor.cpp - ${LIB_INCLUDE_DIR}/DeluxeAgent.hpp - DeluxeAgent.cpp - ${LIB_INCLUDE_DIR}/DeluxeSystem.hpp - DeluxeSystem.cpp - DeluxeSystemImpl.hpp - DeluxeSystemImpl.cpp - ${LIB_INCLUDE_DIR}/DeluxeContext.hpp - DeluxeContext.cpp - ) - -ROSA_add_library_dependencies(ROSADeluxe ROSACore) diff --git a/lib/deluxe/DeluxeContext.cpp b/lib/deluxe/DeluxeContext.cpp deleted file mode 100755 index 4d73657..0000000 --- a/lib/deluxe/DeluxeContext.cpp +++ /dev/null @@ -1,224 +0,0 @@ -//===-- deluxe/DeluxeContext.cpp --------------------------------*- C++ -*-===// -// -// The RoSA Framework -// -// Distributed under the terms and conditions of the Boost Software License 1.0. -// See accompanying file LICENSE. -// -// If you did not receive a copy of the license file, see -// http://www.boost.org/LICENSE_1_0.txt. -// -//===----------------------------------------------------------------------===// -/// -/// \file deluxe/DeluxeContext.cpp -/// -/// \author David Juhasz (david.juhasz@tuwien.ac.at) -/// -/// \date 2017-2019 -/// -/// \brief Implementation for rosa/deluxe/DeluxeContext.hpp. -/// -//===----------------------------------------------------------------------===// - -#define ROSA_LIB_DELUXE_DELUXECONTEXT_CPP // For including helper macros. - -#include "rosa/deluxe/DeluxeContext.hpp" - -#include -#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."); -} - -DeluxeContext::~DeluxeContext(void) noexcept { - // \c rosa::deluxe::DeluxeContext::System is not used outside, just clean it. - for (auto U : DeluxeUnits) { - System->destroyAgent(U); - } - // \note \c System will be marked clean by SystemImpl::~SystemImpl. - LOG_TRACE("DeluxeContext for '" + System->name() + - "' prepared for destruction."); -} - -Optional -DeluxeContext::getExecutionPolicy(AgentHandle Unit) const noexcept { - if (System->isDeluxeSensor(Unit)) { - return {System->getDeluxeSensor(Unit)->executionPolicy()}; - } else if (System->isDeluxeAgent(Unit)) { - return {System->getDeluxeAgent(Unit)->executionPolicy()}; - } else { - return {}; - } -} - -DeluxeContext::ErrorCode DeluxeContext::setExecutionPolicy( - AgentHandle Unit, - std::unique_ptr &&ExecutionPolicy) noexcept { - // Generate trace log. - auto &Trace = LOG_TRACE_STREAM; - Trace << "Setting execution policy of " << System->unwrapAgent(Unit).FullName - << " to "; - if (ExecutionPolicy) { - Trace << "'" << ExecutionPolicy->dump() << "'\n"; - } else { - Trace << "[]\n"; - DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); - } - - if (System->isDeluxeSensor(Unit)) { - const bool Success = System->getDeluxeSensor(Unit)->setExecutionPolicy( - std::move(ExecutionPolicy)); - if (!Success) { - DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); - } else { - return ErrorCode::NoError; - } - } else if (System->isDeluxeAgent(Unit)) { - const bool Success = System->getDeluxeAgent(Unit)->setExecutionPolicy( - std::move(ExecutionPolicy)); - if (!Success) { - DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); - } else { - return ErrorCode::NoError; - } - } else { - DCRETERROR(ErrorCode::NotUnit); - } -} - -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"; - - // 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 || - (!emptyToken(A->masterOutputType(Pos)) && - A->masterOutputType(Pos) != S->MasterInputType)) { - 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"; - - // Make sure preconditions are met. - if (!(System->isDeluxeAgent(Master) && System->isDeluxeAgent(Slave))) { - DCRETERROR(ErrorCode::NotAgent); - } - auto M = System->getDeluxeAgent(Master); - auto S = System->getDeluxeAgent(Slave); - ASSERT(M && S); // Sanity check. - if (Pos >= M->NumberOfInputs) { - DCRETERROR(ErrorCode::WrongPosition); - } else if (M->inputType(Pos) != S->OutputType || - (!emptyToken(M->masterOutputType(Pos)) && - M->masterOutputType(Pos) != S->MasterInputType)) { - 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 { - LOG_INFO_STREAM << "Initializing simulation for " << System->name() - << ". Clearing all data sources.\n"; - // 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 { - DEBUG(for (auto H - : DeluxeUnits) { - std::stringstream Message; - Message << System->unwrapAgent(H).FullName << " is a Deluxe " - << " " << (System->isDeluxeSensor(H) ? "Sensor" : "Agent"); - if (System->isDeluxeSensor(H)) - Message << " with it's data source " - << (!System->getDeluxeSensor(H)->simulationDataSourceIsSet() - ? "not " - : "set"); - Message << '\n'; - LOG_TRACE_STREAM << Message.str(); - }); - - 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 diff --git a/lib/deluxe/DeluxeExecutionPolicy.cpp b/lib/deluxe/DeluxeExecutionPolicy.cpp deleted file mode 100644 index 10410ca..0000000 --- a/lib/deluxe/DeluxeExecutionPolicy.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- deluxe/DeluxeExecutionPolicy.cpp ------------------------*- C++ -*-===// -// -// The RoSA Framework -// -// Distributed under the terms and conditions of the Boost Software License 1.0. -// See accompanying file LICENSE. -// -// If you did not receive a copy of the license file, see -// http://www.boost.org/LICENSE_1_0.txt. -// -//===----------------------------------------------------------------------===// -/// -/// \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::decimation(const size_t D) { - return std::unique_ptr(new Decimation(D)); -} - -std::unique_ptr -DeluxeExecutionPolicy::awaitAll(const std::set &S) { - return std::unique_ptr(new AwaitAll(S)); -} - -std::unique_ptr -DeluxeExecutionPolicy::awaitAny(const std::set &S) { - return std::unique_ptr(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/DeluxeSystem.cpp b/lib/deluxe/DeluxeSystem.cpp deleted file mode 100755 index 2230cf4..0000000 --- a/lib/deluxe/DeluxeSystem.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//===-- deluxe/DeluxeSystem.cpp ---------------------------------*- C++ -*-===// -// -// The RoSA Framework -// -// Distributed under the terms and conditions of the Boost Software License 1.0. -// See accompanying file LICENSE. -// -// If you did not receive a copy of the license file, see -// http://www.boost.org/LICENSE_1_0.txt. -// -//===----------------------------------------------------------------------===// -/// -/// \file deluxe/DeluxeSystem.cpp -/// -/// \author David Juhasz (david.juhasz@tuwien.ac.at) -/// -/// \date 2017 -/// -/// \brief Implementation of rosa/deluxe/DeluxeSystem.hpp. -/// -//===----------------------------------------------------------------------===// - -#include "rosa/deluxe/DeluxeSystem.hpp" - -#include "DeluxeSystemImpl.hpp" - -namespace rosa { -namespace deluxe { - -std::unique_ptr -DeluxeSystem::createSystem(const std::string &Name) noexcept { - return std::unique_ptr(new DeluxeSystemImpl(Name)); -} - -Optional -DeluxeSystem::getDeluxeSensor(const AgentHandle &H) const noexcept { - if (isDeluxeSensor(H)) { - return {static_cast(unwrapAgent(H))}; - } else { - return {}; - } -} - -Optional DeluxeSystem::getDeluxeSensor(AgentHandle &H) const - noexcept { - if (isDeluxeSensor(H)) { - return {static_cast(unwrapAgent(H))}; - } else { - return {}; - } -} - -Optional -DeluxeSystem::getDeluxeAgent(const AgentHandle &H) const noexcept { - if (isDeluxeAgent(H)) { - return {static_cast(unwrapAgent(H))}; - } else { - return {}; - } -} - -Optional DeluxeSystem::getDeluxeAgent(AgentHandle &H) const - noexcept { - if (isDeluxeAgent(H)) { - return {static_cast(unwrapAgent(H))}; - } else { - return {}; - } -} - -} // End namespace deluxe -} // End namespace rosa