libkoishi: API for working with coroutines.

libkoishi Decently portable C11 coroutine library |

Typedefs | Enumerations | Functions
API for working with coroutines.

## Typedefs
typedef void *(* | koishi_entrypoint_t) (void *data)
| A coroutine entry point. More...

## Enumerations
enum | koishi_state { KOISHI_SUSPENDED , KOISHI_RUNNING , KOISHI_DEAD , KOISHI_IDLE }
| State of a koishi_coroutine_t instance. More...

## Functions
KOISHI_API void | koishi_init (koishi_coroutine_t *co, size_t min_stack_size, koishi_entrypoint_t entry_point)
| Initialize a koishi_coroutine_t structure. More...
KOISHI_API void | koishi_recycle (koishi_coroutine_t *co, koishi_entrypoint_t entry_point)
| Recycle a previously initialized coroutine. More...
KOISHI_API void | koishi_deinit (koishi_coroutine_t *co)
| Deinitialize a koishi_coroutine_t structure. More...
KOISHI_API void * | koishi_resume (koishi_coroutine_t *co, void *arg)
| Resume a suspended coroutine. More...
KOISHI_API void * | koishi_yield (void *arg)
| Suspend the currently running coroutine. More...
KOISHI_API KOISHI_NORETURN void | koishi_die (void *arg)
| Return from the currently running coroutine. More...
KOISHI_API void | koishi_kill (koishi_coroutine_t *co, void *arg)
| Stop a coroutine. More...
KOISHI_API int | koishi_state (koishi_coroutine_t *co)
| Query the state of a coroutine. More...
KOISHI_API koishi_coroutine_t * | koishi_active (void)
| Query the currently running coroutine context. More...

## Detailed Description

## Typedef Documentation

## ◆ koishi_entrypoint_t

typedef void*(* koishi_entrypoint_t) (void *data)

A coroutine entry point.

The entry point is a function that is called inside a coroutine context when it is resumed for the first time.

Once the entry point returns, control flow jumps back to the last koishi_resume call for this coroutine, as if it yielded. Its state is set to KOISHI_DEAD and it may not be resumed again.

Parameters

  data | User data that was passed to the first call to koishi_resume.

Returns
  Value to be returned from the corresponding koishi_resume call.

Definition at line 132 of file koishi.h.

## Enumeration Type Documentation

## ◆ koishi_state

enum koishi_state

State of a koishi_coroutine_t instance.

Enumerator
KOISHI_SUSPENDED | The coroutine is suspended and may be resumed with koishi_resume.
KOISHI_RUNNING | The coroutine is currently executing and may be yielded from with koishi_yield. Only up to one coroutine may be running per thread at all times.
KOISHI_DEAD | The coroutine has finished executing and may be recycled with koishi_recycle or destroyed with koishi_deinit.
KOISHI_IDLE | The coroutine has resumed another coroutine and is waiting for it to yield.

Definition at line 89 of file koishi.h.

## Function Documentation

## ◆ koishi_active()

KOISHI_API koishi_coroutine_t* koishi_active | ( | void |  | ) |

Query the currently running coroutine context.

Returns
  The coroutine currently running on this thread. This function may be called from the thread's main context as well, in which case it returns a pseudo-coroutine that represents that context. Attempting to yield from such pseudo-coroutines leads to undefined behavior. Pseudo-coroutines are never in the KOISHI_SUSPENDED state.

## ◆ koishi_deinit()

KOISHI_API void koishi_deinit | ( | koishi_coroutine_t * | co | ) |

Deinitialize a koishi_coroutine_t structure.

This will free the stack and any other resources associated with the coroutine.

Memory allocated for the structure itself will not be freed, this is your responsibility.

After calling this function, the coroutine becomes invalid, and must not be passed to any of the API functions other than koishi_init. In particular, it may not be recycled.

Parameters

  co | The coroutine to deinitialize.

## ◆ koishi_die()

KOISHI_API KOISHI_NORETURN void koishi_die | ( | void * | arg | ) |

