System Monitor
Using the System Monitor
Each participant has access to a System Monitor and can register callbacks to get informed about
changes of the ParticipantState
or the SystemState
that occur during the simulation.
Register Callbacks for State Transitions
To be notified about transitions of the ParticipantState
, a ParticipantStatusHandler
has to be registered. The
ParticipantStatus
contains the new ParticipantState
and further details
about the transition such as the name of the participant, the reason for the status change and timing information:
// Register ParticipantStatusHandler to receive ParticipantStatus updates from all participants.
auto participantStatusHandler =
[](Orchestration::ParticipantStatus status) {};
auto* systemMonitor = participant->GetSystemMonitor();
systemMonitor->AddParticipantStatusHandler(participantStatusHandler);
A SystemStateHandler
can be registered to get informed about system state transitions:
// Register SystemStateHandler to receive SystemState transitions.
auto systemStateHandler =
[](Orchestration::SystemState state) {};
auto* systemMonitor = participant->GetSystemMonitor();
systemMonitor->AddSystemStateHandler(systemStateHandler);
Register Callbacks for Other Participants
A ParticipantConnectedHandler
and ParticipantDisconnectedHandler
can be registered.
They report the name of any other participant connecting and disconnecting from the participant:
auto* systemMonitor = participant->GetSystemMonitor();
auto participantConnectedHandler = [](const std::string& participantName) { ... };
systemMonitor->SetParticipantConnectedHandler(participantConnectedHandler);
auto participantDisconnectedHandler = [](const std::string& participantName) { ... };
systemMonitor->SetParticipantDisconnectedHandler(participantConnectedHandler);
Additionally, there is a function which checks if a participant identified by it’s name is connected or not:
auto* systemMonitor = participant->GetSystemMonitor();
if (systemMonitor->IsParticipantConnected("SomeParticipant"))
{
// things to do only if the other participant is connected
}
API and Data Type Reference
System Monitor API
-
class ISystemMonitor
Public Types
-
using SystemStateHandler = std::function<void(SystemState)>
Callback type to indicate that a SilKit::Services::Orchestration::SystemState has been received. Cf., AddSystemStateHandler(SystemStateHandler);
-
using ParticipantStatusHandler = std::function<void(const ParticipantStatus&)>
Callback type to indicate that a ParticipantStatus has been received. Cf., AddParticipantStatusHandler(ParticipantStatusHandler);
-
using ParticipantConnectedHandler = std::function<void(const ParticipantConnectionInformation &participantInformation)>
Callback type to indicate that a participant has been connected. Cf., SetParticipantConnectedHandler(ParticipantConnectedHandler);
-
using ParticipantDisconnectedHandler = std::function<void(const ParticipantConnectionInformation &participantInformation)>
Callback type to indicate that a participant has been disconnected. Cf., SetParticipantDisconnectedHandler(ParticipantDisconnectedHandler);
Public Functions
-
virtual auto AddSystemStateHandler(SystemStateHandler handler) -> HandlerId = 0
Register a callback for SilKit::Services::Orchestration::SystemState changes.
If the current system state is not SilKit::Services::Orchestration::SystemState::Invalid, the handler will be called immediately.
- Returns
Returns a SilKit::Util::HandlerId that can be used to remove the callback.
-
virtual void RemoveSystemStateHandler(HandlerId handlerId) = 0
Remove a SystemStateHandler by SilKit::Util::HandlerId on this monitor.
- Parameters
handlerId – Identifier of the callback to be removed. Obtained upon adding to respective handler.
-
virtual auto AddParticipantStatusHandler(ParticipantStatusHandler handler) -> HandlerId = 0
Register a callback for SilKit::Services::Orchestration::ParticipantStatus changes.
The handler will be called immediately for any participant that is not in SilKit::Services::Orchestration::ParticipantState::Invalid.
- Returns
Returns a SilKit::Util::HandlerId that can be used to remove the callback.
-
virtual void RemoveParticipantStatusHandler(HandlerId handlerId) = 0
Remove a ParticipantStatusHandler by SilKit::Util::HandlerId on this monitor.
- Parameters
handlerId – Identifier of the callback to be removed. Obtained upon adding to respective handler.
-
virtual auto SystemState() const -> Orchestration::SystemState = 0
Get the current SilKit::Services::Orchestration::SystemState.
-
virtual auto ParticipantStatus(const std::string &participantName) const -> const Orchestration::ParticipantStatus& = 0
Get the current ParticipantStatus of specific participant.
- Parameters
participantName – The name of the participant for which the status is queried (UTF-8).
- Throws
SilKit::SilKitError – If the participant name does not identify a participant that participates in synchronization.
-
virtual void SetParticipantConnectedHandler(ParticipantConnectedHandler handler) = 0
Set a callback for participants being connected.
- Parameters
handler – The callback which overwrites any previously set callback
-
virtual void SetParticipantDisconnectedHandler(ParticipantDisconnectedHandler handler) = 0
Set a callback for participants being disconnected.
- Parameters
handler – The callback which overwrites any previously set callback
-
virtual auto IsParticipantConnected(const std::string &participantName) const -> bool = 0
Check if a participant identified by the participantName is present.
- Parameters
participantName – The name of the participant for which presence is queried (UTF-8).
- Returns
true if the participant is present
-
using SystemStateHandler = std::function<void(SystemState)>
Data Structures
-
struct ParticipantStatus
Details about a participant state change.
Public Members
-
std::string participantName
Name of the participant (UTF-8).
-
ParticipantState state = {ParticipantState::Invalid}
The new state of the participant.
-
std::string enterReason
The reason for the participant to enter the new state (UTF-8).
-
std::chrono::system_clock::time_point enterTime
The enter time of the participant.
-
std::chrono::system_clock::time_point refreshTime
The refresh time.
-
std::string participantName
Enumerations and Typedefs
-
enum SilKit::Services::Orchestration::ParticipantState
Available participant states.
Values:
-
enumerator Invalid
An invalid participant state.
-
enumerator ServicesCreated
The controllers created state.
-
enumerator CommunicationInitializing
The communication initializing state.
-
enumerator CommunicationInitialized
The communication initialized state.
-
enumerator ReadyToRun
The initialized state.
-
enumerator Running
The running state.
-
enumerator Paused
The paused state.
-
enumerator Stopping
The stopping state.
-
enumerator Stopped
The stopped state.
-
enumerator Error
The error state.
-
enumerator ShuttingDown
The shutting down state.
-
enumerator Shutdown
The shutdown state.
-
enumerator Aborting
The aborting state.
-
enumerator Invalid
-
enum SilKit::Services::Orchestration::SystemState
Available system states.
Values:
-
enumerator Invalid
An invalid participant state.
-
enumerator ServicesCreated
The controllers created state.
-
enumerator CommunicationInitializing
The communication initializing state.
-
enumerator CommunicationInitialized
The communication initialized state.
-
enumerator ReadyToRun
The initialized state.
-
enumerator Running
The running state.
-
enumerator Paused
The paused state.
-
enumerator Stopping
The stopping state.
-
enumerator Stopped
The stopped state.
-
enumerator Error
The error state.
-
enumerator ShuttingDown
The shutting down state.
-
enumerator Shutdown
The shutdown state.
-
enumerator Aborting
The aborting state.
-
enumerator Invalid
Usage Example
This section contains a complete example that shows the use of the System Monitor and the order of callbacks in a complete state transition with two participants. Although the participants would typically reside in different processes, their interaction is shown sequentially to demonstrate cause and effect:
/* Copyright (c) 2022 Vector Informatik GmbH
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
// ------------------------------------------------------------
// Setup of the Participants
auto participant1 = SilKit::CreateParticipant(config, participantName1, registryUri);
auto participant2 = SilKit::CreateParticipant(config, participantName2, registryUri);
auto* systemMonitor = participant1->CreateSystemMonitor();
// Register ParticipantStatusHandler to receive ParticipantStatus transitions
auto participantStatusHandler =
This might lead to the following function call invocations at runtime:
auto participantStatusHandler =
[](const ParticipantStatus& participantStatus) {};
systemMonitor->RegisterParticipantStatusHandler(participantStatusHandler);
// Register SystemStateHandler to receive SystemState transitions
auto systemStateHandler =
[](SystemState state) {};
systemMonitor->RegisterSystemStateHandler(systemStateHandler);
// ------------------------------------------------------------
// Transition from Invalid to ServicesCreated.
// LifecycleService needs to call StartLifecycle for a transition to ParticipantState::ServicesCreated.
// For more information about the use of the life cycle service and time synchronization service refer to the corresponding section.
auto* lifecycleService1 = participant1 -> CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Coordinated});
auto* timeSyncService1 = lifecycleService1 -> CreateTimeSyncService();
auto* lifecycleService2 = participant2 -> CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Coordinated});
auto* timeSyncService2 = lifecycleService2 -> CreateTimeSyncService();
timeSyncService1->SetSimulationStepHandler(
[](std::chrono::nanoseconds now, std::chrono::nanoseconds duration) {}, 1ms
);
timeSyncService2->SetSimulationStepHandler(
[](std::chrono::nanoseconds now, std::chrono::nanoseconds duration) {}, 1ms
);
lifecycleService1->StartLifecycle();
// The call of Run() leads to a participant state transition from Invalid to ServicesCreated
// and will trigger the callback of the ParticipantStatusHandler:
participantStatusHandler(participantStatus);
// with:
// - participantStatus.participantName == participantName1
// - participantStatus.state == ParticipantState::ServicesCreated
// - participantStatus.reason = "LifecycleService::StartLifecycle was called"
// - participantStatus.enterTime == enter time_point
// - participantStatus.refreshTime == enter time_point
lifecycleService2->StartLifecycle();
// The call of Run() by the second participant again triggers
// the callback of the ParticipantStatusHandler:
participantStatusHandler(participantStatus);
// with:
// - participantStatus.participantName == participantName2
// - participantStatus.state == ParticipantState::ServicesCreated
// - participantStatus.reason = "LifecycleService::StartLifecycle was called"
// - participantStatus.enterTime == enter time_point
// - participantStatus.refreshTime == enter time_point
// Since all participants are now in ParticipantState::ServicesCreated,
// the callback of the SystemStateHandler is triggered with SystemState::ServicesCreated:
systemStateHandler(state);