<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>xco, branch HEAD</title>
<subtitle>Concurrency for C
</subtitle>
<entry>
<id>b452af6ba0dc945a4cce2a32a57dcaeefaa9eeaf</id>
<published>2026-05-05T22:54:51Z</published>
<updated>2026-05-05T22:54:51Z</updated>
<title>README.md</title>
<link rel="alternate" type="text/html" href="commit/b452af6ba0dc945a4cce2a32a57dcaeefaa9eeaf.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit b452af6ba0dc945a4cce2a32a57dcaeefaa9eeaf
parent d191587748e785931b220f9fd61f69c4d117be1b
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 15:54:51 -0700

README.md

</content>
</entry>
<entry>
<id>d191587748e785931b220f9fd61f69c4d117be1b</id>
<published>2026-05-05T22:43:48Z</published>
<updated>2026-05-05T22:43:48Z</updated>
<title>Add README</title>
<link rel="alternate" type="text/html" href="commit/d191587748e785931b220f9fd61f69c4d117be1b.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit d191587748e785931b220f9fd61f69c4d117be1b
parent a3a4dfec6af6dce976d823d7fedbf2f99e532a43
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 15:43:48 -0700

Add README

</content>
</entry>
<entry>
<id>a3a4dfec6af6dce976d823d7fedbf2f99e532a43</id>
<published>2026-05-05T22:37:32Z</published>
<updated>2026-05-05T22:37:32Z</updated>
<title>Add xco_op layer for pure-effect IO</title>
<link rel="alternate" type="text/html" href="commit/a3a4dfec6af6dce976d823d7fedbf2f99e532a43.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit a3a4dfec6af6dce976d823d7fedbf2f99e532a43
parent ac11fcddc0cf1f7eaf1610374e5e975b3168c16d
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 15:37:32 -0700

Add xco_op layer for pure-effect IO

Coroutines submit ops onto a runtime-owned pending list; the host pulls
the batch via xco_rt_take_ops, executes them externally, and feeds
completions back via xco_op_complete. The xco library reads no clocks
and makes no syscalls — that property extends to IO via this layer.

PENDING/IN_FLIGHT distinction uses a generation counter on the runtime
plus an epoch field on each op, so submit, take, and is_pending are all
O(1) — no per-op walk on take.

</content>
</entry>
<entry>
<id>ac11fcddc0cf1f7eaf1610374e5e975b3168c16d</id>
<published>2026-05-05T21:46:30Z</published>
<updated>2026-05-05T21:46:30Z</updated>
<title>Rename types and fuse try/park into poll</title>
<link rel="alternate" type="text/html" href="commit/ac11fcddc0cf1f7eaf1610374e5e975b3168c16d.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit ac11fcddc0cf1f7eaf1610374e5e975b3168c16d
parent 192570edb8035ef5a3233906c46490b64b1a013d
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 14:46:30 -0700

Rename types and fuse try/park into poll

Three changes that reshape the public API:

- Type renames separate the state-machine concept from the scheduler
  bridge: xco_step_t -&gt; xco_mach_t, xco_t -&gt; xco_coro_t, the waitlist
  node xco_waker_t -&gt; xco_waiter_t, and the scheduler bridge
  xco_step_waker_t -&gt; xco_waker_t. Send-side waker types follow suit.

- Fuse xco_event_try + xco_event_park into xco_event_poll(e, out, w).
  Passing w=NULL is a pure try; passing out=NULL parks unconditionally.
  Same fusion for chan/queue send: xco_chan_send_poll / xco_queue_send_poll
  return DELIVERED/ACCEPTED, BLOCKED, or CLOSED; closed queues now
  report CLOSED under DROP_* policies (was: silent accept).

- Collapse xco_chan_t into xco_queue_t at cap=0+BLOCK, with thin alias
  wrappers preserving the rendezvous-naming at call sites.

Also: xco_timers_peek returns UINT64_MAX sentinel instead of bool+out;
timer source tracks now with monotonic assert and exposes xco_timers_now.

</content>
</entry>
<entry>
<id>192570edb8035ef5a3233906c46490b64b1a013d</id>
<published>2026-05-05T18:31:45Z</published>
<updated>2026-05-05T18:31:45Z</updated>
<title>consistent xco_ prefix</title>
<link rel="alternate" type="text/html" href="commit/192570edb8035ef5a3233906c46490b64b1a013d.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 192570edb8035ef5a3233906c46490b64b1a013d
parent e2e8f4aa33773708c90d37689849c56cf3be6c24
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 11:31:45 -0700

