Expand description
selectgo — the runtime heart of select { }.
Ported from runtime/select.go.
§How it works
selectgo receives a slice of [SCase]s and an optional has_default
flag and picks the first case that can proceed without blocking.
1. Build pollorder — a random permutation of case indices (fairness).
2. Build lockorder — case indices sorted by channel address (deadlock prevention).
3. Acquire all channel locks in lockorder.
4. First pass (pollorder): check each case for immediate readiness.
– buffer op: perform it, release all locks, return winner.
– direct handoff (partner waiting): dequeue partner's sudog, perform op,
release all locks, call goready(partner), return winner.
– send on closed: release all locks, panic.
5. If has_default: release all locks, return (CASE_DEFAULT, false).
6. Blocking path:
a. For every case, allocate a sudog (is_select=true) and enqueue it.
b. Reset G.selectdone to 0 and G.param to null.
c. Release all locks.
d. gopark(Select).
7. On wakeup (winner wrote G.param = winning sudog):
a. Acquire all locks in lockorder.
b. Dequeue all *losing* sudogs (dequeue_sudog is a no-op if a racing
channel op already removed them).
c. Release all locks.
d. Release all sudogs back to the free list.
e. Return (winner_index, ok).§Type erasure
Channels are generic (Hchan<T>) but selectgo must operate over a
heterogeneous set of them. Each [SCase] carries four function pointers
that are monomorphised at the call site (by the select! macro):
| pointer | purpose |
|---|---|
lock_fn | acquire the channel’s RawMutex |
unlock_fn | release the channel’s RawMutex |
try_fn | attempt the channel op while all locks held |
enqueue_fn | enqueue a sudog on the channel’s wait queue |
dequeue_fn | remove a specific sudog (O(1) cleanup) |
chan_ptr is the type-erased *const Hchan<T> used as the channel
identity for deduplication and address-ordered locking.
§Sentinel index
selectgo returns CASE_DEFAULT (usize::MAX) when the default case is
taken. Channel cases use their 0-based index within the slice.
Constants§
- CASE_
DEFAULT - Return value from [
selectgo] when the default case is taken.