From 95869d98316610064cb4b284a28c397c4ffa2f9f Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 23 Jun 2022 06:16:10 -0700 Subject: [PATCH 1/9] add an Asynchronous time coordinator and clean the flags which were becoming a bit too overloaded to be clear --- .../application_api/MessageOperators.cpp | 6 +- src/helics/core/AsyncTimeCoordinator.cpp | 127 +++++++++++++++ src/helics/core/AsyncTimeCoordinator.hpp | 61 +++++++ src/helics/core/BasicHandleInfo.hpp | 15 +- src/helics/core/BrokerBase.cpp | 25 ++- src/helics/core/BrokerBase.hpp | 2 + src/helics/core/CMakeLists.txt | 2 + src/helics/core/CoreBroker.cpp | 10 +- src/helics/core/HandleManager.cpp | 6 +- src/helics/core/flagOperations.hpp | 151 +++++++++++------- 10 files changed, 326 insertions(+), 79 deletions(-) create mode 100644 src/helics/core/AsyncTimeCoordinator.cpp create mode 100644 src/helics/core/AsyncTimeCoordinator.hpp diff --git a/src/helics/application_api/MessageOperators.cpp b/src/helics/application_api/MessageOperators.cpp index ecd20e45b2..56f41a1fd8 100644 --- a/src/helics/application_api/MessageOperators.cpp +++ b/src/helics/application_api/MessageOperators.cpp @@ -151,17 +151,17 @@ std::unique_ptr FirewallOperator::process(std::unique_ptr mess break; case operations::set_flag1: if (res) { - setActionFlag(*message, extra_flag1); + setActionFlag(*message, 10); } break; case operations::set_flag2: if (res) { - setActionFlag(*message, extra_flag2); + setActionFlag(*message, 13); } break; case operations::set_flag3: if (res) { - setActionFlag(*message, extra_flag3); + setActionFlag(*message, 14); } break; case operations::none: diff --git a/src/helics/core/AsyncTimeCoordinator.cpp b/src/helics/core/AsyncTimeCoordinator.cpp new file mode 100644 index 0000000000..286e704bed --- /dev/null +++ b/src/helics/core/AsyncTimeCoordinator.cpp @@ -0,0 +1,127 @@ +/* +Copyright (c) 2017-2022, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ + +#include "../common/fmt_format.h" +#include "AsyncTimeCoordinator.hpp" +#include "flagOperations.hpp" +#include "helics_definitions.hpp" + +#include "json/json.h" +#include +#include +#include +#include +#include + +namespace helics { + +bool AsyncTimeCoordinator::updateTimeFactors() +{ + auto timeStream = generateMinTimeTotal(dependencies, true, mSourceId, NoIgnoredFederates, 0); + currentMinTime = timeStream.next; + currentTimeState = timeStream.mTimeState; + + return false; +} + +void AsyncTimeCoordinator::generateDebuggingTimeInfo(Json::Value& base) const +{ + base["type"] = "global"; + base["nextEvent"] = static_cast(nextEvent); + addTimeState(base, currentTimeState); + base["minTime"] = static_cast(currentMinTime); + BaseTimeCoordinator::generateDebuggingTimeInfo(base); +} + +std::string AsyncTimeCoordinator::printTimeStatus() const +{ + return fmt::format(R"raw({{"time_next":{}, "Te":{}}})raw", + static_cast(currentMinTime), + static_cast(nextEvent)); +} + +MessageProcessingResult AsyncTimeCoordinator::checkExecEntry(GlobalFederateId /*triggerFed*/) +{ + auto ret = MessageProcessingResult::CONTINUE_PROCESSING; + + executionMode = true; + ret = MessageProcessingResult::NEXT_STEP; + + currentMinTime = timeZero; + currentTimeState = TimeState::time_granted; + nextEvent = timeZero; + + ActionMessage execgrant(CMD_EXEC_GRANT); + execgrant.source_id = mSourceId; + transmitTimingMessagesDownstream(execgrant); + transmitTimingMessagesUpstream(execgrant); + return ret; +} + +void AsyncTimeCoordinator::transmitTimingMessagesUpstream(ActionMessage& msg) const +{ + if (!sendMessageFunction) { + return; + } + + for (const auto& dep : dependencies) { + if (dep.connection == ConnectionType::child) { + continue; + } + if (!dep.dependent) { + continue; + } + msg.dest_id = dep.fedID; + if (msg.action() == CMD_EXEC_REQUEST) { + msg.setExtraDestData(dep.sequenceCounter); + } + sendMessageFunction(msg); + } +} + +void AsyncTimeCoordinator::transmitTimingMessagesDownstream(ActionMessage& msg, + GlobalFederateId skipFed) const +{ + if (!sendMessageFunction) { + return; + } + if ((msg.action() == CMD_TIME_REQUEST || msg.action() == CMD_TIME_GRANT)) { + for (const auto& dep : dependencies) { + if (dep.connection != ConnectionType::child) { + continue; + } + if (!dep.dependent) { + continue; + } + if (dep.fedID == skipFed) { + continue; + } + if (dep.dependency) { + if (dep.next > msg.actionTime) { + continue; + } + } + msg.dest_id = dep.fedID; + sendMessageFunction(msg); + } + } else { + for (const auto& dep : dependencies) { + if (dep.dependent) { + if (dep.fedID == skipFed) { + continue; + } + if (msg.action() == CMD_EXEC_REQUEST) { + msg.setExtraDestData(dep.sequenceCounter); + } + msg.dest_id = dep.fedID; + sendMessageFunction(msg); + } + } + } +} + +} // namespace helics diff --git a/src/helics/core/AsyncTimeCoordinator.hpp b/src/helics/core/AsyncTimeCoordinator.hpp new file mode 100644 index 0000000000..75b5259a04 --- /dev/null +++ b/src/helics/core/AsyncTimeCoordinator.hpp @@ -0,0 +1,61 @@ +/* +Copyright (c) 2017-2022, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#pragma once + +#include "ActionMessage.hpp" +#include "BaseTimeCoordinator.hpp" +#include "CoreFederateInfo.hpp" +#include "TimeDependencies.hpp" + +#include "json/forwards.h" +#include +#include +#include +#include +#include + +namespace helics { + +/** class implementing no time coordination + */ +class AsyncTimeCoordinator: public BaseTimeCoordinator { + private: + // the variables for time coordination + Time currentMinTime{Time::minVal()}; + TimeState currentTimeState{TimeState::initialized}; + Time nextEvent{Time::maxVal()}; + + protected: + bool iterating{false}; //!< flag indicating that the min dependency is iterating + + public: + AsyncTimeCoordinator() = default; + + /** compute updates to time values + and send an update if needed + */ + virtual bool updateTimeFactors() override; + + private: + void transmitTimingMessagesUpstream(ActionMessage& msg) const; + void transmitTimingMessagesDownstream(ActionMessage& msg, + GlobalFederateId skipFed = GlobalFederateId{}) const; + + public: + /** check if entry to the executing state can be granted*/ + virtual MessageProcessingResult + checkExecEntry(GlobalFederateId triggerFed = GlobalFederateId{}) override; + + /** generate a string with the current time status*/ + virtual std::string printTimeStatus() const override; + /** generate debugging time information*/ + virtual void generateDebuggingTimeInfo(Json::Value& base) const override; + + /** get the current next time*/ + virtual Time getNextTime() const override { return currentMinTime; } +}; +} // namespace helics diff --git a/src/helics/core/BasicHandleInfo.hpp b/src/helics/core/BasicHandleInfo.hpp index e214deaa38..ba03859493 100644 --- a/src/helics/core/BasicHandleInfo.hpp +++ b/src/helics/core/BasicHandleInfo.hpp @@ -15,16 +15,7 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -/** define extra flag definitions*/ -enum handle_flag_definitions { - mapped_flag = extra_flag1, - /// indicator that an endpoint or message has a source filter - has_source_filter_flag = extra_flag2, - /// indicator that an endpoint or message has a destination filter - has_dest_filter_flag = extra_flag3, - /// indicator that the endpoint or filter has a destination filter that alters the message - has_non_cloning_dest_filter_flag = extra_flag4 -}; + /** class defining and capturing basic information about a handle*/ class BasicHandleInfo { @@ -49,8 +40,8 @@ class BasicHandleInfo { LocalFederateId local_fed_id{}; //!< the local federate id of the handle const InterfaceType handleType{InterfaceType::UNKNOWN}; //!< the type of the handle bool used{false}; //!< indicator that the handle is being used to link with another federate - uint16_t flags{ - 0}; //!< flags corresponding to the flags used in ActionMessages +some extra ones + /// flags corresponding to the flags used in ActionMessages +some extra ones + uint16_t flags{0}; const std::string key; //!< the name of the handle const std::string type; //!< the type of data used by the handle diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index 2e8fb94c87..d794084fa0 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -11,6 +11,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/logging.hpp" #include "ForwardingTimeCoordinator.hpp" #include "GlobalTimeCoordinator.hpp" +#include "AsyncTimeCoordinator.hpp" #include "LogManager.hpp" #include "ProfilerBuffer.hpp" #include "flagOperations.hpp" @@ -150,6 +151,24 @@ std::shared_ptr BrokerBase::generateBaseCLI() "--globaltime", globalTime, "specify that the broker should use a globalTime coordinator to coordinate a master clock time with all federates"); + hApp->add_flag( + "--async", + asyncTime, + "specify that the federation should not synchronize time (time management is done outside of helics or not relevent"); + hApp->add_option_function( + "--timing", + [this](const std::string& arg) { + if (arg == "async") { + asyncTime = true; + } else if (arg == "global") { + globalTime = true; + } else { + asyncTime = false; + globalTime = false; + } + }, + "specify the timing method to use in the broker") + ->check(CLI::IsMember({"async", "global", "distributed"})); hApp->add_flag("--observer", observer, "specify that the broker/core should be added as an observer only"); @@ -295,7 +314,11 @@ void BrokerBase::configureBase() uuid_like = true; } } - if (globalTime) { + if (asyncTime) { + timeCoord = std::make_unique(); + hasTimeDependency = true; + } + else if (globalTime) { timeCoord = std::make_unique(); hasTimeDependency = true; } else { diff --git a/src/helics/core/BrokerBase.hpp b/src/helics/core/BrokerBase.hpp index ca15d1dc78..8652a3aa0d 100644 --- a/src/helics/core/BrokerBase.hpp +++ b/src/helics/core/BrokerBase.hpp @@ -88,6 +88,8 @@ class BrokerBase { bool observer{false}; /// flag indicating that the broker should use a global time coordinator bool globalTime{false}; + /// flag indicating the use of async time keeping + bool asyncTime{false}; private: /// flag indicating that the main processing loop is running diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index 94e8096451..f052b5ba96 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -23,6 +23,7 @@ set(SRC_FILES BaseTimeCoordinator.cpp ForwardingTimeCoordinator.cpp GlobalTimeCoordinator.cpp + AsyncTimeCoordinator.cpp TimeDependencies.cpp HandleManager.cpp FilterInfo.cpp @@ -69,6 +70,7 @@ set(INCLUDE_FILES BaseTimeCoordinator.hpp ForwardingTimeCoordinator.hpp GlobalTimeCoordinator.hpp + AsyncTimeCoordinator.hpp loggingHelper.hpp GlobalFederateId.hpp basic_CoreTypes.hpp diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index f1d49ca915..6cc7281c61 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -253,7 +253,7 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) if (no_ping) { setActionFlag(brokerReply, slow_responding_flag); } - if (globalTime) { + if (globalTime || asyncTime) { setActionFlag(brokerReply, indicator_flag); } transmit(brk->route, brokerReply); @@ -430,7 +430,7 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) if (no_ping) { setActionFlag(brokerReply, slow_responding_flag); } - if (globalTime) { + if (globalTime || asyncTime) { setActionFlag(brokerReply, indicator_flag); } transmit(route, brokerReply); @@ -537,7 +537,7 @@ void CoreBroker::fedRegistration(ActionMessage&& command) if (checkActionFlag(command, child_flag)) { setActionFlag(fedReply, child_flag); } - if (globalTime) { + if (globalTime || asyncTime) { setActionFlag(fedReply, indicator_flag); if (!checkActionFlag(command, non_counting_flag)) { timeCoord->addDependency(global_fedid); @@ -1921,7 +1921,7 @@ void CoreBroker::addEndpoint(ActionMessage& m) if (!isRootc) { transmit(parent_route_id, m); - if (!hasTimeDependency && !globalTime) { + if (!hasTimeDependency && !globalTime && !asyncTime) { if (timeCoord->addDependency(higher_broker_id)) { hasTimeDependency = true; ActionMessage add(CMD_ADD_INTERDEPENDENCY, @@ -1990,7 +1990,7 @@ void CoreBroker::addTranslator(ActionMessage& m) transmit(parent_route_id, m); if (!hasFilters) { hasFilters = true; - if (!globalTime) { + if (!globalTime && !asyncTime) { if (timeCoord->addDependent(higher_broker_id)) { hasTimeDependency = true; ActionMessage add(CMD_ADD_DEPENDENCY, global_broker_id_local, higher_broker_id); diff --git a/src/helics/core/HandleManager.cpp b/src/helics/core/HandleManager.cpp index 2d4b930d6f..30bcb57e5f 100644 --- a/src/helics/core/HandleManager.cpp +++ b/src/helics/core/HandleManager.cpp @@ -177,10 +177,10 @@ int32_t HandleManager::getHandleOption(InterfaceHandle handle, int32_t option) c if (isValidIndex(index, handles)) { switch (option) { case HELICS_HANDLE_OPTION_ONLY_UPDATE_ON_CHANGE: - rvalue = checkActionFlag(handles[index], extra_flag1); + rvalue = checkActionFlag(handles[index], only_update_on_change_flag); break; case HELICS_HANDLE_OPTION_ONLY_TRANSMIT_ON_CHANGE: - rvalue = checkActionFlag(handles[index], extra_flag2); + rvalue = checkActionFlag(handles[index], only_transmit_on_change_flag); break; case HELICS_HANDLE_OPTION_CONNECTION_REQUIRED: rvalue = checkActionFlag(handles[index], required_flag); @@ -189,7 +189,7 @@ int32_t HandleManager::getHandleOption(InterfaceHandle handle, int32_t option) c rvalue = checkActionFlag(handles[index], optional_flag); break; case HELICS_HANDLE_OPTION_SINGLE_CONNECTION_ONLY: - rvalue = checkActionFlag(handles[index], extra_flag4); + rvalue = checkActionFlag(handles[index], single_connection_flag); break; default: break; diff --git a/src/helics/core/flagOperations.hpp b/src/helics/core/flagOperations.hpp index 0968a66761..cae921fa06 100644 --- a/src/helics/core/flagOperations.hpp +++ b/src/helics/core/flagOperations.hpp @@ -13,61 +13,102 @@ operations and helper functions for handling flags in helics namespace helics { /** flag definitions for the action Message Flag field*/ -enum OperationFlags : uint16_t { - iteration_requested_flag = 0, //!< indicator that an iteration has been requested - destination_target = 1, //!< indicator that the target is a destination target - required_flag = 2, //!< flag indicating that an action or match is required - core_flag = 3, //!< flag indicating that message comes from a core vs a broker - error_flag = 4, //!< flag indicating an error condition associated with the command - indicator_flag = 5, //!< flag used for setting values - use_json_serialization_flag = 6, //!< flag to indicate it should use the json packetization - extra_flag1 = 7, //!< extra flag - optional_flag = 8, //!< flag indicating that a connection is optional and may not be matched - clone_flag = - 9, //!< flag indicating the filter is a clone filter or the data needs to be cloned - extra_flag2 = 10, //!< extra flag - destination_processing_flag = - 11, //!< flag indicating the message is for destination processing - disconnected_flag = 12, //!< flag indicating that a broker/federate is disconnected - extra_flag3 = 13, //!< extra flag - extra_flag4 = 14, //!< extra flag - empty_flag = 15, //!< flag indicating the message is empty -}; - -/// overload of extra_flag4 indicating a federate, core or broker is slow responding -constexpr uint16_t slow_responding_flag = extra_flag4; - -/// overload of extra_flag3 indicating an operation is canceled -constexpr uint16_t cancel_flag = extra_flag3; - -/// overload of optional_flag indicating that a federate is an observer only -constexpr uint16_t observer_flag = optional_flag; - -/// overload of extra_flag3 indicating the message is from a parent object -constexpr uint16_t parent_flag = extra_flag3; - -/// overload of extra_flag4 indicating a message is from a child object -constexpr uint16_t child_flag = extra_flag4; - -/// overload of nameless_interface_flag indicating that a federate should not count in any totals -constexpr uint16_t non_counting_flag = empty_flag; - -/// overload of extra_flag2 indicating an endpoint is targeted -constexpr uint16_t targeted_flag = extra_flag2; -/// overload of extra_flag1 indicating that the message requires processing for filters yet -constexpr uint16_t filter_processing_required_flag = extra_flag1; - -/// overload of extra_flag1 to indicate the request is from a non-granting federate -constexpr uint16_t non_granting_flag = extra_flag1; - -/// overload of extra_flag2 to indicate the request is from federate with delayed timing -constexpr uint16_t delayed_timing_flag = extra_flag2; - -/// overload of flag to indicate an interface is nameless -constexpr uint16_t nameless_interface_flag = empty_flag; - -/// overload of optional_flag to mark an interrupted event -constexpr uint16_t interrupted_flag = optional_flag; + enum GeneralFlags : uint16_t { + error_flag = 4, //!< flag indicating an error condition associated with the command + indicator_flag = 5, //!< flag used for setting values + }; + + /// @brief flags used in timing messages + enum TimingFlags : uint16_t { + iteration_requested_flag = 0, //!< indicator that an iteration has been requested + /// flag to indicate the request is from a non-granting federate + non_granting_flag = 7, + + /// flag to indicate the request is from federate with delayed timing + delayed_timing_flag = 10, + /// flag to mark an interrupted event + interrupted_flag = 8, + + /// overload of extra_flag3 indicating the message is from a parent object + parent_flag = 13, + + /// overload of extra_flag4 indicating a message is from a child object + child_flag = 14 + }; + + /// @brief flags used on handles + enum InterfaceFlags : uint16_t { + /// indicator that the target is a destination target + destination_target = 1, + /// flag indicating that an action or match is required + required_flag = 2, + /// flag indicating that the interface accepts only a single connection + single_connection_flag = 3, + /// flag indicating that the values should only be updated on change + only_update_on_change_flag = 6, + /// flag indicating that the target is mapped + mapped_flag = 7, + /// flag indicating that a connection is optional and may not be matched + optional_flag = 8, + /// flag indicating the filter is a clone filter or the data needs to be cloned + clone_flag = 9, + /// flag indicating an endpoint is targeted + targeted_flag = 10, + + /// indicator that an endpoint or message has a source filter + has_source_filter_flag = 11, + /// indicator that the interface should only transmit on change + only_transmit_on_change_flag = 12, + /// indicator that an endpoint or message has a destination filter + has_dest_filter_flag = 13, + /// indicator that the endpoint or filter has a destination filter that alters the message + has_non_cloning_dest_filter_flag = 14, + /// flag to indicate an interface is nameless + nameless_interface_flag = 15, + }; + + /// @brief flags used when connecting a federate/core/broker to a federation + enum ConnectionFlags : uint16_t { + /// flag indicating that message comes from a core vs a broker + core_flag = 3, + /// flag to indicate it should use the json packetization + use_json_serialization_flag = 6, + /// flag indicating that a broker/federate is disconnected + disconnected_flag = 12, + /// flag indicating that a federate is an observer only + observer_flag = 8, + /// flag indicating a federate, core or broker is slow responding + slow_responding_flag = 14, + /// flag indicating that a federate should not count in any totals + non_counting_flag = 15, + + }; + + /// @brief flags used for messages + enum MessageFlags : uint16_t { + /// flag indicating the message is for destination processing + destination_processing_flag = 11, + /// flag indicating that the message requires processing for filters yet + filter_processing_required_flag = 7, + /// flag indicating the message is empty + empty_flag = 15, + }; + + /// @brief general flags used for other operations + enum OperationFlags : uint16_t { + /// flag indicating an operation is canceled + cancel_flag = 13 + }; + + //extra_flag1 = 7, //!< extra flag + + //extra_flag2 = 10, //!< extra flag + + + //extra_flag3 = 13, //!< extra flag + //extra_flag4 = 14, //!< extra flag + + /** template function to set a flag in an object containing a flags field @tparam FlagContainer an object with a .flags field From dfbc713cb94ca2aab5bb1ed190db1c8c3d943075 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 24 Jun 2022 07:11:55 -0700 Subject: [PATCH 2/9] add some basic tests for async time coordinator --- src/helics/core/CommonCore.cpp | 35 ++++++----- src/helics/core/CoreBroker.cpp | 16 ++++- src/helics/core/FederateState.cpp | 43 ++++++++----- src/helics/core/FederateState.hpp | 8 ++- src/helics/core/TimeCoordinator.hpp | 1 + src/helics/core/flagOperations.hpp | 31 +++++---- tests/helics/system_tests/TimingTests.cpp | 77 +++++++++++++++++++++++ 7 files changed, 165 insertions(+), 46 deletions(-) diff --git a/src/helics/core/CommonCore.cpp b/src/helics/core/CommonCore.cpp index 325a1a7f1a..a12544a199 100644 --- a/src/helics/core/CommonCore.cpp +++ b/src/helics/core/CommonCore.cpp @@ -3048,8 +3048,11 @@ void CommonCore::processPriorityCommand(ActionMessage&& command) if (checkActionFlag(command, slow_responding_flag)) { timeoutMon->disableParentPing(); } - if (checkActionFlag(command, indicator_flag)) { + if (checkActionFlag(command, global_timing_flag)) { globalTime = true; + if (checkActionFlag(command, async_timing_flag)) { + asyncTime = true; + } } timeoutMon->reset(); if (delayInitCounter < 0 && minFederateCount == 0 && minChildCount == 0) { @@ -3843,20 +3846,22 @@ void CommonCore::connectFilterTiming() auto fid = filterFedID.load(); if (globalTime) { - ActionMessage ad(CMD_ADD_DEPENDENT); - setActionFlag(ad, parent_flag); - ad.dest_id = fid; - ad.source_id = gRootBrokerID; - filterFed->handleMessage(ad); - - ad.setAction(CMD_ADD_DEPENDENCY); - filterFed->handleMessage(ad); - clearActionFlag(ad, parent_flag); - setActionFlag(ad, child_flag); - ad.swapSourceDest(); - transmit(parent_route_id, ad); - ad.setAction(CMD_ADD_DEPENDENT); - transmit(parent_route_id, ad); + if (!asyncTime) { + ActionMessage ad(CMD_ADD_DEPENDENT); + setActionFlag(ad, parent_flag); + ad.dest_id = fid; + ad.source_id = gRootBrokerID; + filterFed->handleMessage(ad); + + ad.setAction(CMD_ADD_DEPENDENCY); + filterFed->handleMessage(ad); + clearActionFlag(ad, parent_flag); + setActionFlag(ad, child_flag); + ad.swapSourceDest(); + transmit(parent_route_id, ad); + ad.setAction(CMD_ADD_DEPENDENT); + transmit(parent_route_id, ad); + } } else { if (timeCoord->addDependent(higher_broker_id)) { ActionMessage add(CMD_ADD_INTERDEPENDENCY, global_broker_id_local, higher_broker_id); diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index 6cc7281c61..da5805f338 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -254,7 +254,11 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) setActionFlag(brokerReply, slow_responding_flag); } if (globalTime || asyncTime) { - setActionFlag(brokerReply, indicator_flag); + setActionFlag(brokerReply, global_timing_flag); + if (asyncTime) + { + setActionFlag(brokerReply, async_timing_flag); + } } transmit(brk->route, brokerReply); return; @@ -431,7 +435,10 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) setActionFlag(brokerReply, slow_responding_flag); } if (globalTime || asyncTime) { - setActionFlag(brokerReply, indicator_flag); + setActionFlag(brokerReply, global_timing_flag); + if (asyncTime) { + setActionFlag(brokerReply, async_timing_flag); + } } transmit(route, brokerReply); LOG_CONNECTIONS(global_broker_id_local, @@ -538,7 +545,10 @@ void CoreBroker::fedRegistration(ActionMessage&& command) setActionFlag(fedReply, child_flag); } if (globalTime || asyncTime) { - setActionFlag(fedReply, indicator_flag); + setActionFlag(fedReply, global_timing_flag); + if (asyncTime) { + setActionFlag(fedReply, async_timing_flag); + } if (!checkActionFlag(command, non_counting_flag)) { timeCoord->addDependency(global_fedid); timeCoord->addDependent(global_fedid); diff --git a/src/helics/core/FederateState.cpp b/src/helics/core/FederateState.cpp index c18ca4a32b..143c14e657 100644 --- a/src/helics/core/FederateState.cpp +++ b/src/helics/core/FederateState.cpp @@ -1261,7 +1261,8 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); } LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); - if (cmd.actionTime < time_granted) { + if (cmd.actionTime < time_granted && + timeMethod != TimeSynchronizationMethod::ASYNC) { LOG_WARNING( fmt::format("received message {} at time({}) earlier than granted time({})", prettyPrintString(cmd), @@ -1288,7 +1289,7 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); } LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); - if (cmd.actionTime < time_granted) { + if (cmd.actionTime < time_granted && timeMethod!=TimeSynchronizationMethod::ASYNC) { LOG_WARNING(fmt::format( "received message {} at time({}) earlier than granted time({})", prettyPrintString(cmd), @@ -1311,13 +1312,19 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) break; } for (auto& src : subI->input_sources) { + auto valueTime = cmd.actionTime; + if (timeMethod == TimeSynchronizationMethod::ASYNC) { + if (valueTime < time_granted) { + valueTime = time_granted; + } + } if ((cmd.source_id == src.fed_id) && (cmd.source_handle == src.handle)) { subI->addData(src, - cmd.actionTime, + valueTime, cmd.counter, std::make_shared(std::move(cmd.payload))); if (!subI->not_interruptible) { - timeCoord->updateValueTime(cmd.actionTime, !timeGranted_mode); + timeCoord->updateValueTime(valueTime, !timeGranted_mode); LOG_TRACE(timeCoord->printTimeStatus()); } LOG_DATA(fmt::format("receive PUBLICATION {} from {}", @@ -1397,7 +1404,7 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) cmd.name(), cmd.getString(typeStringLoc), cmd.getString(unitStringLoc))) { - if (!usingGlobalTime) { + if (timeMethod==TimeSynchronizationMethod::DISTRIBUTED) { addDependency(cmd.source_id); } } @@ -1405,7 +1412,7 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) auto* eptI = interfaceInformation.getEndpoint(cmd.dest_handle); if (eptI != nullptr) { eptI->addSource(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc)); - if (!usingGlobalTime) { + if (timeMethod == TimeSynchronizationMethod::DISTRIBUTED) { addDependency(cmd.source_id); } } @@ -1415,7 +1422,7 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) auto* pubI = interfaceInformation.getPublication(cmd.dest_handle); if (pubI != nullptr) { if (pubI->addSubscriber(cmd.getSource())) { - if (!usingGlobalTime) { + if (timeMethod == TimeSynchronizationMethod::DISTRIBUTED) { addDependent(cmd.source_id); } } @@ -1427,12 +1434,16 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) if (checkActionFlag(cmd, destination_target)) { eptI->addDestination(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc)); if (eptI->targetedEndpoint) { - addDependent(cmd.source_id); + if (timeMethod == TimeSynchronizationMethod::DISTRIBUTED) { + addDependent(cmd.source_id); + } } } else { eptI->addSource(cmd.getSource(), cmd.name(), cmd.getString(typeStringLoc)); if (eptI->targetedEndpoint) { - addDependency(cmd.source_id); + if (timeMethod == TimeSynchronizationMethod::DISTRIBUTED) { + addDependency(cmd.source_id); + } } } } @@ -1474,11 +1485,15 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) errorString = commandErrorString(cmd.messageID); return MessageProcessingResult::ERROR_RESULT; } - if (checkActionFlag(cmd, indicator_flag)) { - usingGlobalTime = true; - addDependent(gRootBrokerID); - addDependency(gRootBrokerID); - timeCoord->setAsParent(gRootBrokerID); + if (checkActionFlag(cmd, global_timing_flag)) { + if (checkActionFlag(cmd, async_timing_flag)) { + timeMethod = TimeSynchronizationMethod::ASYNC; + } else { + timeMethod = TimeSynchronizationMethod::GLOBAL; + addDependent(gRootBrokerID); + addDependency(gRootBrokerID); + timeCoord->setAsParent(gRootBrokerID); + } timeCoord->globalTime = true; } global_id = cmd.dest_id; diff --git a/src/helics/core/FederateState.hpp b/src/helics/core/FederateState.hpp index 527f956d91..4a2a1b0c49 100644 --- a/src/helics/core/FederateState.hpp +++ b/src/helics/core/FederateState.hpp @@ -39,6 +39,10 @@ class LogManager; constexpr Time startupTime = Time::minVal(); constexpr Time initialTime{-1000000.0}; + +/// @brief enumeration of possible time coordination methods +enum class TimeSynchronizationMethod : uint8_t { DISTRIBUTED = 0, GLOBAL = 1, ASYNC = 2 }; + /** class managing the information about a single federate*/ class FederateState { public: @@ -112,7 +116,9 @@ class FederateState { //!< requesting state waiting to grant bool terminate_on_error{false}; //!< indicator that if the federate encounters a configuration //!< error it should cause a co-simulation abort - bool usingGlobalTime{false}; // indicator that the federation is using global time + /// the time keeping method in use + TimeSynchronizationMethod timeMethod{ + TimeSynchronizationMethod::DISTRIBUTED}; /** counter for the number of times time or execution mode has been granted */ std::uint32_t mGrantCount{0}; // this is intended to allow wrapping /** message timer object for real time operations and timeouts */ diff --git a/src/helics/core/TimeCoordinator.hpp b/src/helics/core/TimeCoordinator.hpp index 8382bd4a8d..79fbc291c1 100644 --- a/src/helics/core/TimeCoordinator.hpp +++ b/src/helics/core/TimeCoordinator.hpp @@ -254,4 +254,5 @@ class TimeCoordinator: public BaseTimeCoordinator { virtual Time getNextTime() const override; }; + } // namespace helics diff --git a/src/helics/core/flagOperations.hpp b/src/helics/core/flagOperations.hpp index cae921fa06..e5420c7e58 100644 --- a/src/helics/core/flagOperations.hpp +++ b/src/helics/core/flagOperations.hpp @@ -24,15 +24,14 @@ namespace helics { /// flag to indicate the request is from a non-granting federate non_granting_flag = 7, - /// flag to indicate the request is from federate with delayed timing - delayed_timing_flag = 10, /// flag to mark an interrupted event interrupted_flag = 8, - - /// overload of extra_flag3 indicating the message is from a parent object + /// flag to indicate the request is from federate with delayed timing + delayed_timing_flag = 10, + /// flag indicating the message is from a parent object parent_flag = 13, - /// overload of extra_flag4 indicating a message is from a child object + /// flag indicating a message is from a child object child_flag = 14 }; @@ -64,32 +63,38 @@ namespace helics { /// indicator that the endpoint or filter has a destination filter that alters the message has_non_cloning_dest_filter_flag = 14, /// flag to indicate an interface is nameless - nameless_interface_flag = 15, + nameless_interface_flag = 15 }; /// @brief flags used when connecting a federate/core/broker to a federation enum ConnectionFlags : uint16_t { /// flag indicating that message comes from a core vs a broker - core_flag = 3, + core_flag = 3, + /// flag indicating to use global timing (overload of indicator flag) + global_timing_flag = 5, + /// flag to indicate it should use the json packetization - use_json_serialization_flag = 6, - /// flag indicating that a broker/federate is disconnected - disconnected_flag = 12, + use_json_serialization_flag = 6, + /// flag indicating use of asynchronous timing on a global level + async_timing_flag = 7, /// flag indicating that a federate is an observer only observer_flag = 8, + /// flag indicating that a broker/federate is disconnected + disconnected_flag = 12, + /// flag indicating a federate, core or broker is slow responding slow_responding_flag = 14, /// flag indicating that a federate should not count in any totals - non_counting_flag = 15, + non_counting_flag = 15 }; /// @brief flags used for messages enum MessageFlags : uint16_t { - /// flag indicating the message is for destination processing - destination_processing_flag = 11, /// flag indicating that the message requires processing for filters yet filter_processing_required_flag = 7, + /// flag indicating the message is for destination processing + destination_processing_flag = 11, /// flag indicating the message is empty empty_flag = 15, }; diff --git a/tests/helics/system_tests/TimingTests.cpp b/tests/helics/system_tests/TimingTests.cpp index 3cd4453a86..af7c1a9fa5 100644 --- a/tests/helics/system_tests/TimingTests.cpp +++ b/tests/helics/system_tests/TimingTests.cpp @@ -707,3 +707,80 @@ TEST_F(timing, dual_fast_sender_tests_ci_skip) // ci_skip } #endif + + +TEST_F(timing, async_timing) +{ + extraBrokerArgs = "--async"; + SetupTest("test", 2); + auto vFed1 = GetFederateAs(0); + auto vFed2 = GetFederateAs(1); + vFed1->setProperty(HELICS_PROPERTY_TIME_PERIOD, 0.5); + vFed2->setProperty(HELICS_PROPERTY_TIME_PERIOD, 0.5); + + auto& pub = vFed1->registerGlobalPublication("pub1"); + vFed2->registerSubscription("pub1"); + vFed1->enterExecutingModeAsync(); + vFed2->enterExecutingMode(); + vFed1->enterExecutingModeComplete(); + + auto res = vFed1->requestTime(1.0); + EXPECT_EQ(res, 1.0); + pub.publish(0.27); + res = vFed2->requestTime(0.5); + EXPECT_EQ(res, 0.5); + res = vFed2->requestTime(2.0); + EXPECT_GE(res, 1.0); // the result should show up at the next available time point + // vFed2 should be able to grant in advance of fed1 using the async timing + res = vFed2->requestTime(2.0); + EXPECT_GE(res, 2.0); + res = vFed1->requestTime(1.5); + EXPECT_EQ(res, 1.5); + pub.publish(0.44); + vFed1->query("root", "global_flush"); + vFed1->requestTime(2.0); + res = vFed2->requestTime(5.0); + EXPECT_LT(res, 4.0); + + vFed1->finalize(); + vFed2->finalize(); +} + + +TEST_F(timing, async_timing_message) +{ + extraBrokerArgs = "--async"; + SetupTest("test", 2); + auto mFed1 = GetFederateAs(0); + auto mFed2 = GetFederateAs(1); + mFed1->setProperty(HELICS_PROPERTY_TIME_PERIOD, 0.5); + mFed2->setProperty(HELICS_PROPERTY_TIME_PERIOD, 0.5); + + auto& pub = mFed1->registerGlobalTargetedEndpoint("pub1"); + auto& sub = mFed2->registerTargetedEndpoint("pubr"); + sub.addSourceEndpoint("pub1"); + mFed1->enterExecutingModeAsync(); + mFed2->enterExecutingMode(); + mFed1->enterExecutingModeComplete(); + + auto res = mFed1->requestTime(1.0); + EXPECT_EQ(res, 1.0); + pub.send("test message"); + res = mFed2->requestTime(0.5); + EXPECT_EQ(res, 0.5); + res = mFed2->requestTime(2.0); + EXPECT_GE(res, 1.0); // the result should show up at the next available time point + // vFed2 should be able to grant in advance of fed1 using the async timing + res = mFed2->requestTime(2.0); + EXPECT_GE(res, 2.0); + res = mFed1->requestTime(1.5); + EXPECT_EQ(res, 1.5); + pub.send("test 2"); + mFed1->query("root", "global_flush"); + mFed1->requestTime(2.0); + res = mFed2->requestTime(5.0); + EXPECT_LT(res, 4.0); + + mFed1->finalize(); + mFed2->finalize(); +} From fdc643ff46eaa13982620e9546bd2d1955b7ea63 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 24 Jun 2022 14:21:51 +0000 Subject: [PATCH 3/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/helics/core/AsyncTimeCoordinator.cpp | 7 +- src/helics/core/BasicHandleInfo.hpp | 4 +- src/helics/core/BrokerBase.cpp | 27 ++- src/helics/core/CoreBroker.cpp | 3 +- src/helics/core/FederateState.cpp | 5 +- src/helics/core/FederateState.hpp | 3 +- src/helics/core/flagOperations.hpp | 199 +++++++++++----------- tests/helics/system_tests/TimingTests.cpp | 4 +- 8 files changed, 122 insertions(+), 130 deletions(-) diff --git a/src/helics/core/AsyncTimeCoordinator.cpp b/src/helics/core/AsyncTimeCoordinator.cpp index 286e704bed..2f33d2352a 100644 --- a/src/helics/core/AsyncTimeCoordinator.cpp +++ b/src/helics/core/AsyncTimeCoordinator.cpp @@ -5,8 +5,9 @@ Energy, LLC. See the top-level NOTICE for additional details. All rights reserv SPDX-License-Identifier: BSD-3-Clause */ -#include "../common/fmt_format.h" #include "AsyncTimeCoordinator.hpp" + +#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" @@ -24,7 +25,7 @@ bool AsyncTimeCoordinator::updateTimeFactors() auto timeStream = generateMinTimeTotal(dependencies, true, mSourceId, NoIgnoredFederates, 0); currentMinTime = timeStream.next; currentTimeState = timeStream.mTimeState; - + return false; } @@ -84,7 +85,7 @@ void AsyncTimeCoordinator::transmitTimingMessagesUpstream(ActionMessage& msg) co } void AsyncTimeCoordinator::transmitTimingMessagesDownstream(ActionMessage& msg, - GlobalFederateId skipFed) const + GlobalFederateId skipFed) const { if (!sendMessageFunction) { return; diff --git a/src/helics/core/BasicHandleInfo.hpp b/src/helics/core/BasicHandleInfo.hpp index ba03859493..e03aa3fa24 100644 --- a/src/helics/core/BasicHandleInfo.hpp +++ b/src/helics/core/BasicHandleInfo.hpp @@ -15,8 +15,6 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { - - /** class defining and capturing basic information about a handle*/ class BasicHandleInfo { public: @@ -41,7 +39,7 @@ class BasicHandleInfo { const InterfaceType handleType{InterfaceType::UNKNOWN}; //!< the type of the handle bool used{false}; //!< indicator that the handle is being used to link with another federate /// flags corresponding to the flags used in ActionMessages +some extra ones - uint16_t flags{0}; + uint16_t flags{0}; const std::string key; //!< the name of the handle const std::string type; //!< the type of data used by the handle diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index d794084fa0..8dd2a97934 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -9,9 +9,9 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/fmt_format.h" #include "../common/logging.hpp" +#include "AsyncTimeCoordinator.hpp" #include "ForwardingTimeCoordinator.hpp" #include "GlobalTimeCoordinator.hpp" -#include "AsyncTimeCoordinator.hpp" #include "LogManager.hpp" #include "ProfilerBuffer.hpp" #include "flagOperations.hpp" @@ -154,18 +154,18 @@ std::shared_ptr BrokerBase::generateBaseCLI() hApp->add_flag( "--async", asyncTime, - "specify that the federation should not synchronize time (time management is done outside of helics or not relevent"); + "specify that the federation should not synchronize time (time management is done outside of helics or not relevant"); hApp->add_option_function( - "--timing", - [this](const std::string& arg) { - if (arg == "async") { - asyncTime = true; - } else if (arg == "global") { - globalTime = true; - } else { - asyncTime = false; - globalTime = false; - } + "--timing", + [this](const std::string& arg) { + if (arg == "async") { + asyncTime = true; + } else if (arg == "global") { + globalTime = true; + } else { + asyncTime = false; + globalTime = false; + } }, "specify the timing method to use in the broker") ->check(CLI::IsMember({"async", "global", "distributed"})); @@ -317,8 +317,7 @@ void BrokerBase::configureBase() if (asyncTime) { timeCoord = std::make_unique(); hasTimeDependency = true; - } - else if (globalTime) { + } else if (globalTime) { timeCoord = std::make_unique(); hasTimeDependency = true; } else { diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index da5805f338..41b5362a98 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -255,8 +255,7 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) } if (globalTime || asyncTime) { setActionFlag(brokerReply, global_timing_flag); - if (asyncTime) - { + if (asyncTime) { setActionFlag(brokerReply, async_timing_flag); } } diff --git a/src/helics/core/FederateState.cpp b/src/helics/core/FederateState.cpp index 143c14e657..e253980101 100644 --- a/src/helics/core/FederateState.cpp +++ b/src/helics/core/FederateState.cpp @@ -1289,7 +1289,8 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); } LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); - if (cmd.actionTime < time_granted && timeMethod!=TimeSynchronizationMethod::ASYNC) { + if (cmd.actionTime < time_granted && + timeMethod != TimeSynchronizationMethod::ASYNC) { LOG_WARNING(fmt::format( "received message {} at time({}) earlier than granted time({})", prettyPrintString(cmd), @@ -1404,7 +1405,7 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) cmd.name(), cmd.getString(typeStringLoc), cmd.getString(unitStringLoc))) { - if (timeMethod==TimeSynchronizationMethod::DISTRIBUTED) { + if (timeMethod == TimeSynchronizationMethod::DISTRIBUTED) { addDependency(cmd.source_id); } } diff --git a/src/helics/core/FederateState.hpp b/src/helics/core/FederateState.hpp index 4a2a1b0c49..8ba7d0e803 100644 --- a/src/helics/core/FederateState.hpp +++ b/src/helics/core/FederateState.hpp @@ -117,8 +117,7 @@ class FederateState { bool terminate_on_error{false}; //!< indicator that if the federate encounters a configuration //!< error it should cause a co-simulation abort /// the time keeping method in use - TimeSynchronizationMethod timeMethod{ - TimeSynchronizationMethod::DISTRIBUTED}; + TimeSynchronizationMethod timeMethod{TimeSynchronizationMethod::DISTRIBUTED}; /** counter for the number of times time or execution mode has been granted */ std::uint32_t mGrantCount{0}; // this is intended to allow wrapping /** message timer object for real time operations and timeouts */ diff --git a/src/helics/core/flagOperations.hpp b/src/helics/core/flagOperations.hpp index e5420c7e58..cac1dcc3e6 100644 --- a/src/helics/core/flagOperations.hpp +++ b/src/helics/core/flagOperations.hpp @@ -13,107 +13,104 @@ operations and helper functions for handling flags in helics namespace helics { /** flag definitions for the action Message Flag field*/ - enum GeneralFlags : uint16_t { - error_flag = 4, //!< flag indicating an error condition associated with the command - indicator_flag = 5, //!< flag used for setting values - }; - - /// @brief flags used in timing messages - enum TimingFlags : uint16_t { - iteration_requested_flag = 0, //!< indicator that an iteration has been requested - /// flag to indicate the request is from a non-granting federate - non_granting_flag = 7, - - /// flag to mark an interrupted event - interrupted_flag = 8, - /// flag to indicate the request is from federate with delayed timing - delayed_timing_flag = 10, - /// flag indicating the message is from a parent object - parent_flag = 13, - - /// flag indicating a message is from a child object - child_flag = 14 - }; - - /// @brief flags used on handles - enum InterfaceFlags : uint16_t { - /// indicator that the target is a destination target - destination_target = 1, - /// flag indicating that an action or match is required - required_flag = 2, - /// flag indicating that the interface accepts only a single connection - single_connection_flag = 3, - /// flag indicating that the values should only be updated on change - only_update_on_change_flag = 6, - /// flag indicating that the target is mapped - mapped_flag = 7, - /// flag indicating that a connection is optional and may not be matched - optional_flag = 8, - /// flag indicating the filter is a clone filter or the data needs to be cloned - clone_flag = 9, - /// flag indicating an endpoint is targeted - targeted_flag = 10, - - /// indicator that an endpoint or message has a source filter - has_source_filter_flag = 11, - /// indicator that the interface should only transmit on change - only_transmit_on_change_flag = 12, - /// indicator that an endpoint or message has a destination filter - has_dest_filter_flag = 13, - /// indicator that the endpoint or filter has a destination filter that alters the message - has_non_cloning_dest_filter_flag = 14, - /// flag to indicate an interface is nameless - nameless_interface_flag = 15 - }; - - /// @brief flags used when connecting a federate/core/broker to a federation - enum ConnectionFlags : uint16_t { - /// flag indicating that message comes from a core vs a broker - core_flag = 3, - /// flag indicating to use global timing (overload of indicator flag) - global_timing_flag = 5, - - /// flag to indicate it should use the json packetization - use_json_serialization_flag = 6, - /// flag indicating use of asynchronous timing on a global level - async_timing_flag = 7, - /// flag indicating that a federate is an observer only - observer_flag = 8, - /// flag indicating that a broker/federate is disconnected - disconnected_flag = 12, - - /// flag indicating a federate, core or broker is slow responding - slow_responding_flag = 14, - /// flag indicating that a federate should not count in any totals - non_counting_flag = 15 - - }; - - /// @brief flags used for messages - enum MessageFlags : uint16_t { - /// flag indicating that the message requires processing for filters yet - filter_processing_required_flag = 7, - /// flag indicating the message is for destination processing - destination_processing_flag = 11, - /// flag indicating the message is empty - empty_flag = 15, - }; - - /// @brief general flags used for other operations - enum OperationFlags : uint16_t { - /// flag indicating an operation is canceled - cancel_flag = 13 - }; - - //extra_flag1 = 7, //!< extra flag - - //extra_flag2 = 10, //!< extra flag - - - //extra_flag3 = 13, //!< extra flag - //extra_flag4 = 14, //!< extra flag - - +enum GeneralFlags : uint16_t { + error_flag = 4, //!< flag indicating an error condition associated with the command + indicator_flag = 5, //!< flag used for setting values +}; + +/// @brief flags used in timing messages +enum TimingFlags : uint16_t { + iteration_requested_flag = 0, //!< indicator that an iteration has been requested + /// flag to indicate the request is from a non-granting federate + non_granting_flag = 7, + + /// flag to mark an interrupted event + interrupted_flag = 8, + /// flag to indicate the request is from federate with delayed timing + delayed_timing_flag = 10, + /// flag indicating the message is from a parent object + parent_flag = 13, + + /// flag indicating a message is from a child object + child_flag = 14 +}; + +/// @brief flags used on handles +enum InterfaceFlags : uint16_t { + /// indicator that the target is a destination target + destination_target = 1, + /// flag indicating that an action or match is required + required_flag = 2, + /// flag indicating that the interface accepts only a single connection + single_connection_flag = 3, + /// flag indicating that the values should only be updated on change + only_update_on_change_flag = 6, + /// flag indicating that the target is mapped + mapped_flag = 7, + /// flag indicating that a connection is optional and may not be matched + optional_flag = 8, + /// flag indicating the filter is a clone filter or the data needs to be cloned + clone_flag = 9, + /// flag indicating an endpoint is targeted + targeted_flag = 10, + + /// indicator that an endpoint or message has a source filter + has_source_filter_flag = 11, + /// indicator that the interface should only transmit on change + only_transmit_on_change_flag = 12, + /// indicator that an endpoint or message has a destination filter + has_dest_filter_flag = 13, + /// indicator that the endpoint or filter has a destination filter that alters the message + has_non_cloning_dest_filter_flag = 14, + /// flag to indicate an interface is nameless + nameless_interface_flag = 15 +}; + +/// @brief flags used when connecting a federate/core/broker to a federation +enum ConnectionFlags : uint16_t { + /// flag indicating that message comes from a core vs a broker + core_flag = 3, + /// flag indicating to use global timing (overload of indicator flag) + global_timing_flag = 5, + + /// flag to indicate it should use the json packetization + use_json_serialization_flag = 6, + /// flag indicating use of asynchronous timing on a global level + async_timing_flag = 7, + /// flag indicating that a federate is an observer only + observer_flag = 8, + /// flag indicating that a broker/federate is disconnected + disconnected_flag = 12, + + /// flag indicating a federate, core or broker is slow responding + slow_responding_flag = 14, + /// flag indicating that a federate should not count in any totals + non_counting_flag = 15 + +}; + +/// @brief flags used for messages +enum MessageFlags : uint16_t { + /// flag indicating that the message requires processing for filters yet + filter_processing_required_flag = 7, + /// flag indicating the message is for destination processing + destination_processing_flag = 11, + /// flag indicating the message is empty + empty_flag = 15, +}; + +/// @brief general flags used for other operations +enum OperationFlags : uint16_t { + /// flag indicating an operation is canceled + cancel_flag = 13 +}; + +// extra_flag1 = 7, //!< extra flag + +// extra_flag2 = 10, //!< extra flag + +// extra_flag3 = 13, //!< extra flag +// extra_flag4 = 14, //!< extra flag /** template function to set a flag in an object containing a flags field @tparam FlagContainer an object with a .flags field diff --git a/tests/helics/system_tests/TimingTests.cpp b/tests/helics/system_tests/TimingTests.cpp index af7c1a9fa5..61658f14ae 100644 --- a/tests/helics/system_tests/TimingTests.cpp +++ b/tests/helics/system_tests/TimingTests.cpp @@ -708,7 +708,6 @@ TEST_F(timing, dual_fast_sender_tests_ci_skip) // ci_skip #endif - TEST_F(timing, async_timing) { extraBrokerArgs = "--async"; @@ -741,12 +740,11 @@ TEST_F(timing, async_timing) vFed1->requestTime(2.0); res = vFed2->requestTime(5.0); EXPECT_LT(res, 4.0); - + vFed1->finalize(); vFed2->finalize(); } - TEST_F(timing, async_timing_message) { extraBrokerArgs = "--async"; From f6d81c6c02b85dd6a1cb5ad2dabef7d01ccce896 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 24 Jun 2022 08:00:56 -0700 Subject: [PATCH 4/9] fix clang tidy issues --- .../application_api/MessageOperators.cpp | 4 +-- src/helics/helics_enums.h | 28 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/helics/application_api/MessageOperators.cpp b/src/helics/application_api/MessageOperators.cpp index 56f41a1fd8..7c27d9211e 100644 --- a/src/helics/application_api/MessageOperators.cpp +++ b/src/helics/application_api/MessageOperators.cpp @@ -77,9 +77,9 @@ MessageConditionalOperator::MessageConditionalOperator( } void MessageConditionalOperator::setConditionFunction( - std::function userConditionalFunction) + std::function userConditionFunction) { - evalFunction = std::move(userConditionalFunction); + evalFunction = std::move(userConditionFunction); } std::unique_ptr MessageConditionalOperator::process(std::unique_ptr message) diff --git a/src/helics/helics_enums.h b/src/helics/helics_enums.h index a624920a19..fec6d5a27c 100644 --- a/src/helics/helics_enums.h +++ b/src/helics/helics_enums.h @@ -18,8 +18,9 @@ SPDX-License-Identifier: BSD-3-Clause extern "C" { #endif + /** pick a core type depending on compile configuration usually either ZMQ if available or TCP */ -typedef enum { +typedef enum { /* NOLINT */ /** a default core type that will default to something available*/ HELICS_CORE_TYPE_DEFAULT = 0, /** use the Zero MQ networking protocol */ @@ -60,7 +61,7 @@ typedef enum { } HelicsCoreTypes; /** enumeration of allowable data types for publications and inputs*/ -typedef enum { +typedef enum { /* NOLINT */ HELICS_DATA_TYPE_UNKNOWN = -1, /** a sequence of characters*/ HELICS_DATA_TYPE_STRING = 0, @@ -94,7 +95,7 @@ typedef enum { #define HELICS_DATA_TYPE_CHAR HELICS_DATA_TYPE_STRING /** enumeration of possible federate flags*/ -typedef enum { +typedef enum { /* NOLINT */ /** flag indicating that a federate is observe only*/ HELICS_FLAG_OBSERVER = 0, /** flag indicating that a federate can only return requested times*/ @@ -141,7 +142,7 @@ typedef enum { } HelicsFederateFlags; /** enumeration of additional core flags*/ -typedef enum { +typedef enum { /* NOLINT */ /** used to delay a core from entering initialization mode even if it would otherwise be ready*/ HELICS_FLAG_DELAY_INIT_ENTRY = 45, /** used to clear the HELICS_DELAY_INIT_ENTRY flag in cores*/ @@ -151,7 +152,7 @@ typedef enum { } HelicsCoreFlags; /** enumeration of general flags that can be used in federates/cores/brokers */ -typedef enum { +typedef enum { /* NOLINT */ /** flag specifying that a federate, core, or broker may be slow to respond to pings If the federate goes offline there is no good way to detect it so use with caution */ @@ -174,7 +175,7 @@ typedef enum { /** log level definitions */ -typedef enum { +typedef enum { /* NOLINT */ /** log level for dumping log messages*/ HELICS_LOG_LEVEL_DUMPLOG = -10, /** don't print anything except a few catastrophic errors*/ @@ -204,7 +205,7 @@ typedef enum { /** enumeration of return values from the C interface functions */ -typedef enum { +typedef enum { /* NOLINT */ /** global fatal error for federation */ HELICS_ERROR_FATAL = -404, /** an unknown non-helics error was produced */ @@ -246,7 +247,7 @@ typedef enum { const int HELICS_INVALID_OPTION_INDEX = -101; /** enumeration of properties that apply to federates and sometimes cores*/ -typedef enum { +typedef enum { /* NOLINT */ /** the property controlling the minimum time delta for a federate*/ HELICS_PROPERTY_TIME_DELTA = 137, /** the property controlling the period for a federate*/ @@ -287,7 +288,7 @@ typedef enum { const int HELICS_INVALID_PROPERTY_VALUE = -972; /** enumeration of the multi_input operations*/ -typedef enum { +typedef enum { /* NOLINT */ /** time and priority order the inputs from the core library*/ HELICS_MULTI_INPUT_NO_OP = 0, /** vectorize the inputs either double vector or string vector*/ @@ -310,7 +311,7 @@ typedef enum { } HelicsMultiInputModes; /** enumeration of options that apply to handles*/ -typedef enum { +typedef enum { /* NOLINT */ /** specify that a connection is required for an interface and will generate an error if not available*/ HELICS_HANDLE_OPTION_CONNECTION_REQUIRED = 397, @@ -345,7 +346,7 @@ typedef enum { } HelicsHandleOptions; /** enumeration of the predefined filter types*/ -typedef enum { +typedef enum { /* NOLINT */ /** a custom filter type that executes a user defined callback*/ HELICS_FILTER_TYPE_CUSTOM = 0, /** a filter type that executes a fixed delay on a message*/ @@ -365,7 +366,7 @@ typedef enum { } HelicsFilterTypes; /** enumeration of the predefined translator types*/ -typedef enum { +typedef enum { /* NOLINT */ /** a custom filter type that executes a user defined callback*/ HELICS_TRANSLATOR_TYPE_CUSTOM = 0, /** a translator type that converts to and from JSON*/ @@ -380,7 +381,7 @@ fast is the default, meaning the query travels along priority channels and takes existing messages; ordered means it follows normal priority patterns and will be ordered along with existing messages */ -typedef enum { +typedef enum { /* NOLINT */ /** sequencing mode to operate on priority channels*/ HELICS_SEQUENCING_MODE_FAST = 0, /** sequencing mode to operate on the normal channels*/ @@ -392,6 +393,7 @@ typedef enum { #define HELICS_BIG_NUMBER 9223372036.854774 const double cHelicsBigNumber = HELICS_BIG_NUMBER; + #ifdef __cplusplus } /* end of extern "C" { */ #endif From ea3e068e9ff753f0964e9f1bf0ec57e62ef858ff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 24 Jun 2022 15:16:30 +0000 Subject: [PATCH 5/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/helics/helics_enums.h | 620 +++++++++++++++++++------------------- 1 file changed, 314 insertions(+), 306 deletions(-) diff --git a/src/helics/helics_enums.h b/src/helics/helics_enums.h index fec6d5a27c..e0703f6ecb 100644 --- a/src/helics/helics_enums.h +++ b/src/helics/helics_enums.h @@ -18,77 +18,78 @@ SPDX-License-Identifier: BSD-3-Clause extern "C" { #endif - /** pick a core type depending on compile configuration usually either ZMQ if available or TCP */ typedef enum { /* NOLINT */ - /** a default core type that will default to something available*/ - HELICS_CORE_TYPE_DEFAULT = 0, - /** use the Zero MQ networking protocol */ - HELICS_CORE_TYPE_ZMQ = 1, - /** use MPI for operation on a parallel cluster */ - HELICS_CORE_TYPE_MPI = 2, - /** use the Test core if all federates are in the same process */ - HELICS_CORE_TYPE_TEST = 3, - /** interprocess uses memory mapped files to transfer data (for use when all federates are - on the same machine */ - HELICS_CORE_TYPE_INTERPROCESS = 4, - /** interprocess uses memory mapped files to transfer data (for use when all federates are - on the same machine ipc is the same as /ref HELICS_CORE_TYPE_interprocess*/ - HELICS_CORE_TYPE_IPC = 5, - /** use a generic TCP protocol message stream to send messages */ - HELICS_CORE_TYPE_TCP = 6, - /** use UDP packets to send the data */ - HELICS_CORE_TYPE_UDP = 7, - /** single socket version of ZMQ core usually for high fed count on the same system*/ - HELICS_CORE_TYPE_ZMQ_SS = 10, - /** for using the nanomsg communications */ - HELICS_CORE_TYPE_NNG = 9, - /** a single socket version of the TCP core for more easily handling firewalls*/ - HELICS_CORE_TYPE_TCP_SS = 11, - /** a core type using http for communication*/ - HELICS_CORE_TYPE_HTTP = 12, - /** a core using websockets for communication*/ - HELICS_CORE_TYPE_WEBSOCKET = 14, - /** an in process core type for handling communications in shared - memory it is pretty similar to the test core but stripped from - the "test" components*/ - HELICS_CORE_TYPE_INPROC = 18, - /** an explicit core type that is recognized but explicitly doesn't - exist, for testing and a few other assorted reasons*/ - HELICS_CORE_TYPE_NULL = 66, - /** an explicit core type exists but does nothing but return empty values or sink calls*/ - HELICS_CORE_TYPE_EMPTY = 77 + /** a default core type that will default to something available*/ + HELICS_CORE_TYPE_DEFAULT = 0, + /** use the Zero MQ networking protocol */ + HELICS_CORE_TYPE_ZMQ = 1, + /** use MPI for operation on a parallel cluster */ + HELICS_CORE_TYPE_MPI = 2, + /** use the Test core if all federates are in the same process */ + HELICS_CORE_TYPE_TEST = 3, + /** interprocess uses memory mapped files to transfer data (for use when all + federates are on the same machine */ + HELICS_CORE_TYPE_INTERPROCESS = 4, + /** interprocess uses memory mapped files to transfer data (for use when all + federates are on the same machine ipc is the same as /ref + HELICS_CORE_TYPE_interprocess*/ + HELICS_CORE_TYPE_IPC = 5, + /** use a generic TCP protocol message stream to send messages */ + HELICS_CORE_TYPE_TCP = 6, + /** use UDP packets to send the data */ + HELICS_CORE_TYPE_UDP = 7, + /** single socket version of ZMQ core usually for high fed count on the same system*/ + HELICS_CORE_TYPE_ZMQ_SS = 10, + /** for using the nanomsg communications */ + HELICS_CORE_TYPE_NNG = 9, + /** a single socket version of the TCP core for more easily handling firewalls*/ + HELICS_CORE_TYPE_TCP_SS = 11, + /** a core type using http for communication*/ + HELICS_CORE_TYPE_HTTP = 12, + /** a core using websockets for communication*/ + HELICS_CORE_TYPE_WEBSOCKET = 14, + /** an in process core type for handling communications in shared + memory it is pretty similar to the test core but + stripped from the "test" components*/ + HELICS_CORE_TYPE_INPROC = 18, + /** an explicit core type that is recognized but explicitly doesn't + exist, for testing and a few other assorted reasons*/ + HELICS_CORE_TYPE_NULL = 66, + /** an explicit core type exists but does nothing but return empty values or sink + calls*/ + HELICS_CORE_TYPE_EMPTY = 77 } HelicsCoreTypes; /** enumeration of allowable data types for publications and inputs*/ typedef enum { /* NOLINT */ - HELICS_DATA_TYPE_UNKNOWN = -1, - /** a sequence of characters*/ - HELICS_DATA_TYPE_STRING = 0, - /** a double precision floating point number*/ - HELICS_DATA_TYPE_DOUBLE = 1, - /** a 64 bit integer*/ - HELICS_DATA_TYPE_INT = 2, - /** a pair of doubles representing a complex number*/ - HELICS_DATA_TYPE_COMPLEX = 3, - /** an array of doubles*/ - HELICS_DATA_TYPE_VECTOR = 4, - /** a complex vector object*/ - HELICS_DATA_TYPE_COMPLEX_VECTOR = 5, - /** a named point consisting of a string and a double*/ - HELICS_DATA_TYPE_NAMED_POINT = 6, - /** a boolean data type*/ - HELICS_DATA_TYPE_BOOLEAN = 7, - /** time data type*/ - HELICS_DATA_TYPE_TIME = 8, - /** raw data type*/ - HELICS_DATA_TYPE_RAW = 25, - /** type converts to a valid json string*/ - HELICS_DATA_TYPE_JSON = 30, - /** the data type can change*/ - HELICS_DATA_TYPE_MULTI = 33, - /** open type that can be anything*/ - HELICS_DATA_TYPE_ANY = 25262 + HELICS_DATA_TYPE_UNKNOWN = -1, + /** a sequence of characters*/ + HELICS_DATA_TYPE_STRING = 0, + /** a double precision floating point number*/ + HELICS_DATA_TYPE_DOUBLE = 1, + /** a 64 bit integer*/ + HELICS_DATA_TYPE_INT = 2, + /** a pair of doubles representing a complex number*/ + HELICS_DATA_TYPE_COMPLEX = 3, + /** an array of doubles*/ + HELICS_DATA_TYPE_VECTOR = 4, + /** a complex vector object*/ + HELICS_DATA_TYPE_COMPLEX_VECTOR = 5, + /** a named point consisting of a string and a double*/ + HELICS_DATA_TYPE_NAMED_POINT = 6, + /** a boolean data type*/ + HELICS_DATA_TYPE_BOOLEAN = 7, + /** time data type*/ + HELICS_DATA_TYPE_TIME = 8, + /** raw data type*/ + HELICS_DATA_TYPE_RAW = 25, + /** type converts to a valid json string*/ + HELICS_DATA_TYPE_JSON = 30, + /** the data type can change*/ + HELICS_DATA_TYPE_MULTI = 33, + /** open type that can be anything*/ + HELICS_DATA_TYPE_ANY = 25262 } HelicsDataTypes; /** single character data type this is intentionally the same as string*/ @@ -96,192 +97,196 @@ typedef enum { /* NOLINT */ /** enumeration of possible federate flags*/ typedef enum { /* NOLINT */ - /** flag indicating that a federate is observe only*/ - HELICS_FLAG_OBSERVER = 0, - /** flag indicating that a federate can only return requested times*/ - HELICS_FLAG_UNINTERRUPTIBLE = 1, - /** flag indicating that a federate can be interrupted*/ - HELICS_FLAG_INTERRUPTIBLE = 2, - /** flag indicating that a federate/interface is a signal generator only*/ - HELICS_FLAG_SOURCE_ONLY = 4, - /** flag indicating a federate/interface should only transmit values if they have changed(binary - equivalence)*/ - HELICS_FLAG_ONLY_TRANSMIT_ON_CHANGE = 6, - /** flag indicating a federate/interface should only trigger an update if a value has changed - * (binary equivalence)*/ - HELICS_FLAG_ONLY_UPDATE_ON_CHANGE = 8, - /** flag indicating a federate should only grant time if all other federates have already passed - * the requested time*/ - HELICS_FLAG_WAIT_FOR_CURRENT_TIME_UPDATE = 10, - /** flag indicating a federate should operate on a restrictive time policy, which disallows some - 2nd order time evaluation and can be useful for certain types of dependency cycles - and update patterns, but generally shouldn't be used as it can lead to some very slow update - conditions*/ - HELICS_FLAG_RESTRICTIVE_TIME_POLICY = 11, - /** flag indicating that a federate has rollback capability*/ - HELICS_FLAG_ROLLBACK = 12, - /** flag indicating that a federate performs forward computation and does internal rollback*/ - HELICS_FLAG_FORWARD_COMPUTE = 14, - /** flag indicating that a federate needs to run in real time*/ - HELICS_FLAG_REALTIME = 16, - /** flag indicating that the federate will only interact on a single thread*/ - HELICS_FLAG_SINGLE_THREAD_FEDERATE = 27, - /** used to not display warnings on mismatched requested times*/ - HELICS_FLAG_IGNORE_TIME_MISMATCH_WARNINGS = 67, - /** specify that checking on configuration files should be strict and throw and error on any - invalid values */ - HELICS_FLAG_STRICT_CONFIG_CHECKING = 75, - /** specify that the federate should use json serialization for all data types*/ - HELICS_FLAG_USE_JSON_SERIALIZATION = 79, - /** specify that the federate is event triggered-meaning (all/most) events are triggered by - incoming events*/ - HELICS_FLAG_EVENT_TRIGGERED = 81, - /** specify that that federate should capture the profiling data to the local federate logging - system*/ - HELICS_FLAG_LOCAL_PROFILING_CAPTURE = 96 + /** flag indicating that a federate is observe only*/ + HELICS_FLAG_OBSERVER = 0, + /** flag indicating that a federate can only return requested times*/ + HELICS_FLAG_UNINTERRUPTIBLE = 1, + /** flag indicating that a federate can be interrupted*/ + HELICS_FLAG_INTERRUPTIBLE = 2, + /** flag indicating that a federate/interface is a signal generator only*/ + HELICS_FLAG_SOURCE_ONLY = 4, + /** flag indicating a federate/interface should only transmit values if they have + changed(binary equivalence)*/ + HELICS_FLAG_ONLY_TRANSMIT_ON_CHANGE = 6, + /** flag indicating a federate/interface should only trigger an update if a value has + * changed (binary equivalence)*/ + HELICS_FLAG_ONLY_UPDATE_ON_CHANGE = 8, + /** flag indicating a federate should only grant time if all other federates have + * already passed the requested time*/ + HELICS_FLAG_WAIT_FOR_CURRENT_TIME_UPDATE = 10, + /** flag indicating a federate should operate on a restrictive time policy, which + disallows some 2nd order time evaluation and can be useful for certain types of + dependency cycles and update patterns, but generally shouldn't be used as it can + lead to some very slow update conditions*/ + HELICS_FLAG_RESTRICTIVE_TIME_POLICY = 11, + /** flag indicating that a federate has rollback capability*/ + HELICS_FLAG_ROLLBACK = 12, + /** flag indicating that a federate performs forward computation and does internal + rollback*/ + HELICS_FLAG_FORWARD_COMPUTE = 14, + /** flag indicating that a federate needs to run in real time*/ + HELICS_FLAG_REALTIME = 16, + /** flag indicating that the federate will only interact on a single thread*/ + HELICS_FLAG_SINGLE_THREAD_FEDERATE = 27, + /** used to not display warnings on mismatched requested times*/ + HELICS_FLAG_IGNORE_TIME_MISMATCH_WARNINGS = 67, + /** specify that checking on configuration files should be strict and throw and error + on any invalid values */ + HELICS_FLAG_STRICT_CONFIG_CHECKING = 75, + /** specify that the federate should use json serialization for all data types*/ + HELICS_FLAG_USE_JSON_SERIALIZATION = 79, + /** specify that the federate is event triggered-meaning (all/most) events are + triggered by incoming events*/ + HELICS_FLAG_EVENT_TRIGGERED = 81, + /** specify that that federate should capture the profiling data to the local + federate logging system*/ + HELICS_FLAG_LOCAL_PROFILING_CAPTURE = 96 } HelicsFederateFlags; /** enumeration of additional core flags*/ typedef enum { /* NOLINT */ - /** used to delay a core from entering initialization mode even if it would otherwise be ready*/ - HELICS_FLAG_DELAY_INIT_ENTRY = 45, - /** used to clear the HELICS_DELAY_INIT_ENTRY flag in cores*/ - HELICS_FLAG_ENABLE_INIT_ENTRY = 47, - /** ignored flag used to test some code paths*/ - HELICS_FLAG_IGNORE = 999 + /** used to delay a core from entering initialization mode even if it would otherwise + be ready*/ + HELICS_FLAG_DELAY_INIT_ENTRY = 45, + /** used to clear the HELICS_DELAY_INIT_ENTRY flag in cores*/ + HELICS_FLAG_ENABLE_INIT_ENTRY = 47, + /** ignored flag used to test some code paths*/ + HELICS_FLAG_IGNORE = 999 } HelicsCoreFlags; /** enumeration of general flags that can be used in federates/cores/brokers */ typedef enum { /* NOLINT */ - /** flag specifying that a federate, core, or broker may be slow to respond to pings - If the federate goes offline there is no good way to detect it so use with caution - */ - HELICS_FLAG_SLOW_RESPONDING = 29, - /** flag specifying the federate/core/broker is operating in a user debug mode so deadlock - timers and timeout are disabled this flag is a combination of slow_responding and disabling of - some timeouts*/ - HELICS_FLAG_DEBUGGING = 31, - /** specify that a federate error should terminate the federation*/ - HELICS_FLAG_TERMINATE_ON_ERROR = 72, - /** specify that the log files should be flushed on every log message*/ - HELICS_FLAG_FORCE_LOGGING_FLUSH = 88, - /** specify that a full log should be dumped into a file*/ - HELICS_FLAG_DUMPLOG = 89, - /** specify that helics should capture profiling data*/ - HELICS_FLAG_PROFILING = 93, - /** flag trigger for generating a profiling marker*/ - HELICS_FLAG_PROFILING_MARKER = 95 + /** flag specifying that a federate, core, or broker may be slow to respond to pings + If the federate goes offline there is no good way to detect it so use with + caution + */ + HELICS_FLAG_SLOW_RESPONDING = 29, + /** flag specifying the federate/core/broker is operating in a user debug mode so + deadlock timers and timeout are disabled this flag is a combination of + slow_responding and disabling of some timeouts*/ + HELICS_FLAG_DEBUGGING = 31, + /** specify that a federate error should terminate the federation*/ + HELICS_FLAG_TERMINATE_ON_ERROR = 72, + /** specify that the log files should be flushed on every log message*/ + HELICS_FLAG_FORCE_LOGGING_FLUSH = 88, + /** specify that a full log should be dumped into a file*/ + HELICS_FLAG_DUMPLOG = 89, + /** specify that helics should capture profiling data*/ + HELICS_FLAG_PROFILING = 93, + /** flag trigger for generating a profiling marker*/ + HELICS_FLAG_PROFILING_MARKER = 95 } HelicsFlags; /** log level definitions */ typedef enum { /* NOLINT */ - /** log level for dumping log messages*/ - HELICS_LOG_LEVEL_DUMPLOG = -10, - /** don't print anything except a few catastrophic errors*/ - HELICS_LOG_LEVEL_NO_PRINT = -4, - /** only print error level indicators*/ - HELICS_LOG_LEVEL_ERROR = 0, - /** profiling log level*/ - HELICS_LOG_LEVEL_PROFILING = 2, - /** only print warnings and errors*/ - HELICS_LOG_LEVEL_WARNING = 3, - /** warning errors and summary level information*/ - HELICS_LOG_LEVEL_SUMMARY = 6, - /** summary+ notices about federate and broker connections +messages about network - connections*/ - HELICS_LOG_LEVEL_CONNECTIONS = 9, - /** connections+ interface definitions*/ - HELICS_LOG_LEVEL_INTERFACES = 12, - /** interfaces + timing message*/ - HELICS_LOG_LEVEL_TIMING = 15, - /** timing+ data transfer notices*/ - HELICS_LOG_LEVEL_DATA = 18, - /** data+ additional debug message*/ - HELICS_LOG_LEVEL_DEBUG = 21, - /** all internal messages*/ - HELICS_LOG_LEVEL_TRACE = 24 + /** log level for dumping log messages*/ + HELICS_LOG_LEVEL_DUMPLOG = -10, + /** don't print anything except a few catastrophic errors*/ + HELICS_LOG_LEVEL_NO_PRINT = -4, + /** only print error level indicators*/ + HELICS_LOG_LEVEL_ERROR = 0, + /** profiling log level*/ + HELICS_LOG_LEVEL_PROFILING = 2, + /** only print warnings and errors*/ + HELICS_LOG_LEVEL_WARNING = 3, + /** warning errors and summary level information*/ + HELICS_LOG_LEVEL_SUMMARY = 6, + /** summary+ notices about federate and broker connections +messages about network + connections*/ + HELICS_LOG_LEVEL_CONNECTIONS = 9, + /** connections+ interface definitions*/ + HELICS_LOG_LEVEL_INTERFACES = 12, + /** interfaces + timing message*/ + HELICS_LOG_LEVEL_TIMING = 15, + /** timing+ data transfer notices*/ + HELICS_LOG_LEVEL_DATA = 18, + /** data+ additional debug message*/ + HELICS_LOG_LEVEL_DEBUG = 21, + /** all internal messages*/ + HELICS_LOG_LEVEL_TRACE = 24 } HelicsLogLevels; /** enumeration of return values from the C interface functions */ typedef enum { /* NOLINT */ - /** global fatal error for federation */ - HELICS_ERROR_FATAL = -404, - /** an unknown non-helics error was produced */ - HELICS_ERROR_EXTERNAL_TYPE = -203, - /** the function produced a helics error of some other type */ - HELICS_ERROR_OTHER = -101, - /** user code generated exception */ - HELICS_USER_EXCEPTION = -29, - /** insufficient space is available to store requested data */ - HELICS_ERROR_INSUFFICIENT_SPACE = -18, - /** the function execution has failed */ - HELICS_ERROR_EXECUTION_FAILURE = -14, - /** the call made was invalid in the present state of the calling object */ - HELICS_ERROR_INVALID_FUNCTION_CALL = -10, - /** error issued when an invalid state transition occurred */ - HELICS_ERROR_INVALID_STATE_TRANSITION = -9, - /** the function issued a warning of some kind */ - HELICS_WARNING = -8, - /** the federate has terminated unexpectedly and the call cannot be completed */ - HELICS_ERROR_SYSTEM_FAILURE = -6, - /** the input was discarded and not used for some reason */ - HELICS_ERROR_DISCARD = -5, - /** the parameter passed was invalid and unable to be used */ - HELICS_ERROR_INVALID_ARGUMENT = -4, - /** indicator that the object used was not a valid object */ - HELICS_ERROR_INVALID_OBJECT = -3, - /** the operation to connect has failed */ - HELICS_ERROR_CONNECTION_FAILURE = -2, - /** registration has failed */ - HELICS_ERROR_REGISTRATION_FAILURE = -1, - /** the function executed successfully */ - HELICS_OK = 0, - /** user system abort to match typical SIGINT value*/ - HELICS_ERROR_USER_ABORT = 130, - /** force termination to match typical SIGKILL value*/ - HELICS_ERROR_TERMINATED = 143 + /** global fatal error for federation */ + HELICS_ERROR_FATAL = -404, + /** an unknown non-helics error was produced */ + HELICS_ERROR_EXTERNAL_TYPE = -203, + /** the function produced a helics error of some other type */ + HELICS_ERROR_OTHER = -101, + /** user code generated exception */ + HELICS_USER_EXCEPTION = -29, + /** insufficient space is available to store requested data */ + HELICS_ERROR_INSUFFICIENT_SPACE = -18, + /** the function execution has failed */ + HELICS_ERROR_EXECUTION_FAILURE = -14, + /** the call made was invalid in the present state of the calling object */ + HELICS_ERROR_INVALID_FUNCTION_CALL = -10, + /** error issued when an invalid state transition occurred */ + HELICS_ERROR_INVALID_STATE_TRANSITION = -9, + /** the function issued a warning of some kind */ + HELICS_WARNING = -8, + /** the federate has terminated unexpectedly and the call cannot be completed */ + HELICS_ERROR_SYSTEM_FAILURE = -6, + /** the input was discarded and not used for some reason */ + HELICS_ERROR_DISCARD = -5, + /** the parameter passed was invalid and unable to be used */ + HELICS_ERROR_INVALID_ARGUMENT = -4, + /** indicator that the object used was not a valid object */ + HELICS_ERROR_INVALID_OBJECT = -3, + /** the operation to connect has failed */ + HELICS_ERROR_CONNECTION_FAILURE = -2, + /** registration has failed */ + HELICS_ERROR_REGISTRATION_FAILURE = -1, + /** the function executed successfully */ + HELICS_OK = 0, + /** user system abort to match typical SIGINT value*/ + HELICS_ERROR_USER_ABORT = 130, + /** force termination to match typical SIGKILL value*/ + HELICS_ERROR_TERMINATED = 143 } HelicsErrorTypes; const int HELICS_INVALID_OPTION_INDEX = -101; /** enumeration of properties that apply to federates and sometimes cores*/ typedef enum { /* NOLINT */ - /** the property controlling the minimum time delta for a federate*/ - HELICS_PROPERTY_TIME_DELTA = 137, - /** the property controlling the period for a federate*/ - HELICS_PROPERTY_TIME_PERIOD = 140, - /** the property controlling time offset for the period of federate*/ - HELICS_PROPERTY_TIME_OFFSET = 141, - /** the property controlling real time lag for a federate the max time a federate can lag - real time*/ - HELICS_PROPERTY_TIME_RT_LAG = 143, - /** the property controlling real time lead for a federate the max time a federate can be - ahead of real time*/ - HELICS_PROPERTY_TIME_RT_LEAD = 144, - /** the property controlling real time tolerance for a federate sets both rt_lag and - rt_lead*/ - HELICS_PROPERTY_TIME_RT_TOLERANCE = 145, - /** the property controlling input delay for a federate*/ - HELICS_PROPERTY_TIME_INPUT_DELAY = 148, - /** the property controlling output delay for a federate*/ - HELICS_PROPERTY_TIME_OUTPUT_DELAY = 150, - /** the property specifying a timeout to trigger actions if the time for granting exceeds a - certain threshold*/ - HELICS_PROPERTY_TIME_GRANT_TIMEOUT = 161, - /** integer property controlling the maximum number of iterations in a federate*/ - HELICS_PROPERTY_INT_MAX_ITERATIONS = 259, - /** integer property controlling the log level in a federate see \ref HelicsLogLevels*/ - HELICS_PROPERTY_INT_LOG_LEVEL = 271, - /** integer property controlling the log level for file logging in a federate see \ref - HelicsLogLevels*/ - HELICS_PROPERTY_INT_FILE_LOG_LEVEL = 272, - /** integer property controlling the log level for console logging in a federate see \ref - HelicsLogLevels*/ - HELICS_PROPERTY_INT_CONSOLE_LOG_LEVEL = 274, - /** integer property controlling the size of the log buffer*/ - HELICS_PROPERTY_INT_LOG_BUFFER = 276 + /** the property controlling the minimum time delta for a federate*/ + HELICS_PROPERTY_TIME_DELTA = 137, + /** the property controlling the period for a federate*/ + HELICS_PROPERTY_TIME_PERIOD = 140, + /** the property controlling time offset for the period of federate*/ + HELICS_PROPERTY_TIME_OFFSET = 141, + /** the property controlling real time lag for a federate the max time a federate can + lag real time*/ + HELICS_PROPERTY_TIME_RT_LAG = 143, + /** the property controlling real time lead for a federate the max time a federate + can be ahead of real time*/ + HELICS_PROPERTY_TIME_RT_LEAD = 144, + /** the property controlling real time tolerance for a federate sets both rt_lag and + rt_lead*/ + HELICS_PROPERTY_TIME_RT_TOLERANCE = 145, + /** the property controlling input delay for a federate*/ + HELICS_PROPERTY_TIME_INPUT_DELAY = 148, + /** the property controlling output delay for a federate*/ + HELICS_PROPERTY_TIME_OUTPUT_DELAY = 150, + /** the property specifying a timeout to trigger actions if the time for granting + exceeds a certain threshold*/ + HELICS_PROPERTY_TIME_GRANT_TIMEOUT = 161, + /** integer property controlling the maximum number of iterations in a federate*/ + HELICS_PROPERTY_INT_MAX_ITERATIONS = 259, + /** integer property controlling the log level in a federate see \ref + HelicsLogLevels*/ + HELICS_PROPERTY_INT_LOG_LEVEL = 271, + /** integer property controlling the log level for file logging in a federate see + \ref HelicsLogLevels*/ + HELICS_PROPERTY_INT_FILE_LOG_LEVEL = 272, + /** integer property controlling the log level for console logging in a federate see + \ref HelicsLogLevels*/ + HELICS_PROPERTY_INT_CONSOLE_LOG_LEVEL = 274, + /** integer property controlling the size of the log buffer*/ + HELICS_PROPERTY_INT_LOG_BUFFER = 276 } HelicsProperties; /** result returned for requesting the value of an invalid/unknown property */ @@ -289,90 +294,94 @@ const int HELICS_INVALID_PROPERTY_VALUE = -972; /** enumeration of the multi_input operations*/ typedef enum { /* NOLINT */ - /** time and priority order the inputs from the core library*/ - HELICS_MULTI_INPUT_NO_OP = 0, - /** vectorize the inputs either double vector or string vector*/ - HELICS_MULTI_INPUT_VECTORIZE_OPERATION = 1, - /** all inputs are assumed to be boolean and all must be true to return true*/ - HELICS_MULTI_INPUT_AND_OPERATION = 2, - /** all inputs are assumed to be boolean and at least one must be true to return true*/ - HELICS_MULTI_INPUT_OR_OPERATION = 3, - /** sum all the inputs*/ - HELICS_MULTI_INPUT_SUM_OPERATION = 4, - /** do a difference operation on the inputs, first-sum(rest) - for double input, vector diff for vector input*/ - HELICS_MULTI_INPUT_DIFF_OPERATION = 5, - /** find the max of the inputs*/ - HELICS_MULTI_INPUT_MAX_OPERATION = 6, - /** find the min of the inputs*/ - HELICS_MULTI_INPUT_MIN_OPERATION = 7, - /** take the average of the inputs*/ - HELICS_MULTI_INPUT_AVERAGE_OPERATION = 8 + /** time and priority order the inputs from the core library*/ + HELICS_MULTI_INPUT_NO_OP = 0, + /** vectorize the inputs either double vector or string vector*/ + HELICS_MULTI_INPUT_VECTORIZE_OPERATION = 1, + /** all inputs are assumed to be boolean and all must be true to return true*/ + HELICS_MULTI_INPUT_AND_OPERATION = 2, + /** all inputs are assumed to be boolean and at least one must be true to return + true*/ + HELICS_MULTI_INPUT_OR_OPERATION = 3, + /** sum all the inputs*/ + HELICS_MULTI_INPUT_SUM_OPERATION = 4, + /** do a difference operation on the inputs, first-sum(rest) + for double input, vector diff for vector input*/ + HELICS_MULTI_INPUT_DIFF_OPERATION = 5, + /** find the max of the inputs*/ + HELICS_MULTI_INPUT_MAX_OPERATION = 6, + /** find the min of the inputs*/ + HELICS_MULTI_INPUT_MIN_OPERATION = 7, + /** take the average of the inputs*/ + HELICS_MULTI_INPUT_AVERAGE_OPERATION = 8 } HelicsMultiInputModes; /** enumeration of options that apply to handles*/ typedef enum { /* NOLINT */ - /** specify that a connection is required for an interface and will generate an error if not - available*/ - HELICS_HANDLE_OPTION_CONNECTION_REQUIRED = 397, - /** specify that a connection is NOT required for an interface and will only be made if - available no warning will be issues if not available*/ - HELICS_HANDLE_OPTION_CONNECTION_OPTIONAL = 402, - /** specify that only a single connection is allowed for an interface*/ - HELICS_HANDLE_OPTION_SINGLE_CONNECTION_ONLY = 407, - /** specify that multiple connections are allowed for an interface*/ - HELICS_HANDLE_OPTION_MULTIPLE_CONNECTIONS_ALLOWED = 409, - /** specify that the last data should be buffered and sent on subscriptions after init*/ - HELICS_HANDLE_OPTION_BUFFER_DATA = 411, - /** specify that the types should be checked strictly for pub/sub and filters*/ - HELICS_HANDLE_OPTION_STRICT_TYPE_CHECKING = 414, - /** specify that the mismatching units should be ignored*/ - HELICS_HANDLE_OPTION_IGNORE_UNIT_MISMATCH = 447, - /** specify that an interface will only transmit on change(only applicable to - publications)*/ - HELICS_HANDLE_OPTION_ONLY_TRANSMIT_ON_CHANGE = 452, - /** specify that an interface will only update if the value has actually changed*/ - HELICS_HANDLE_OPTION_ONLY_UPDATE_ON_CHANGE = 454, - /** specify that an interface does not participate in determining time interrupts*/ - HELICS_HANDLE_OPTION_IGNORE_INTERRUPTS = 475, - /** specify the multi-input processing method for inputs*/ - HELICS_HANDLE_OPTION_MULTI_INPUT_HANDLING_METHOD = 507, - /** specify the source index with the highest priority*/ - HELICS_HANDLE_OPTION_INPUT_PRIORITY_LOCATION = 510, - /** specify that the priority list should be cleared or question if it is cleared*/ - HELICS_HANDLE_OPTION_CLEAR_PRIORITY_LIST = 512, - /** specify the required number of connections or get the actual number of connections*/ - HELICS_HANDLE_OPTION_CONNECTIONS = 522 + /** specify that a connection is required for an interface and will generate an error + if not available*/ + HELICS_HANDLE_OPTION_CONNECTION_REQUIRED = 397, + /** specify that a connection is NOT required for an interface and will only be made + if available no warning will be issues if not available*/ + HELICS_HANDLE_OPTION_CONNECTION_OPTIONAL = 402, + /** specify that only a single connection is allowed for an interface*/ + HELICS_HANDLE_OPTION_SINGLE_CONNECTION_ONLY = 407, + /** specify that multiple connections are allowed for an interface*/ + HELICS_HANDLE_OPTION_MULTIPLE_CONNECTIONS_ALLOWED = 409, + /** specify that the last data should be buffered and sent on subscriptions after + init*/ + HELICS_HANDLE_OPTION_BUFFER_DATA = 411, + /** specify that the types should be checked strictly for pub/sub and filters*/ + HELICS_HANDLE_OPTION_STRICT_TYPE_CHECKING = 414, + /** specify that the mismatching units should be ignored*/ + HELICS_HANDLE_OPTION_IGNORE_UNIT_MISMATCH = 447, + /** specify that an interface will only transmit on change(only applicable to + publications)*/ + HELICS_HANDLE_OPTION_ONLY_TRANSMIT_ON_CHANGE = 452, + /** specify that an interface will only update if the value has actually changed*/ + HELICS_HANDLE_OPTION_ONLY_UPDATE_ON_CHANGE = 454, + /** specify that an interface does not participate in determining time interrupts*/ + HELICS_HANDLE_OPTION_IGNORE_INTERRUPTS = 475, + /** specify the multi-input processing method for inputs*/ + HELICS_HANDLE_OPTION_MULTI_INPUT_HANDLING_METHOD = 507, + /** specify the source index with the highest priority*/ + HELICS_HANDLE_OPTION_INPUT_PRIORITY_LOCATION = 510, + /** specify that the priority list should be cleared or question if it is cleared*/ + HELICS_HANDLE_OPTION_CLEAR_PRIORITY_LIST = 512, + /** specify the required number of connections or get the actual number of + connections*/ + HELICS_HANDLE_OPTION_CONNECTIONS = 522 } HelicsHandleOptions; /** enumeration of the predefined filter types*/ typedef enum { /* NOLINT */ - /** a custom filter type that executes a user defined callback*/ - HELICS_FILTER_TYPE_CUSTOM = 0, - /** a filter type that executes a fixed delay on a message*/ - HELICS_FILTER_TYPE_DELAY = 1, - /** a filter type that executes a random delay on the messages*/ - HELICS_FILTER_TYPE_RANDOM_DELAY = 2, - /** a filter type that randomly drops messages*/ - HELICS_FILTER_TYPE_RANDOM_DROP = 3, - /** a filter type that reroutes a message to a different destination than originally - specified*/ - HELICS_FILTER_TYPE_REROUTE = 4, - /** a filter type that duplicates a message and sends the copy to a different destination*/ - HELICS_FILTER_TYPE_CLONE = 5, - /** a customizable filter type that can perform different actions on a message based on - firewall like rules*/ - HELICS_FILTER_TYPE_FIREWALL = 6 + /** a custom filter type that executes a user defined callback*/ + HELICS_FILTER_TYPE_CUSTOM = 0, + /** a filter type that executes a fixed delay on a message*/ + HELICS_FILTER_TYPE_DELAY = 1, + /** a filter type that executes a random delay on the messages*/ + HELICS_FILTER_TYPE_RANDOM_DELAY = 2, + /** a filter type that randomly drops messages*/ + HELICS_FILTER_TYPE_RANDOM_DROP = 3, + /** a filter type that reroutes a message to a different destination than originally + specified*/ + HELICS_FILTER_TYPE_REROUTE = 4, + /** a filter type that duplicates a message and sends the copy to a different + destination*/ + HELICS_FILTER_TYPE_CLONE = 5, + /** a customizable filter type that can perform different actions on a message based + on firewall like rules*/ + HELICS_FILTER_TYPE_FIREWALL = 6 } HelicsFilterTypes; /** enumeration of the predefined translator types*/ typedef enum { /* NOLINT */ - /** a custom filter type that executes a user defined callback*/ - HELICS_TRANSLATOR_TYPE_CUSTOM = 0, - /** a translator type that converts to and from JSON*/ - HELICS_TRANSLATOR_TYPE_JSON = 11, - /** a translator type that just encodes the message again in binary*/ - HELICS_TRANSLATOR_TYPE_BINARY = 12 + /** a custom filter type that executes a user defined callback*/ + HELICS_TRANSLATOR_TYPE_CUSTOM = 0, + /** a translator type that converts to and from JSON*/ + HELICS_TRANSLATOR_TYPE_JSON = 11, + /** a translator type that just encodes the message again in binary*/ + HELICS_TRANSLATOR_TYPE_BINARY = 12 } HelicsTranslatorTypes; @@ -382,18 +391,17 @@ existing messages; ordered means it follows normal priority patterns and will be existing messages */ typedef enum { /* NOLINT */ - /** sequencing mode to operate on priority channels*/ - HELICS_SEQUENCING_MODE_FAST = 0, - /** sequencing mode to operate on the normal channels*/ - HELICS_SEQUENCING_MODE_ORDERED = 1, - /** select the default channel*/ - HELICS_SEQUENCING_MODE_DEFAULT = 2 + /** sequencing mode to operate on priority channels*/ + HELICS_SEQUENCING_MODE_FAST = 0, + /** sequencing mode to operate on the normal channels*/ + HELICS_SEQUENCING_MODE_ORDERED = 1, + /** select the default channel*/ + HELICS_SEQUENCING_MODE_DEFAULT = 2 } HelicsSequencingModes; #define HELICS_BIG_NUMBER 9223372036.854774 const double cHelicsBigNumber = HELICS_BIG_NUMBER; - #ifdef __cplusplus } /* end of extern "C" { */ #endif From 40baa619a855ad729fd8ac61f4a62a64a0f5ce7c Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 30 Jun 2022 05:00:08 -0700 Subject: [PATCH 6/9] add more/clearer documentation and some additional enumeration values --- docs/references/configuration_options_reference.md | 4 ++++ src/helics/application_api/MessageOperators.cpp | 6 +++--- src/helics/core/AsyncTimeCoordinator.hpp | 9 ++++++++- src/helics/core/BrokerBase.cpp | 2 +- src/helics/core/flagOperations.hpp | 6 ++++++ 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/references/configuration_options_reference.md b/docs/references/configuration_options_reference.md index 80c232d463..51e20298d6 100644 --- a/docs/references/configuration_options_reference.md +++ b/docs/references/configuration_options_reference.md @@ -295,6 +295,9 @@ String used to define the configuration of the broker if one is autogenerated. S - `--file_log_level=` - Specifies the level of logging to file for this broker. - `--console_log_level=` - Specifies the level of logging to file for this broker. - `--dumplog` - Captures a record of all logging messages and writes them out to file or console when the broker terminates. +- `--globaltime` - Specify that the broker should use a globalTime coordinator to coordinate a master clock time with all federates. +- `--async` - Specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently). +- `--timing = ("async"|"global"|"default"|"distributed")` - specify the timing mode to use for time coordination - `--tick=` - Heartbeat period in ms. When brokers fail to respond after 2 ticks secondary actions are taking to confirm the broker is still connected to the federation. Times can also be entered as strings such as "15s" or "75ms". - `--timeout=` milliseconds to wait for all the federates to connect to the broker (can also be entered as a time like '10s' or '45ms') - `--network_timeout=` - Time to establish a socket connection in ms. Times can also be entered as strings such as "15s" or "75ms". @@ -385,6 +388,7 @@ _Valid values:_ - `interfaces` - `HELICS_LOG_LEVEL_INTERFACES` - `timing` - `HELICS_LOG_LEVEL_TIMING` - `data` - `HELICS_LOG_LEVEL_DATA` +- `debug` - `HELICS_LOG_LEVEL_DEBUG` - `trace` - `HELICS_LOG_LEVEL_TRACE` Determines the level of detail for log messages. In the list above, the keywords on the left can be used when specifying the logging level via a JSON configuration file. The enumerations on the right are used when configuring via the API. diff --git a/src/helics/application_api/MessageOperators.cpp b/src/helics/application_api/MessageOperators.cpp index 7c27d9211e..dbf37d590a 100644 --- a/src/helics/application_api/MessageOperators.cpp +++ b/src/helics/application_api/MessageOperators.cpp @@ -151,17 +151,17 @@ std::unique_ptr FirewallOperator::process(std::unique_ptr mess break; case operations::set_flag1: if (res) { - setActionFlag(*message, 10); + setActionFlag(*message, user_custom_message_flag1); } break; case operations::set_flag2: if (res) { - setActionFlag(*message, 13); + setActionFlag(*message, user_custom_message_flag2); } break; case operations::set_flag3: if (res) { - setActionFlag(*message, 14); + setActionFlag(*message, user_custom_message_flag3); } break; case operations::none: diff --git a/src/helics/core/AsyncTimeCoordinator.hpp b/src/helics/core/AsyncTimeCoordinator.hpp index 75b5259a04..717b56001f 100644 --- a/src/helics/core/AsyncTimeCoordinator.hpp +++ b/src/helics/core/AsyncTimeCoordinator.hpp @@ -20,7 +20,14 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -/** class implementing no time coordination +/** class implementing a time coordinate that explicity allowed asynchronous operation of the federates. That is the federates are not time synchronized +and are allowed to operate ahead of others potential uses are +1). The use of an external time coordination mechanism. +2). A purely command driven system +3). All federates are operated in real time mode +4). You don't care about the data and just want to see how fast all the federates go on their own. + +This time coordinator does only mimimal time keeping for entry to execution mode and allows asynchronous operation of the federation */ class AsyncTimeCoordinator: public BaseTimeCoordinator { private: diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index 8dd2a97934..cb77cdd52c 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -154,7 +154,7 @@ std::shared_ptr BrokerBase::generateBaseCLI() hApp->add_flag( "--async", asyncTime, - "specify that the federation should not synchronize time (time management is done outside of helics or not relevant"); + "specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently)"); hApp->add_option_function( "--timing", [this](const std::string& arg) { diff --git a/src/helics/core/flagOperations.hpp b/src/helics/core/flagOperations.hpp index cac1dcc3e6..b7e6a0847b 100644 --- a/src/helics/core/flagOperations.hpp +++ b/src/helics/core/flagOperations.hpp @@ -93,9 +93,15 @@ enum ConnectionFlags : uint16_t { enum MessageFlags : uint16_t { /// flag indicating that the message requires processing for filters yet filter_processing_required_flag = 7, + /// custom message flag 1 + user_custom_message_flag1 = 10, /// flag indicating the message is for destination processing destination_processing_flag = 11, /// flag indicating the message is empty + /// custom message flag 2 + user_custom_message_flag2 = 13, + /// custom message flag 3 + user_custom_message_flag3 = 14, empty_flag = 15, }; From 9a5c629f9486f85bf1af34d69ee343381e750e84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 30 Jun 2022 13:07:01 +0000 Subject: [PATCH 7/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/helics/core/AsyncTimeCoordinator.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/helics/core/AsyncTimeCoordinator.hpp b/src/helics/core/AsyncTimeCoordinator.hpp index 717b56001f..fd26858d7c 100644 --- a/src/helics/core/AsyncTimeCoordinator.hpp +++ b/src/helics/core/AsyncTimeCoordinator.hpp @@ -20,14 +20,14 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -/** class implementing a time coordinate that explicity allowed asynchronous operation of the federates. That is the federates are not time synchronized -and are allowed to operate ahead of others potential uses are -1). The use of an external time coordination mechanism. -2). A purely command driven system -3). All federates are operated in real time mode -4). You don't care about the data and just want to see how fast all the federates go on their own. +/** class implementing a time coordinate that explicitly allowed asynchronous operation of the +federates. That is the federates are not time synchronized and are allowed to operate ahead of +others potential uses are 1). The use of an external time coordination mechanism. 2). A purely +command driven system 3). All federates are operated in real time mode 4). You don't care about +the data and just want to see how fast all the federates go on their own. -This time coordinator does only mimimal time keeping for entry to execution mode and allows asynchronous operation of the federation +This time coordinator does only minimal time keeping for entry to execution mode and allows +asynchronous operation of the federation */ class AsyncTimeCoordinator: public BaseTimeCoordinator { private: From 43df02ac9ec1d1b91f039e48ded75081821d23b9 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 30 Jun 2022 15:48:12 -0700 Subject: [PATCH 8/9] Apply suggestions from code review Co-authored-by: Ryan Mast <3969255+nightlark@users.noreply.github.com> --- docs/references/configuration_options_reference.md | 2 +- src/helics/core/AsyncTimeCoordinator.hpp | 8 ++++---- src/helics/core/BrokerBase.cpp | 2 +- tests/helics/system_tests/TimingTests.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/references/configuration_options_reference.md b/docs/references/configuration_options_reference.md index 51e20298d6..6f7bdf02d4 100644 --- a/docs/references/configuration_options_reference.md +++ b/docs/references/configuration_options_reference.md @@ -296,7 +296,7 @@ String used to define the configuration of the broker if one is autogenerated. S - `--console_log_level=` - Specifies the level of logging to file for this broker. - `--dumplog` - Captures a record of all logging messages and writes them out to file or console when the broker terminates. - `--globaltime` - Specify that the broker should use a globalTime coordinator to coordinate a master clock time with all federates. -- `--async` - Specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently). +- `--asynctime` - Specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently). - `--timing = ("async"|"global"|"default"|"distributed")` - specify the timing mode to use for time coordination - `--tick=` - Heartbeat period in ms. When brokers fail to respond after 2 ticks secondary actions are taking to confirm the broker is still connected to the federation. Times can also be entered as strings such as "15s" or "75ms". - `--timeout=` milliseconds to wait for all the federates to connect to the broker (can also be entered as a time like '10s' or '45ms') diff --git a/src/helics/core/AsyncTimeCoordinator.hpp b/src/helics/core/AsyncTimeCoordinator.hpp index fd26858d7c..c646c8f46c 100644 --- a/src/helics/core/AsyncTimeCoordinator.hpp +++ b/src/helics/core/AsyncTimeCoordinator.hpp @@ -20,10 +20,10 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -/** class implementing a time coordinate that explicitly allowed asynchronous operation of the -federates. That is the federates are not time synchronized and are allowed to operate ahead of -others potential uses are 1). The use of an external time coordination mechanism. 2). A purely -command driven system 3). All federates are operated in real time mode 4). You don't care about +/** class implementing a time coordinator that explicitly allows asynchronous operation of the +federates -- that is, the federates are not time synchronized and are allowed to operate ahead of +others. Potential uses are: 1) the use of an external time coordination mechanism, 2) a purely +command driven system, 3) all federates are operated in real time mode, 4) you don't care about the data and just want to see how fast all the federates go on their own. This time coordinator does only minimal time keeping for entry to execution mode and allows diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index cb77cdd52c..5b46e4a1d3 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -152,7 +152,7 @@ std::shared_ptr BrokerBase::generateBaseCLI() globalTime, "specify that the broker should use a globalTime coordinator to coordinate a master clock time with all federates"); hApp->add_flag( - "--async", + "--asynctime", asyncTime, "specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently)"); hApp->add_option_function( diff --git a/tests/helics/system_tests/TimingTests.cpp b/tests/helics/system_tests/TimingTests.cpp index 61658f14ae..4000c31217 100644 --- a/tests/helics/system_tests/TimingTests.cpp +++ b/tests/helics/system_tests/TimingTests.cpp @@ -710,7 +710,7 @@ TEST_F(timing, dual_fast_sender_tests_ci_skip) // ci_skip TEST_F(timing, async_timing) { - extraBrokerArgs = "--async"; + extraBrokerArgs = "--asynctime"; SetupTest("test", 2); auto vFed1 = GetFederateAs(0); auto vFed2 = GetFederateAs(1); @@ -747,7 +747,7 @@ TEST_F(timing, async_timing) TEST_F(timing, async_timing_message) { - extraBrokerArgs = "--async"; + extraBrokerArgs = "--asynctime"; SetupTest("test", 2); auto mFed1 = GetFederateAs(0); auto mFed2 = GetFederateAs(1); From a94da9ab27a98cf3c7f510ea8356a85d31136412 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 30 Jun 2022 17:45:59 -0700 Subject: [PATCH 9/9] Update src/helics/core/BrokerBase.cpp Co-authored-by: Ryan Mast <3969255+nightlark@users.noreply.github.com> --- src/helics/core/BrokerBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index 5b46e4a1d3..557dfb7799 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -168,7 +168,7 @@ std::shared_ptr BrokerBase::generateBaseCLI() } }, "specify the timing method to use in the broker") - ->check(CLI::IsMember({"async", "global", "distributed"})); + ->check(CLI::IsMember({"async", "global", "distributed", "default"})); hApp->add_flag("--observer", observer, "specify that the broker/core should be added as an observer only");