std/select
Wait on the first ready of many sources, like Go's select. Arm channel receives and sends, fd reads and writes, or a timeout, then wait parks until one fires and returns the winning arm's index. The value of a receive arm is fetched afterwards with ch.recv() or tryRecv(), which keeps Select non-generic; that is also why only single-consumer channels are supported.
On a program that never spawned a green task there is no scheduler, so a timeout arm never fires. The helpers in std/timer call ensureTimersLive() first.
from "std/select" import { Select }API reference
Select
pub struct SelectOwns its runtime state, so the pointer fields make it move-tracked (no @copy), and frees it in Drop, so no Select value outlives its state (an explicit destroy(&self) could be called twice, or followed by another wait()).
Select.new
fn Select.new(): SelectSelect.onRead
fn Select.onRead<T: AsFd>(self: &mut Select, h: &T): voidArm on h becoming readable. The arm holds only the descriptor NUMBER until wait() returns (a borrow cannot keep h alive past this call), so the caller must keep h open across the wait: closing it first arms whatever descriptor reuses the number. That is a wrong wakeup, not a memory error; channel arms keep an owner.
Select.onRecv
fn Select.onRecv<T>(self: &mut Select, ch: &Channel<T>): voidArm on a value becoming receivable from ch. The arm keeps its own reference to the channel, so dropping ch before wait() is safe.
Select.onSend
fn Select.onSend<T>(self: &mut Select, ch: &Channel<T>): voidArm on ch having room for a send.
Select.onTimeout
fn Select.onTimeout(self: &mut Select, ms: i64): voidSelect.onWrite
fn Select.onWrite<T: AsFd>(self: &mut Select, h: &T): voidArm on h accepting a write without blocking.
Select.wait
fn Select.wait(self: &mut Select): i64Arm every source, park until one fires, tear down the rest, return the winning arm index.