consistent xco_ prefix

</content>
</entry>
<entry>
<id>e2e8f4aa33773708c90d37689849c56cf3be6c24</id>
<published>2026-05-05T18:06:34Z</published>
<updated>2026-05-05T18:06:34Z</updated>
<title>consolidate into xco.h xco.c</title>
<link rel="alternate" type="text/html" href="commit/e2e8f4aa33773708c90d37689849c56cf3be6c24.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit e2e8f4aa33773708c90d37689849c56cf3be6c24
parent 4d2f6297ebb294ab4f31bdaae93404c817e770df
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 11:06:34 -0700

consolidate into xco.h xco.c

</content>
</entry>
<entry>
<id>4d2f6297ebb294ab4f31bdaae93404c817e770df</id>
<published>2026-05-05T17:31:43Z</published>
<updated>2026-05-05T17:31:43Z</updated>
<title>Add countdown, notify, mutex, ticker, task_group, send-op, and chan/queue close</title>
<link rel="alternate" type="text/html" href="commit/4d2f6297ebb294ab4f31bdaae93404c817e770df.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 4d2f6297ebb294ab4f31bdaae93404c817e770df
parent 7cc24269a31cc36717b7d32f3dfcb3218c9ddca2
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 10:31:43 -0700

Add countdown, notify, mutex, ticker, task_group, send-op, and chan/queue close

Seven new primitives building on the existing event substrate:

- countdown_t: latch-backed fan-in counter (add/done/event).
- notify_t: transient wake-one/wake-all signal, FIFO waitlist.
- mutex_t: semaphore_t alias with binary-semaphore wrappers.
- queue_send_op_t: selectable send mirroring chan_send_op_t.
- ticker_t: re-armable timer-driven signal with skip-ahead.
- task_group_t: fan-in join + fan-out cancel over caller-allocated slots.
- chan/queue close: EOF semantics, delivered-bit on send-wakers, typed
  chan_recv / queue_recv returning RECV_GOT/EMPTY/CLOSED, idempotent
  close that drains parked senders and wakes parked receivers.

</content>
</entry>
<entry>
<id>7cc24269a31cc36717b7d32f3dfcb3218c9ddca2</id>
<published>2026-05-05T16:25:18Z</published>
<updated>2026-05-05T16:25:18Z</updated>
<title>Unify xco and xstep outer API: drive coroutines through xstep directly</title>
<link rel="alternate" type="text/html" href="commit/7cc24269a31cc36717b7d32f3dfcb3218c9ddca2.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 7cc24269a31cc36717b7d32f3dfcb3218c9ddca2
parent ec177b0d2ad8ed0c7ac11b3ee08836bbd0b41169
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 09:25:18 -0700

Unify xco and xstep outer API: drive coroutines through xstep directly

Remove xco_resume, xco_status, and xco_task_resume — they were pure
forwards to xstep / xstep_status on the embedded base. Callers now use
xstep(&amp;c-&gt;base, v) and xstep_status(&amp;c-&gt;base) for both coroutines and
hand-coded state machines, making the substrate unification visible
at the call site. xco_spawn / xco_task_spawn / xco_init / xco_suspend
stay because they have shapes xstep can&#39;t express (stacks, inner-side
suspension).

New test drives an xco_task_t through xstep directly to confirm the
trampoline still wires task_done from the body&#39;s return — i.e. the
unification holds at the task layer too.

</content>
</entry>
<entry>
<id>ec177b0d2ad8ed0c7ac11b3ee08836bbd0b41169</id>
<published>2026-05-05T16:13:16Z</published>
<updated>2026-05-05T16:13:16Z</updated>
<title>Add semaphore, queue, broadcast, task, and ergonomic helpers</title>
<link rel="alternate" type="text/html" href="commit/ec177b0d2ad8ed0c7ac11b3ee08836bbd0b41169.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit ec177b0d2ad8ed0c7ac11b3ee08836bbd0b41169
parent 3a82709a0f8258ffa4e0a224ce0a45dfc493ce46
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 09:13:16 -0700

Add semaphore, queue, broadcast, task, and ergonomic helpers

Filling out the basic communication primitives over the event substrate:
- semaphore: counting permits with FIFO direct-handoff release
- queue: bounded FIFO with BLOCK / DROP_NEWEST / DROP_OLDEST policies
- broadcast: re-armable slot for coalescing fan-out
- task: lifecycle handle (xstep + done latch + cancel) with an xco
  specialization that auto-fires done from the trampoline

