File coro.h

Declarations for coroutines in poco.

Implements coroutines that can be suspended and resumed.

Typedefs

typedef enum coro_state coro_state_t

Defines the states a coroutine can be at any given time.

typedef struct coro Coro
typedef void (*CoroEntrypoint)(void *context)

Function declaration for the coroutine entrypoint.

Param context:

Provided user context when creating the coroutine.

Enums

enum event_sink_slot

Preset event slot indices.

A 2 slot system is likely all we need here:

  1. Primary slot for a communication primitive event.

  2. Optional time slot for timeouts.

Note

There shouldn’t be a need for any more than what is defined.

Values:

enumerator EVENT_SINK_SLOT_PRIMARY

Primary slot reserved for the main (non-timeout) event of this yield.

enumerator EVENT_SINK_SLOT_TIMEOUT

Secondary slot reserved for timeout.

enumerator EVENT_SINK_SLOT_COUNT
enum coro_state

Defines the states a coroutine can be at any given time.

Values:

enumerator CORO_STATE_READY
enumerator CORO_STATE_RUNNING
enumerator CORO_STATE_BLOCKED
enumerator CORO_STATE_FINISHED

Functions

Coro *coro_create_static(Coro *coro, CoroEntrypoint entrypoint, void *context, PlatformStackElement *stack, size_t stack_count)

Creates a statically defined coroutine with the specific stack and entrypoint.

Note

For stack diagnostics, we actually consume the first and last element of the stack for watermarks. The consequence is that the actual usable stack size will be 2 less than the declared value.

Parameters:
  • coro – Coroutine descriptor to initialise.

  • entrypoint – Entrypoint function.

  • context – User context passed into the entrypoint function.

  • stack – Pointer to a predefined stack space (must be word aligned).

  • stack_count – Number of platform specific elements in the stack.

Returns:

pointer to the coroutine, or NULL if parameters are invalid.

void coro_destroy_static(Coro *coro)

Destroy a static coroutine.

Note

This does not free memory, it just clears the underlying platform specific context members.

Parameters:

coro – Coroutine created using coro_create_static.

Coro *coro_create(CoroEntrypoint entrypoint, void *context, size_t stack_count)

Creates a coroutine with the specific stack and entrypoint.

Note

For stack diagnostics, we actually consume the first and last element of the stack for watermarks. The consequence is that the actual usable stack size will be 2 less than the declared value.

Parameters:
  • entrypoint – Entrypoint function.

  • context – User context passed into the entrypoint function.

  • stack_count – Number of platform specific elements in the stack.

Returns:

pointer to the coroutine, or NULL if a coroutine cannot be created.

void coro_free(Coro *coro)

Frees a dynamically created coroutine.

Warning

Using this on a statically created coroutine is undefined.

Parameters:

coro – Coroutine to free.

void coro_yield(void)

Called by the coroutine to yield control back to the scheduler.

The coroutine will be placed immediately back into the scheduler. Depending on the scheduler, this may cause it to be scheduled again immediately.

This yields with the NONE event source.

Note

This function will block until the coroutine is resumed again.

void coro_yield_delay(int64_t duration_ms)

Yield the coroutine with a specific delay.

Delay times are “at least” values, the guarantee is that the coroutine will not resume until at least the specified time has passed. The scheduler may resume the coroutine later if required.

Parameters:

duration_ms – Minimum duration in milliseconds the coroutine should wait.

void coro_join(Coro *coro)

Join and waits for the target coroutine to finish before resuming.

Parameters:

coro – Coroutine to join.

struct coro
#include <coro.h>

Represents a coroutine that can be scheduled and executed.

Public Members

CoroEntrypoint entrypoint

Coroutine’s main entrypoint function.

PlatformStackElement *stack

Stack Declaration

size_t stack_size

Stack length, in bytes. Will always be an integer multiple of PlatformStackElement.

size_t triggered_event_sink_slot

The event sink item that unblocked this sink, only valid after a blocked coroutine as been unblocked.

CoroEventSource event_source

Managed event source, only valid if the coroutine has notified the scheduler.

CoroEventSink event_sinks[EVENT_SINK_SLOT_COUNT]

Managed event sinks, only valid if the coroutine is blocked.

PlatformContext suspend_context
PlatformContext resume_context
coro_state_t coro_state

The current coroutine state. Schedulers should only have read-access to this.

CoroSignal yield_signal

For a non-running coroutine, this is the signal it last yielded with.