Time Synchronization Service

The time synchronization service is the main interface to model a participant’s behavior in case virtual time synchronization shall be used. It allows configuring a simulation step length and set the simulation step that will be executed repeatedly.

Note

Here, only a brief overview of the API is given, see Virtual Time Synchronization for more information on time synchronization with the SIL Kit.

Using the Time Synchronization Service

Once the time synchronization service was created, the participant will automatically partake in the virtual time synchronization. Setting a simulation step, even an empty one, is mandatory for participants using the time synchronization service interface. Please note that the lifecycle service and the time synchronization service can only be created once. Calling these methods more than once throws an exception. The following code creates a lifecycle service, a time synchronization service and defines the simulation step handler with the participant’s step duration:

SilKit::Services::Orchestration::LifecycleConfiguration lc
    {SilKit::Services::Orchestration::OperationMode::Coordinated};
auto* lifecycleService = participant->CreateLifecycleService(lc);
auto* timeSyncService = lifecycleService->CreateTimeSyncService();

// Set simulation step to a lambda
timeSyncService->SetSimulationStepHandler(
    [](std::chrono::nanoseconds now, std::chrono::nanoseconds duration) {
        // Do simulation computation at timepoint 'now'
    }, 1ms
);

Retrieving the Current Time

After a successful startup according to the Lifecycle State Machine, the participant will enter the Running state. The participant can now access the current simulation time using the Now() method which will be equal to the time transported in the last simulation step handler.

Asynchronous Step Handler

In special cases, it may be required to synchronize an application thread with the execution of the simulation step. That is, the application wants to execute some code during a simulation step, but on a different thread than where the simulation step is executing. To achieve this, use SetSimulationStepHandlerAsync() to assign the simulation step function that is triggered when the virtual time advances, and CompleteSimulationStep() to manually trigger the end of the simulation step and continue the simulation.

Note

See Blocking vs. Asynchronous Step Handler for more details and the differences between the handler modes.

API Reference

class ITimeSyncService

Public Types

using SimulationStepHandler = std::function<void(std::chrono::nanoseconds now, std::chrono::nanoseconds duration)>

Public Functions

virtual ~ITimeSyncService() = default
virtual void SetSimulationStepHandler(SimulationStepHandler task, std::chrono::nanoseconds initialStepSize) = 0

Set the task to be executed with each grant / tick.

Can be changed at runtime. Execution context depends on the run type.

Throwing an error inside the handler will cause a call to ReportError().

virtual void SetSimulationStepHandlerAsync(SimulationStepHandler task, std::chrono::nanoseconds initialStepSize) = 0

Set the task to be executed with each grant / tick.

Can be changed at runtime. Execution context depends on the run type. Execution will perform one simulation step at a time. CompleteSimulationStep is required to signal completion of the simulation step.

Throwing an error inside the handler will cause a call to ReportError().

virtual void CompleteSimulationStep() = 0

Signal that the current simulation task is finished and the next simulation step can be processed.

This method should only be used after calling SetSimulationStepHandlerAsync. Otherwise, undefined runtime behavior will result.

virtual auto Now() const -> std::chrono::nanoseconds = 0

Get the current simulation time.