Helpers that compress the standard try-park-suspend dance:
- xco_yield, xco_await, xco_await_or_cancel
- task_is_cancelled

Plumbing: waker_fire centralizes the &quot;fire receives a fully detached
waker&quot; contract, and rt_dequeue clears prev too so step-wakers can
re-park without re-init.

</content>
</entry>
<entry>
<id>3a82709a0f8258ffa4e0a224ce0a45dfc493ce46</id>
<published>2026-05-05T10:01:20Z</published>
<updated>2026-05-05T10:01:20Z</updated>
<title>Add timers: pluggable timer source with pairing-heap default</title>
<link rel="alternate" type="text/html" href="commit/3a82709a0f8258ffa4e0a224ce0a45dfc493ce46.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 3a82709a0f8258ffa4e0a224ce0a45dfc493ce46
parent 76cdbc983cbfd158c6114e33a7252c576ed6b63c
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 03:01:20 -0700

Add timers: pluggable timer source with pairing-heap default

timer_t is a sticky event keyed on a u64 deadline. The library never
reads a clock — the caller passes now to timers_advance (or rt_run,
which forwards it to any attached source). Storage is pluggable via a
timers_t vtable; the in-tree pairing heap gives O(log n) amortized
cancel, which matters because timeouts mostly don&#39;t fire.

Runtime gains an optional timers_t pointer; rt_run(rt, now) advances
it each pass before draining the ready queue, so a timer firing from
inside rt_run drains its waiters in the same call.

timeout_t bundles a timer with a cancel_t and a bridge waker that
fires cancel_set on expiration — composes with wait_or_cancel out of
the box.

</content>
</entry>
<entry>
<id>76cdbc983cbfd158c6114e33a7252c576ed6b63c</id>
<published>2026-05-05T09:18:48Z</published>
<updated>2026-05-05T09:18:48Z</updated>
<title>Add cancellation: cancel_t alias plus wait_or_cancel helper</title>
<link rel="alternate" type="text/html" href="commit/76cdbc983cbfd158c6114e33a7252c576ed6b63c.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 76cdbc983cbfd158c6114e33a7252c576ed6b63c
parent 4f8d1cf83170dc3899d1147c5113da8b5e495b72
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 02:18:48 -0700

Add cancellation: cancel_t alias plus wait_or_cancel helper

A cancel token is just a sticky latch — these are vocabulary aliases
plus a 2-input select builder so call sites can express &quot;await X, or
be cancelled&quot; without open-coding the composition. Cancel notifies;
in-flight values are released by the caller&#39;s deinit chain, not
dropped by the runtime.

</content>
</entry>
<entry>
<id>4f8d1cf83170dc3899d1147c5113da8b5e495b72</id>
<published>2026-05-05T09:07:38Z</published>
<updated>2026-05-05T09:07:38Z</updated>
<title>Add allof: all-of waitset sharing select&#39;s storage</title>
<link rel="alternate" type="text/html" href="commit/4f8d1cf83170dc3899d1147c5113da8b5e495b72.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 4f8d1cf83170dc3899d1147c5113da8b5e495b72
parent c8fcdddc76d080bee2555c69513e555134ae6768
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 02:07:38 -0700

Add allof: all-of waitset sharing select&#39;s storage

Folds an all-of combinator into select_event_t/select_input_t — caller
switches between any-of and all-of by changing only the init call. A
shared remaining counter (select inits to 1, allof to n) drives one
fire callback; done&#39;s payload is the closing input&#39;s index in both modes.

</content>
</entry>
<entry>
<id>c8fcdddc76d080bee2555c69513e555134ae6768</id>
<published>2026-05-05T08:47:59Z</published>
<updated>2026-05-05T08:47:59Z</updated>
<title>Add channel: rendezvous primitive on the event substrate</title>
<link rel="alternate" type="text/html" href="commit/c8fcdddc76d080bee2555c69513e555134ae6768.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit c8fcdddc76d080bee2555c69513e555134ae6768
parent a5b1bc4c164eec894ea9b6ca5f9de807da6b7988
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 01:47:59 -0700

Add channel: rendezvous primitive on the event substrate

Unbuffered uintptr_t channel. Sender and receiver wait on each other;
whichever arrives first parks until its peer shows up. The pending
value lives in the parked sender&#39;s chan_send_waker_t — no per-channel
buffer.

