This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 10/5/2026.

Channel

~import std/channel

Koru Standard Library: Channels — bounded MPMC channels over proto elements.

channel.kz · 6 tors

Koru Standard Library: Channels — bounded MPMC channels over proto elements. · 63 more lines
Koru Standard Library: Channels — bounded MPMC channels over proto elements. std/channel:new(inbox, capacity: 256) { reading: Reading } // declare std/channel(inbox) // program-wide consumer join ! reading r |> handle(r) // competing consumer arm ! closed |> shutdown() // close arm (reserved word) std/channel:send(inbox, r) | ok |> .. | full |> .. | closed |> .. std/channel:send(inbox, reading: r) | .. // kind-labeled form (multi-kind) std/channel:recv(inbox) | some v |> .. | none |> .. | closed |> .. std/channel:close(inbox) | ok |> .. THE SHAPE (docs/CHANNEL.md, ruled 2026-09-24): the `{ }` body is a BRANCH TABLE — each `name: Proto` entry is one message kind: the arm word plus the proto its payload carries. Multi-kind is legal (`{ reading: Reading, alert: Alert }` → `! reading` + `! alert`); each kind gets its own ring — one firing carries one kind, and a value of a kind never queues behind another kind. `capacity:` is required, a power of two above zero; `capacity: 0` is the rendezvous spelling — deferred, refused with teaching. `std/channel(name)` is the bare-reference JOIN (the `default` tor, a [pre] rewrite to `consume` — the store `default`→`watch` pattern): `!` arms on it attach program-wide and are COLLECTED BY `new`, which splices them into the generated drain — consumers are statically enumerable, one value goes to one unit, join order. Arms under `channel:new` itself refuse. What the declaration emits into the channel's home module: - `pub const <Proto> = struct { ... }` per kind's proto — skipped when another consumer (std/list:new) already derived it. - `__koru_chan_<n>_<kind>_ring: MpmcRing(<Proto>, cap)` per kind, plus one `__koru_chan_<n>_closed` atomic — rings.kz carries no close bit; closed is channel semantics, not queue mechanics. - `__channel_send_<n>_<kind>` { value: Proto } | ok | full | closed — one send tor per kind. - `__channel_recv_<n>` {} | some Proto | none | closed — single-kind channels only (recv can't spell one payload type on a multi-kind channel; it refuses with teaching at the site). - `__channel_close_<n>` {} | ok — sets the bit, fires every `! closed` unit in join order. - `__channel_<n>_<kind>_<i>` / `__channel_<n>_closed_<i>` — one generated unit per `!` arm, the emitVerbUnit convention. - `<n>-step` / `<n>-live` / `<n>-wait` — the pump participant verbs, the same names a `! step` store exposes, so a channel joins a pump by name: std/pump(main) ! step |> inbox-step() ! live |> inbox-live() ! wait i |> inbox-wait(i: i) step: one drain pass — for each kind, each of that kind's consumer units attempts one dequeue in join order (competing: first pop wins the value); returns items moved. live: 0 once closed AND every kind's ring is drained. wait: `-> i128`, 1ms — a same-thread re-poll interest (a scalar IS a deadline); the cross-thread eventfd rung is deliberately unbuilt. `closed`-arm timing: the units fire inside `std/channel:close` — the transition point — so a channel never joined to a pump still runs them. Ordering law (same as pump/store): the declaration precedes its uses in document order — transforms run in source order and the chain steps find the channel by its emitted marker.

new

keywordcomptimetransform koru_std/channel.kz:545

default

keywordcomptimetransformpre koru_std/channel.kz:919

consume

keywordcomptimetransform koru_std/channel.kz:993

send

keywordcomptimetransform koru_std/channel.kz:1407

recv

keywordcomptimetransform koru_std/channel.kz:1421

close

keywordcomptimetransform koru_std/channel.kz:1435