ALT and PRI_ALT (Alternation)
Import: from stbass import ALT, PRI_ALT, Guard
Wait for one of several guarded channel operations. Only the first ready channel is consumed.
ALT (Fair Selection)
result = await ALT(
Guard(channel_a, handler=lambda v: f"from_a: {v}"),
Guard(channel_b, handler=lambda v: f"from_b: {v}"),
)When multiple guards are ready simultaneously, ALT picks randomly among them (fair selection).
PRI_ALT (Priority Selection)
result = await PRI_ALT(
Guard(high_priority_ch, handler=lambda v: v), # checked first
Guard(low_priority_ch, handler=lambda v: v), # checked second
Guard(TIMER(seconds=5.0), handler=lambda v: "timeout"), # fallback
)PRI_ALT picks the first ready guard in declaration order (priority selection).
How ALT works internally
ALT uses a polling loop with asyncio.sleep(0) to check channel readiness without consuming values. It checks channel._queue.empty() for channels and timer events for timers. Only the winning guard's channel is consumed via recv().
Guard
Import: from stbass import Guard
A guard wraps a channel (or timer, or SKIP sentinel) with an optional precondition and handler.
Constructor
Guard(channel, *, precondition=True, handler=None)| Parameter | Type | Description |
|-----------|------|-------------|
| channel | Chan \| TIMER \| DEADLINE \| SKIP | The channel or timer to guard |
| precondition | bool \| Callable[[], bool] | Static or dynamic eligibility condition |
| handler | Callable \| None | Transform the received value. If None, raw value is returned. |
Preconditions