Return from the currently running coroutine.

Like koishi_yield, except the coroutine is put into the KOISHI_DEAD state and may not be resumed again. For that reason, this function does not return. This is equivalent to returning from the entry point.

Parameters

  arg | Value to return from the corresponding koishi_resume call.

## ◆ koishi_init()

KOISHI_API void koishi_init | ( | koishi_coroutine_t * | co,
|  | size_t | min_stack_size,
|  | koishi_entrypoint_t | entry_point
| ) |  |

Initialize a koishi_coroutine_t structure.

This function must be called before using any of the other APIs with a particular coroutine instance. It allocates a stack at least `min_stack_size` bytes big and sets up an initial jump context.

After this function returns, the coroutine is in the KOISHI_SUSPENDED state. When resumed (see koishi_resume), `entry_point` will begin executing in the coroutine's context.

Parameters

  co | The coroutine to initialize.
  min_stack_size | Minimum size of the stack. The actual size will be a multiple of the system page size and at least two pages big. If 0, the default size will be used (currently 65536).
  entry_point | Function that will be called when the coroutine is first resumed.

## ◆ koishi_kill()

KOISHI_API void koishi_kill | ( | koishi_coroutine_t * | co,
|  | void * | arg
| ) |  |

Stop a coroutine.

Puts `co` into the KOISHI_DEAD state, indicating that it must not be resumed again. If `co` is the currently running coroutine, then this is equivalent to calling koishi_die with `arg` as the argument.

If `co` is in the KOISHI_IDLE state, the coroutine it's waiting on would yield to the caller of `co`, as if `co` called koishi_yield(`arg`). This applies to both explicit and implicit yields (e.g. by return from the entry point), recursively.

Parameters

  co | The coroutine to stop.
  arg | Value to return from the corresponding koishi_resume call.

## ◆ koishi_recycle()

KOISHI_API void koishi_recycle | ( | koishi_coroutine_t * | co,
|  | koishi_entrypoint_t | entry_point
| ) |  |

Recycle a previously initialized coroutine.

This is a light-weight version of koishi_init. It will set up a new context, but reuse the existing stack, if allowed by the implementation. This is useful for applications that want to create lots of short-lived coroutines fairly often. They can avoid expensive stack allocations and deallocations by pooling and recycling completed tasks.

Parameters

  co | The coroutine to recycle. It must be initialized.
  entry_point | Function that will be called when the coroutine is first resumed.

## ◆ koishi_resume()

KOISHI_API void* koishi_resume | ( | koishi_coroutine_t * | co,
|  | void * | arg
| ) |  |

Resume a suspended coroutine.

Transfers control flow to the coroutine context, putting it into the KOISHI_RUNNING state. The calling context is put into the KOISHI_IDLE state.

If the coroutine is resumed for the first time, `arg` will be passed as a parameter to its entry point (see koishi_entrypoint_t). Otherwise, it will be returned from the corresponding koishi_yield call.

This function returns when the coroutine yields or finishes executing.

Parameters

  co | The coroutine to jump into. Must be in the KOISHI_SUSPENDED state.
  arg | A value to pass into the coroutine.

Returns
  Value returned from the coroutine once it yields or returns.

## ◆ koishi_state()

KOISHI_API int koishi_state | ( | koishi_coroutine_t * | co | ) |

Query the state of a coroutine.

Returns
  One of the four possible states.
  - KOISHI_SUSPENDED
  - KOISHI_RUNNING
  - KOISHI_IDLE
  - KOISHI_DEAD

## ◆ koishi_yield()

KOISHI_API void* koishi_yield | ( | void * | arg | ) |

Suspend the currently running coroutine.

Transfers control flow out of the coroutine back to where it was last resumed, putting it into the KOISHI_SUSPENDED state. The calling context is put into the KOISHI_RUNNING state.

This function must be called from a real coroutine context.

This function returns when and if the coroutine is resumed again.

Parameters

  arg | Value to return from the corresponding koishi_resume call.

Returns
  Value passed to a future koishi_resume call.