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