Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

std.channel

Explicit imports for bounded channels and timed waits and selection. Supported target: x86_64 Linux GNU. Imports are allocation-free aliases of the existing prelude facilities, with identical generic type identity.

ExportContract
channel[T](capacity: Positive[i64])Result[tuple[Sender[T], Receiver[T]], AllocError]
Sender[T], Receiver[T]Owned endpoints; explicit share() retains the queue
select_recv(&first, &second)Result[Selected[A, B], SelectError]
select_recv_nowait(&first, &second)Same, without waiting for messages
select_recv_timeout(&first, &second, timeout_ms: u64)Same, with a millisecond budget
SendError[T]Full(value), Disconnected(value)
RecvErrorEmpty, Disconnected
SendTimeoutError[T]TimedOut(value), Disconnected(value)
RecvTimeoutErrorTimedOut, Disconnected
Selected[A, B]First(value), Second(value)
SelectErrorEmpty, TimedOut, Disconnected

A worker sums messages until the sender’s scope drops it:

from std.channel import channel, Receiver, SendError
from std.thread import spawn, SpawnError

def total(inbox: Receiver[i64]) -> Result[i64, OverflowError[i64]]:
    mut sum = 0
    while True:
        match inbox.recv():
            case Ok(value):
                sum += value
            case Err(_):
                break
    Ok(sum)

def main() -> Result[(), AllocError | SendError[i64] | SpawnError[()] | IoError | OverflowError[i64]]:
    sender, inbox = channel[i64](2)?
    with spawn(total, inbox).drop_job()? as task:
        with sender as outbox:
            for n in range(1, 6):
                outbox.send(n * 10)?
        print(task.join()?)?
    Ok(())
150

The linked facility pages specify every endpoint method. Capacity must be a Positive[i64] and bounds queued messages. Computed capacities use Positive.try_from(count)?; invalid literals are compile errors. Construction returns only AllocError for capacity overflow or exhaustion. Construction makes one fallible allocation; send, receive, share, error transport and selection allocate nothing. Messages move without deep copying; rejected sends return the original value. Queue operations have constant bookkeeping plus value transfer, with unbounded lock and scheduling latency; destroying queued values costs their cleanup. Last receiver drop destroys queued values and wakes blocked senders; last sender drop allows buffered messages to drain before disconnection.

Messages must be wholly owned and worker-eligible. References, uncertified foreign handles, and recursive receiver retention are still rejected. Imports do not weaken the checks for live opposite endpoints across joins or future waits. Timeouts are budgets, not hard deadlines. Use std.time to compute remaining milliseconds; tokens do not interrupt an ordinary channel wait. No unbounded channel or arbitrary selector is added.

Acknowledgements