modm API documentation
|
Typedefs | |
using | modm::Fiber< StackSize >::id = uintptr_t |
void | modm::this_fiber::yield () |
lbuild module: modm:architecture:fiber
This module provides an interface to yield control back to a scheduler. The basic functionality is provided by the yield()
function which transparently gives control back to the scheduler and returns afterwards. It is particularly important to yield in long running loops to prevent the system from locking up by preventing other fibers from making progress:
For convenience a poll()
function is provided that can be used to yield until a condition is met:
An extension of this concept is provided by the poll_for()
and poll_until()
functions, which yield until the condition is met or until a timeout occurs:
If microseconds are passed for the duration, the functions use the modm::chrono::micro_clock
(=modm::PreciseClock
), otherwise they use modm::chrono::milli_clock
(=modm::Clock
). This requires that these clocks are already initialized and running.
These basic building blocks are then used to implement the sleep_for()
and sleep_until()
convenience functions:
The yield()
function is implemented by the modm:processing:fiber
module which provides a cooperative multitasking scheduler that is able to switch between multiple fiber contexts.
If yield()
is called outside of a fiber context, for example, in the main()
function when the scheduler is not yet running, yield()
will return in-place. This mechanism allows for a graceful fallback to a blocking API without changes to the code using yield()
.
This mechanism also supports running modm on devices with very small memories where a stackful scheduler may be to resource intensive: The modm:processing:fiber
module is strictly opt-in and if not selected the scheduler is not included and the yield()
function is implemented as an empty stub while still allowing for the whole API to be used without changes:
Therefore, if you use these functions in your code, only depend on modm:architecture:fiber
and let the user decide on the implementation by including modm:processing:fiber
or not. This compromise allows for a seamless transition between different devices and scheduling strategies.
You can check what fiber your code is executed in by calling the get_id()
function:
The returned ID is the address of the currently running fiber object. If called outside of a fiber, for example, in the main function before the scheduler is running, the function returns 0
. The implementation ensures that all returned values are unique and thus allow the ID to be used for tracking ownership of various recursive locks, for example.
using modm::Fiber< StackSize >::id = uintptr_t |
Identifier of a fiber task.
void modm::this_fiber::yield | ( | ) |
Calls into the currently active scheduler to jump to the next fiber. Local control flow resumes by returning from this function.