Single-consumer drainable queue for streaming events, with optional protocol auto-forwarding.
When constructed with a name, the StreamMux auto-wires every
push() to also inject a ProtocolEvent into the main event stream
using the channel's name as the method. When constructed without a
name, the channel is local-only ā items are only visible to
in-process consumers that iterate the channel directly.
Items are popped off the front as the consumer advances ā there is
no retention beyond what's currently queued. A channel accepts
exactly one subscriber; a second __iter__ / __aiter__ call
raises. Use tee(n) / atee(n) for fan-out.
Starts unbound ā neither __iter__ nor __aiter__ is available
until the StreamMux calls _bind(is_async). After binding, only
the matching iteration protocol works; the other raises TypeError.
Pump wiring (set by the run stream, not by _bind):
- _request_more: sync pump callable, returns True if a new
event was produced.
- _arequest_more: async pump coroutine factory, same contract.
Memory is bounded by caller pace: both sync and async use caller- driven pumps, so each cursor advance produces at most one event.
Lazy-subscribe: push appends to the local buffer only when a
subscriber has registered. Auto-forward via _wire_fn always fires
regardless of subscription state.
Lifecycle (close / fail) is managed by the mux ā transformers
don't need to close their channels manually.