xco
A minimal C11 concurrency library. No allocation, no atomics, no hidden threads, no clocks. Single-threaded. Caller-provided storage.
Layers
Bottom-up; each layer is a thin abstraction over the one below.
xco_mach — generic resumable function, a state machine. Step in a value, step out a value, report suspended/dead. Substrate shared by stack-switching coroutines and hand-coded state machines.
event substrate — pollable events (
xco_event_t) with a fused try-or-park primitive and a single-threaded FIFO ready queue. Concrete events: latch, countdown, notify, semaphore/mutex, select (any-of) and allof, queue (with chan = unbuffered queue), broadcast, cancel, timer + pluggable timer source, timeout, ticker.xco_task — lifecycle handle for a running step: a done latch (fires with the return value) plus a cancel latch.
xco_task_group_tfans these in/out across a dynamic set of tasks.xco_coro — stack-switching coroutines. Asymmetric:
xco_suspendalways returns to the most recent resumer. Embedsxco_mach_tas first member, so generic code overxco_mach_t *works on both coroutines and hand-coded state machines.xco_op — pure-effect IO layer. Coroutines submit ops onto the runtime; the host pulls a batch via
xco_rt_take_ops, executes them however it likes (io_uring, threads, mocks, replay), and feeds completions back viaxco_op_complete. The library makes no syscalls — that property extends to IO via this layer.
Properties
- No allocation. Every event, task, queue buffer, and coroutine stack is caller-provided.
- No atomics. Single-threaded by construction; the substrate is built around an O(1) intrusive ready queue and intrusive doubly-linked waitlists.
- No clocks. The host passes
nowintoxco_rt_run; timers are driven by a pluggable source (in-tree pairing heap). - One-waiter invariant. A suspended machine is parked on at most one
event. Multi-wait is composed in the event graph (build a
select, park on that).
Build
make # builds build/libxco.a
make test # builds and runs the test suite
The platform is auto-detected from uname -m; override with
PLATFORM=<dir> (must match a directory under platform/).
Layout
xco.h,xco.c— architecture-neutral library.platform/<arch>/xco_platform.{h,c}— register save/restore and initial-context setup. Adding an arch means adding a directory here.tests/test_xco.c— coroutine smoke test.tests/test_event.c— event substrate.tests/test_op.c— IO/op layer.