Quick Start
This guide provides small snippets on how to use poco.
The activities generally fall into the following steps.
Pick and initialise a scheduler.
Create tasks.
Run the scheduler in the main loop.
poco can be included either as a single header or as individual components. The examples provided as part of this library showcase both styles.
Picking a Scheduler
The scheduler determines which coroutine is run at each context switch. Every coroutine is run within the context of a scheduler.
Coroutine/Task Creation
Tasks are the execution units within poco. You can group the program’s activities in the form of a coroutine and the poco scheduler will run in along side all other defined coroutines.
void producer_task(void *context) {
Queue *queue = context;
for (int i = 0; i < 3; ++i) {
queue_put(queue, &i, PLATFORM_TICKS_FOREVER);
printf("Put %d\n", i);
coro_yield_delay(1000);
}
int const sentinel = CONSUMER_STOP;
queue_put(queue, &sentinel, PLATFORM_TICKS_FOREVER);
printf("Put %d\n", sentinel);
}
Once the function has been defined, it can be attached to a coroutine via
coro_create().
if (producer_handle == NULL) {
/* Memory error */
To pause a coroutine, simply yield control back to the scheduler using the provided yield commands. As this is a coroutine library, yielding back to the scheduler is under control by the developer (with the exception of communication primitives).
Note
The frequency and duration between yields directly effects the responsiveness of the program. It is best to yield often to ensure the best responsiveness.
coro_yield()to yield.coro_yield_delay()to yield and sleep the task for a period of time.
poco’s built-in communication primitives also perform yields, such as when putting items
in a queue.
If coroutines need to be sequential, :cpp:func`coro_join` can be used to ensure a particular coroutine runs after another.
Scheduler
TODO
Running
TODO