Two-tier API on the send side:
  chan_try_send / chan_park_send / chan_unpark_send
      Lightweight direct send. Sender parks until a receiver consumes
      the value, then resumes via the runtime.

  chan_send_op_t
      Per-call op object exposing a done latch as event_t. Embeds
      chan_send_waker_t (so the chan&#39;s send list stays uniform — recv
      reads .value at one offset for both flavors) and overrides the
      embedded waker&#39;s fire to set the op&#39;s done latch instead of
      resuming an xstep. This is what makes select-over-send work:
      compose &amp;op-&gt;done.base in a select like any other event.

Recv side is exposed as event_t (chan_t.recv) and composes with select
directly. To make transient sources usable through select — where the
fire-time value would otherwise be dropped by select_input_fire —
select_input_t now captures the value at fire time, and the fast path
in select_event_init stashes it from the inline try. Consumers read
inputs[winner].value uniformly across sticky and transient sources.

Both waitlists are doubly-linked FIFOs; in single-threaded operation
only one side is ever non-empty (try-then-park is atomic), so the
queues never need cross-side matching beyond pop-and-fire. Tests
cover both arrival orders, sender and receiver FIFO accumulation,
mid-list unpark, select-on-recv (wake and fast paths), and the four
send-op cases (inline, parked, select-wins, select-loses).

</content>
</entry>
<entry>
<id>a5b1bc4c164eec894ea9b6ca5f9de807da6b7988</id>
<published>2026-05-05T08:24:42Z</published>
<updated>2026-05-05T08:24:42Z</updated>
<title>Add event substrate: waker, latch, select, runtime</title>
<link rel="alternate" type="text/html" href="commit/a5b1bc4c164eec894ea9b6ca5f9de807da6b7988.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit a5b1bc4c164eec894ea9b6ca5f9de807da6b7988
parent 1d21190e6bf4de8704273bef5bc4863f5010bd6d
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Tue,  5 May 2026 01:24:42 -0700

Add event substrate: waker, latch, select, runtime

A pollable event abstraction on top of xstep. Three layers:

  waker_t    Intrusive notification node, doubly-linked while parked
             on an event waitlist (O(1) unpark) and singly-linked on
             the runtime ready queue. fire(w, value) delivers the
             event&#39;s payload directly.

  event_t    Abstract pollable: try / park / unpark. Concrete impls
             provided: latch_t (one-shot sticky bool with payload)
             and select_event_t (any-of N events, composes since a
             select is itself an event).

  runtime_t  Intrusive FIFO of step-wakers. rt_run drains it,
             resuming each xstep with the value its waker captured.

Caller-provided storage throughout — no allocation, no atomics,
single-threaded. The one-waker invariant (an xstep is parked on at
most one event) is what lets a single step_waker live inline in the
xstep and a single next/prev pair serve both list memberships;
multi-wait composes through select rather than per-step bookkeeping.

</content>
</entry>
<entry>
<id>1d21190e6bf4de8704273bef5bc4863f5010bd6d</id>
<published>2026-05-05T04:50:42Z</published>
<updated>2026-05-05T04:50:42Z</updated>
<title>Factor resumable-function interface into xstep.h</title>
<link rel="alternate" type="text/html" href="commit/1d21190e6bf4de8704273bef5bc4863f5010bd6d.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 1d21190e6bf4de8704273bef5bc4863f5010bd6d
parent 552dff0b3b6d727f42c428080c897229f31369d7
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Mon,  4 May 2026 21:50:42 -0700

Factor resumable-function interface into xstep.h

Coroutines and hand-coded state machines are both resumable functions
differing only in mechanism. Pull the shared shape — step function,
status, result — into xstep_t so generic code can drive either kind
through one interface.

xco_t embeds xstep_t as its first member and registers an internal
xco_step into base.step; xco_resume / xco_status become typed inline
forwards to xstep() / xstep_status(). Status enum and result type
unify under XSTEP_*; the test now drives both a coroutine and a
hand-coded state machine through the same drive_counter(xstep_t *).

</content>
</entry>
<entry>
<id>552dff0b3b6d727f42c428080c897229f31369d7</id>
<published>2026-05-05T02:11:59Z</published>
<updated>2026-05-05T02:11:59Z</updated>
<title>xco initial commit</title>
<link rel="alternate" type="text/html" href="commit/552dff0b3b6d727f42c428080c897229f31369d7.html" />
<author>
<name>Ryan Sepassi</name>
<email>rsepassi@gmail.com</email>
</author>
<content>commit 552dff0b3b6d727f42c428080c897229f31369d7
Author: Ryan Sepassi &lt;rsepassi@gmail.com&gt;
Date:   Mon,  4 May 2026 19:11:59 -0700

xco initial commit

</content>
</entry>
</feed>
