15.8. More On the System Loops

Most of the work done by the Core is processed within a context of system loops. They enable processing of blocking or lengthy operations. The actual work that needs to be done is divided to smaller parts, each being processed in a single loop iteration. The iterations are called ticks. At the end of each tick the next tick callback is fired by the system which allows to do an additional work in parallel or cancel the work being processed by the Core without the need for using worker threads. Since the Core threading model is single-threaded any worker thread must not interact with the Core nor the running simulation. For example when connecting to the simulation the Core runs the connect loop, when running the simulation the main loop is being run, etc.

[Note]Note

Time differences between two ticks (and two next tick callbacks) are not fixed. The actual difference depends on the amount of the work that needs be done within a single tick, recent CPU and resource loads, etc. Also when there is no work to be done the Core sleeps for a while so that CPU cycles are not wasted. This is controlled by the tick scheduler. However there are soft limits on minimum and maximum time differences that the tick scheduler tries to hold. They can be specified via registry (Settings/System/Scheduler node, see Section 27.16, “Scheduler”) and the default values are 0.005f (the minimum difference) and 0.05f (the maximum difference).

The system loops are entered by appropriate calls to the System class. When the work associated with a particular loop is done, the loop is left automatically. The successful completion of the work often results in a system state change. If the work can not be completed an exception will be thrown and the state will not be changed.

The system loops can also be cancelled by the application by calling System::request_quit(). If called the current system loop would be cancelled. That would result either in a simple quit from the loop (if no state change is associated with the loop) or throwing an exception (if the work was not completed and a state change was expected).

The following tables list all the system loops, associated state changes and what happens if an error occurs or quit is requested:

Table 15.2. Download data system loop
LoopSystem::download_data()
PurposeDownload prerequisite data
Required statePHASE_INITIALIZED
State if succeedsPHASE_DATA_DOWNLOADED
State if failsPHASE_INITIALIZED, exception
Quit effectPHASE_INITIALIZED, ExSystemError exception

Table 15.3. Connect system loop
LoopSystem::connect( const std::istream & config )
PurposeConnect to the simulation
Required statePHASE_DATA_DOWNLOADED
State if succeedsPHASE_CONNECTED
State if failsPHASE_DATA_DOWNLOADED, exception
Quit effectPHASE_DATA_DOWNLOADED, ExSystemError exception

Table 15.4. Run system loop
LoopSystem::run()
PurposeRun main loop
Required statePHASE_CONNECTED
State if succeedsPHASE_CONNECTED
State if failsPHASE_CONNECTED, non-managed exception
Quit effectPHASE_CONNECTED

Table 15.5. Disconnect system loop
LoopSystem::disconnect()
PurposeDisconnect from the simulation
Required statePHASE_CONNECTED
State if succeedsPHASE_DATA_DOWNLOADED
State if failsPHASE_CONNECTED, exception
Quit effectPHASE_CONNECTED, ExSystemError exception

Table 15.6. Generic system loop
LoopSystem::generic_loop()
PurposeLoop until cancelled.
Required state !PHASE_CONNECTED && !PHASE_RUNNING
State if succeeds
State if failsexception
Quit effect