MainLoopScheduler implements the Kanzi application main loop in form of a customizable sequence of stages, each consisting of a sequence of tasks, where a task is any callable, including functions, function objects, and lambdas. More...
#include <kanzi/core.ui/main_loop/main_loop_scheduler.hpp>
Classes | |
struct | TaskInfo |
TaskInfo is a structure containing information related to a task. More... | |
Public Types | |
Enumerations. | |
enum | TaskRecurrence { TaskRecurrence::Recurring, TaskRecurrence::OneTime } |
Enumeration for task recurrence options. More... | |
enum | TimerRecurrence { TimerRecurrence::Recurring, TimerRecurrence::OneTime } |
Enumeration for timer recurrence options. More... | |
Public types and aliases. | |
using | Task = function< void(chrono::nanoseconds)> |
Type alias for stage tasks. More... | |
using | TimerTask = function< void(chrono::nanoseconds, unsigned int)> |
Type alias for timer tasks. More... | |
using | Precondition = function< bool(void)> |
Type alias for stage precondition callbacks. More... | |
using | Callback = function< void(void)> |
Type alias for general callbacks. More... | |
using | OnSuspendCallback = function< optional< chrono::nanoseconds >(chrono::nanoseconds)> |
Type alias for on-suspension callbacks. More... | |
using | StageSequenceContainer = stable_vector< Stage * > |
Type alias for container of the execution sequence of the stages. More... | |
using | TaskInfoContainer = vector< TaskInfo > |
Alias for the vector of TaskInfo instances. More... | |
Public Member Functions | |
MainLoopTimerToken | appendTimer (const Stage &stage, FixedString name, TimerRecurrence recurrence, chrono::nanoseconds interval, TimerTask task) |
Adds a timer task to be executed after a stage in the main loop. More... | |
MainLoopTimerToken | appendTimer (const Stage &stage, MetadataGeneratedName name, TimerRecurrence recurrence, chrono::nanoseconds interval, TimerTask task) |
Adds a timer task to be executed after a stage in the main loop. More... | |
MainLoopTimerToken | prependTimer (const Stage &stage, FixedString name, TimerRecurrence recurrence, chrono::nanoseconds interval, TimerTask task) |
/name Timer. More... | |
MainLoopTimerToken | prependTimer (const Stage &stage, MetadataGeneratedName name, TimerRecurrence recurrence, chrono::nanoseconds interval, TimerTask task) |
Adds a timer task to be executed before a stage in the main loop. More... | |
bool | removeTimer (const MainLoopTimerToken &token) |
Removes a timer task from the main loop. More... | |
Constructors and destructor. | |
MainLoopScheduler () | |
Constructor. More... | |
~MainLoopScheduler () | |
Destructor. More... | |
MainLoopScheduler (const MainLoopScheduler &)=delete | |
MainLoopScheduler & | operator= (const MainLoopScheduler &)=delete |
MainLoopScheduler (MainLoopScheduler &&)=delete | |
MainLoopScheduler & | operator= (MainLoopScheduler &&)=delete |
Main loop entry points. | |
void | loopMain () |
Executes the whole application main loop, along with automatic suspension and frame rate control. More... | |
void | loopRunning () |
Executes the Running part of the main loop, along with automatic suspension and frame rate control. More... | |
bool | run () |
Executes a single iteration of the main loop in the Running state, with elapsed duration observed using the internal clock. More... | |
void | loopPaused () |
Executes the Paused part of the main loop. More... | |
void | suspend () |
Puts the application thread into revocable suspension for the duration determined by the frame limit and callback set with setOnSuspendCallback(). More... | |
void | yield () |
Puts the application thread into irrevocable suspension till the next frame border. More... | |
void | executeStage (const Stage &stage) |
Executes all tasks mapped to a stage of the main loop. More... | |
State control. | |
void | pause () |
Pauses the main loop and changes its state to Paused. More... | |
void | resume () |
Resumes the main loop and changes its state back to Running. More... | |
void | quit () |
Quits the main loop and changes its state to Quitting. More... | |
MainLoopState | getState () const |
Gets the main loop scheduler state. More... | |
void | setCurrentFrameRendered () |
Sets whether rendering was performed in the current frame. More... | |
bool | isCurrentFrameRendered () const |
Returns whether rendering was performed in the current frame. More... | |
Stage control. | |
void | setStageSequence (StageSequenceContainer stageSequence) |
Sets the sequence of execution of the main loop stages. More... | |
Task control. | |
MainLoopTaskToken | prependTask (const Stage &stage, FixedString name, TaskRecurrence recurrence, Task task) |
Adds a task to the front of a stage. More... | |
MainLoopTaskToken | prependTask (const Stage &stage, MetadataGeneratedName name, TaskRecurrence recurrence, Task task) |
Adds a task to the front of a stage. More... | |
MainLoopTaskToken | appendTask (const Stage &stage, FixedString name, TaskRecurrence recurrence, Task task) |
Adds a task to the back of a stage. More... | |
MainLoopTaskToken | appendTask (const Stage &stage, MetadataGeneratedName name, TaskRecurrence recurrence, Task task) |
Adds a task to the back of a stage. More... | |
bool | removeTask (const Stage &stage, const MainLoopTaskToken &token) |
Removes a task from a stage. More... | |
bool | replaceTask (const Stage &stage, const MainLoopTaskToken &token, Task task) |
Replaces a task in a stage with another one. More... | |
void | clearTasks (const Stage &stage) |
Removes all tasks in a stage. More... | |
TaskInfoContainer | getTaskInfo (const Stage &stage) const |
Returns a container with information about all tasks in a stage. More... | |
Task | getTask (const Stage &stage, const MainLoopTaskToken &token) const |
Return a task in a stage with given token. More... | |
Callbacks. | |
/} | |
void | setPrecondition (const Stage &stage, Precondition precondition) |
Sets a precondition for a stage. More... | |
void | setOnSuspendCallback (OnSuspendCallback callback) |
Sets the OnSuspend callback. More... | |
void | setOnPauseCallback (Callback callback) |
Sets the OnPause callback. More... | |
void | setResumeCheckCallback (Callback callback) |
Sets the ResumeCheck callback. More... | |
void | setOnResumeCallback (Callback callback) |
Sets the OnResume callback. More... | |
Event handle setters. | |
void | setTaskDispatcherEventHandle (NativeEventHandle nativeHandle) |
Sets the native event handle that is used in waiting for the task dispatcher. More... | |
void | setInputEventHandle (NativeEventHandle nativeHandle) |
Sets the native event handle that is used in waiting for user input. More... | |
Configurations. | |
void | setFrameRateLimit (optional< unsigned int > frameRate) |
Sets the frame rate limit of the application. More... | |
void | enableSuspendWhenIdle (bool suspendEnabled) |
Sets whether an application allows suspension. More... | |
bool | isSuspendWhenIdleEnabled () const |
Returns whether an application allows suspension. More... | |
bool | needsPolling () const |
Returns whether an event source needs polling. More... | |
Timing. | |
void | resetClock () |
Resets all internal timestamps of MainLoopScheduler. More... | |
void | advanceFrame () |
Advances the frame counter, and records last frame duration based on internal clock. More... | |
chrono::nanoseconds | getLastFrameDuration () const |
Returns the duration of the last frame: the amount of time that passed between the start of the previous frame and the start of the current frame. More... | |
optional< chrono::nanoseconds > | getSuspendDuration () const |
Suggests the duration of suspension based on configured frame limit, callback set with setOnSuspendCallback(), and the time elapsed since the start of frame based on the internal clock. More... | |
chrono::nanoseconds | getYieldDuration () const |
Suggests the yield duration, which is the remaining frame allotment, based on the frame limit and time elapsed since the start of frame as per the internal clock. More... | |
optional< chrono::nanoseconds > | getDurationUntilNextTimer () const |
Returns the time until the next timer task executes, based on internal clock. More... | |
void | setClockCallback (function< TimePoint()> callback) |
Sets the implementation of the time source. More... | |
Profiling. | |
void | initializeProfilerSampleBuffer (optional< size_t > sampleBufferSize) |
Initializes the sample buffer of main loop profiler. More... | |
MainLoopProfilerSharedPtr | getProfiler () |
Gets the main loop profiler. More... | |
uint64_t | getFrameNumber () |
Gets the current frame number in the main loop. More... | |
MainLoopScheduler implements the Kanzi application main loop in form of a customizable sequence of stages, each consisting of a sequence of tasks, where a task is any callable, including functions, function objects, and lambdas.
It also provides the default Kanzi stages, along with platform specific mechanisms for automatic suspension, and frame rate control.
Application class owns an instance of MainLoopScheduler, and fills it with stage sequence and tasks. For more details, see the implementation of Application::initializeMainLoopTasks().
You can customize the application main loop by extending its stages with additional tasks, replacing existing tasks with your own implementations, or adding timer tasks to execute some functionality at regular intervals.
To modify contents of a stage:
To observe contents of a stage:
To add and remove a timer task:
using kanzi::MainLoopScheduler::Task = function<void(chrono::nanoseconds)> |
Type alias for stage tasks.
lastFrameDuration | Time elapsed between start of last and current main loop iteration. |
using kanzi::MainLoopScheduler::TimerTask = function<void(chrono::nanoseconds, unsigned int)> |
Type alias for timer tasks.
elapsedDuration | The time since the last invocation or creation, rounded down to a multiple of the interval of the timer. |
repeatCount | The number of elapsed intervals since the last invocation. |
using kanzi::MainLoopScheduler::Precondition = function<bool(void)> |
Type alias for stage precondition callbacks.
using kanzi::MainLoopScheduler::Callback = function<void(void)> |
Type alias for general callbacks.
using kanzi::MainLoopScheduler::OnSuspendCallback = function<optional<chrono::nanoseconds>(chrono::nanoseconds)> |
Type alias for on-suspension callbacks.
remainingFrameAllotment | The time remaining in the frame based on the configured frame rate limit and elapsed time as per internal clock. |
using kanzi::MainLoopScheduler::StageSequenceContainer = stable_vector<Stage*> |
Type alias for container of the execution sequence of the stages.
using kanzi::MainLoopScheduler::TaskInfoContainer = vector<TaskInfo> |
Alias for the vector of TaskInfo instances.
|
strong |
|
strong |
Enumeration for timer recurrence options.
|
explicit |
Constructor.
kanzi::MainLoopScheduler::~MainLoopScheduler | ( | ) |
Destructor.
|
delete |
|
delete |
|
delete |
|
delete |
void kanzi::MainLoopScheduler::loopMain | ( | ) |
Executes the whole application main loop, along with automatic suspension and frame rate control.
void kanzi::MainLoopScheduler::loopRunning | ( | ) |
Executes the Running part of the main loop, along with automatic suspension and frame rate control.
An application exits this function only when it is no longer in the Running state.
bool kanzi::MainLoopScheduler::run | ( | ) |
Executes a single iteration of the main loop in the Running state, with elapsed duration observed using the internal clock.
void kanzi::MainLoopScheduler::loopPaused | ( | ) |
Executes the Paused part of the main loop.
An application exits this function only when it is no longer in the Paused state.
void kanzi::MainLoopScheduler::suspend | ( | ) |
Puts the application thread into revocable suspension for the duration determined by the frame limit and callback set with setOnSuspendCallback().
Input events and task dispatcher signals can revoke this suspension before the duration expires.
void kanzi::MainLoopScheduler::yield | ( | ) |
Puts the application thread into irrevocable suspension till the next frame border.
void kanzi::MainLoopScheduler::executeStage | ( | const Stage & | stage | ) |
Executes all tasks mapped to a stage of the main loop.
Passes the duration of the last frame to each task.
stage | Stage to execute. |
void kanzi::MainLoopScheduler::pause | ( | ) |
Pauses the main loop and changes its state to Paused.
void kanzi::MainLoopScheduler::resume | ( | ) |
Resumes the main loop and changes its state back to Running.
void kanzi::MainLoopScheduler::quit | ( | ) |
Quits the main loop and changes its state to Quitting.
MainLoopState kanzi::MainLoopScheduler::getState | ( | ) | const |
Gets the main loop scheduler state.
void kanzi::MainLoopScheduler::setCurrentFrameRendered | ( | ) |
Sets whether rendering was performed in the current frame.
Call this function from a task in the Render stage to inform the main loop that the task performed rendering. The main loop uses this as a precondition for executing the Present stage for a frame.
bool kanzi::MainLoopScheduler::isCurrentFrameRendered | ( | ) | const |
Returns whether rendering was performed in the current frame.
The main loop uses this as a precondition for executing the Present stage for a frame.
void kanzi::MainLoopScheduler::setStageSequence | ( | StageSequenceContainer | stageSequence | ) |
Sets the sequence of execution of the main loop stages.
stageSequence | Container of stage sequence. |
MainLoopTaskToken kanzi::MainLoopScheduler::prependTask | ( | const Stage & | stage, |
FixedString | name, | ||
TaskRecurrence | recurrence, | ||
Task | task | ||
) |
Adds a task to the front of a stage.
Use this overload when you have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. Must be a string literal. |
recurrence | Recurrence choice for the task that you want to insert. |
task | The task that you want to insert. |
MainLoopTaskToken kanzi::MainLoopScheduler::prependTask | ( | const Stage & | stage, |
MetadataGeneratedName | name, | ||
TaskRecurrence | recurrence, | ||
Task | task | ||
) |
Adds a task to the front of a stage.
Use this overload when you do not have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. |
recurrence | Recurrence choice for the task that you want to insert. |
task | The task that you want to insert. |
MainLoopTaskToken kanzi::MainLoopScheduler::appendTask | ( | const Stage & | stage, |
FixedString | name, | ||
TaskRecurrence | recurrence, | ||
Task | task | ||
) |
Adds a task to the back of a stage.
Use this overload when you have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. Must be a string literal. |
recurrence | Recurrence choice for the task that you want to insert. |
task | The task that you want to insert. |
MainLoopTaskToken kanzi::MainLoopScheduler::appendTask | ( | const Stage & | stage, |
MetadataGeneratedName | name, | ||
TaskRecurrence | recurrence, | ||
Task | task | ||
) |
Adds a task to the back of a stage.
Use this overload when you do not have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. |
recurrence | Recurrence choice for the task that you want to insert. |
task | The task that you want to insert. |
bool kanzi::MainLoopScheduler::removeTask | ( | const Stage & | stage, |
const MainLoopTaskToken & | token | ||
) |
Removes a task from a stage.
stage | Reference to the stage. |
token | Token of the task. |
bool kanzi::MainLoopScheduler::replaceTask | ( | const Stage & | stage, |
const MainLoopTaskToken & | token, | ||
Task | task | ||
) |
Replaces a task in a stage with another one.
stage | Reference to the stage. |
token | Token of the task. |
task | The task with which to replace the current task. |
void kanzi::MainLoopScheduler::clearTasks | ( | const Stage & | stage | ) |
Removes all tasks in a stage.
stage | Reference to the stage. |
TaskInfoContainer kanzi::MainLoopScheduler::getTaskInfo | ( | const Stage & | stage | ) | const |
Returns a container with information about all tasks in a stage.
stage | Reference to the stage. |
Task kanzi::MainLoopScheduler::getTask | ( | const Stage & | stage, |
const MainLoopTaskToken & | token | ||
) | const |
Return a task in a stage with given token.
stage | Reference to the stage. |
token | Token of the task. |
MainLoopTimerToken kanzi::MainLoopScheduler::prependTimer | ( | const Stage & | stage, |
FixedString | name, | ||
TimerRecurrence | recurrence, | ||
chrono::nanoseconds | interval, | ||
TimerTask | task | ||
) |
/name Timer.
/{ Adds a timer task to be executed before a stage in the main loop. Use this overload when you have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. Must be a string literal. |
recurrence | Recurrence type of the task. |
interval | The amount of time after which to execute the task. |
task | The task. |
MainLoopTimerToken kanzi::MainLoopScheduler::prependTimer | ( | const Stage & | stage, |
MetadataGeneratedName | name, | ||
TimerRecurrence | recurrence, | ||
chrono::nanoseconds | interval, | ||
TimerTask | task | ||
) |
Adds a timer task to be executed before a stage in the main loop.
Use this overload when you do not have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. |
recurrence | Recurrence type of the task. |
interval | The amount of time after which to execute the task. |
task | The task. |
MainLoopTimerToken kanzi::MainLoopScheduler::appendTimer | ( | const Stage & | stage, |
FixedString | name, | ||
TimerRecurrence | recurrence, | ||
chrono::nanoseconds | interval, | ||
TimerTask | task | ||
) |
Adds a timer task to be executed after a stage in the main loop.
Use this overload when you have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. Must be a string literal. |
recurrence | Recurrence type of the task. |
interval | The amount of time after which to execute the task. |
task | The task. |
MainLoopTimerToken kanzi::MainLoopScheduler::appendTimer | ( | const Stage & | stage, |
MetadataGeneratedName | name, | ||
TimerRecurrence | recurrence, | ||
chrono::nanoseconds | interval, | ||
TimerTask | task | ||
) |
Adds a timer task to be executed after a stage in the main loop.
Use this overload when you do not have the task name available at compile time.
stage | Reference to the stage. |
name | Name for the task. |
recurrence | Recurrence type of the task. |
interval | The amount of time after which to execute the task. |
task | The task. |
bool kanzi::MainLoopScheduler::removeTimer | ( | const MainLoopTimerToken & | token | ) |
Removes a timer task from the main loop.
token | Token of the task. |
void kanzi::MainLoopScheduler::setPrecondition | ( | const Stage & | stage, |
Precondition | precondition | ||
) |
Sets a precondition for a stage.
Kanzi executes a Stage only if the return from its precondition is true, or no precondition is attached.
stage | Reference to a stage. |
precondition | Precondition for the stage. |
void kanzi::MainLoopScheduler::setOnSuspendCallback | ( | OnSuspendCallback | callback | ) |
Sets the OnSuspend callback.
Kanzi executes this callback every time the main loop enters suspension, passing as argument the time remaining in frame, based on configured frame rate limit and elapsed time as per internal clock. The callback should return of the following:
callback | The callback to use. |
void kanzi::MainLoopScheduler::setOnPauseCallback | ( | Callback | callback | ) |
Sets the OnPause callback.
Kanzi executes this callback every time when the main loop enters the Paused state.
callback | The callback to use. |
void kanzi::MainLoopScheduler::setResumeCheckCallback | ( | Callback | callback | ) |
Sets the ResumeCheck callback.
Kanzi executes this callback in every iteration of the Paused loop.
callback | The callback to use. |
void kanzi::MainLoopScheduler::setOnResumeCallback | ( | Callback | callback | ) |
Sets the OnResume callback.
Kanzi executes this callback every time when the main loop exits the Paused state.
callback | The callback to use. |
void kanzi::MainLoopScheduler::setTaskDispatcherEventHandle | ( | NativeEventHandle | nativeHandle | ) |
Sets the native event handle that is used in waiting for the task dispatcher.
nativeHandle | Native event handle bound to the task dispatcher. |
void kanzi::MainLoopScheduler::setInputEventHandle | ( | NativeEventHandle | nativeHandle | ) |
Sets the native event handle that is used in waiting for user input.
nativeHandle | Native event handle bound to input. |
void kanzi::MainLoopScheduler::setFrameRateLimit | ( | optional< unsigned int > | frameRate | ) |
Sets the frame rate limit of the application.
This sets an upper limit on the number of frames rendered by Kanzi every second.
frameRate | The number of frames to render every second. To disable frame rate limit, use nullopt or 0. |
void kanzi::MainLoopScheduler::enableSuspendWhenIdle | ( | bool | suspendEnabled | ) |
Sets whether an application allows suspension.
suspendEnabled | If the application allows suspension, use true, otherwise false. |
bool kanzi::MainLoopScheduler::isSuspendWhenIdleEnabled | ( | ) | const |
Returns whether an application allows suspension.
bool kanzi::MainLoopScheduler::needsPolling | ( | ) | const |
Returns whether an event source needs polling.
Polling is needed when an event source does not have the capability to abort suspension.
void kanzi::MainLoopScheduler::resetClock | ( | ) |
Resets all internal timestamps of MainLoopScheduler.
A platform backend typically calls this interface when it switches the application from another state to Running state.
void kanzi::MainLoopScheduler::advanceFrame | ( | ) |
Advances the frame counter, and records last frame duration based on internal clock.
Additionally, records difference between the observed last frame duration and frame allotment based on set frame rate limit, which is used to compensate the allotment of subsequent frames.
chrono::nanoseconds kanzi::MainLoopScheduler::getLastFrameDuration | ( | ) | const |
Returns the duration of the last frame: the amount of time that passed between the start of the previous frame and the start of the current frame.
optional<chrono::nanoseconds> kanzi::MainLoopScheduler::getSuspendDuration | ( | ) | const |
Suggests the duration of suspension based on configured frame limit, callback set with setOnSuspendCallback(), and the time elapsed since the start of frame based on the internal clock.
chrono::nanoseconds kanzi::MainLoopScheduler::getYieldDuration | ( | ) | const |
Suggests the yield duration, which is the remaining frame allotment, based on the frame limit and time elapsed since the start of frame as per the internal clock.
Additionally, adjusts the result based on the differences between the observed frame durations and the desired frame allotment based on set frame rate limit.
optional<chrono::nanoseconds> kanzi::MainLoopScheduler::getDurationUntilNextTimer | ( | ) | const |
Returns the time until the next timer task executes, based on internal clock.
|
inline |
Sets the implementation of the time source.
Use this when you need precise control of time in unit testing.
callback | Callback to execute when the current time is needed. |
void kanzi::MainLoopScheduler::initializeProfilerSampleBuffer | ( | optional< size_t > | sampleBufferSize | ) |
Initializes the sample buffer of main loop profiler.
Only effective in profiling builds.
sampleBufferSize | Optional size of sample buffer. If nullopt, Kanzi uses KZ_PROFILING_MAIN_LOOP. |
MainLoopProfilerSharedPtr kanzi::MainLoopScheduler::getProfiler | ( | ) |
Gets the main loop profiler.
uint64_t kanzi::MainLoopScheduler::getFrameNumber | ( | ) |
Gets the current frame number in the main loop.