Skip to content

Select

Category: Communication · Status: stub · Lessons: chapter 05, Message passing (planned)

One line: Waiting on several channel operations or futures at once, and continuing with whichever becomes ready first.

Also called: select!, race.

How it connects

flowchart LR
  n_channel["Channel"]
  n_select["Select"]
  n_select -->|uses| n_channel
  classDef center stroke-width:3px
  class n_select center
  classDef outside stroke-dasharray: 4 3
  class n_channel outside

In each language

Rust none in std; crossbeam's select! runs a random one of the ready channel operations, and tokio's select! returns when the first branch completes and cancels the rest
Go the select statement: when several cases can proceed, one is chosen by uniform pseudo-random selection; a default case makes it non-blocking
C select and poll wait on file descriptors, not on in-memory channels
Java CompletableFuture.anyOf completes when any of the given futures does; NIO's Selector multiplexes selectable I/O channels
Python asyncio.wait with return_when=FIRST_COMPLETED returns the done and pending sets as soon as any awaitable finishes
C# Task.WhenAny completes when any of the supplied tasks has completed
JavaScript Promise.race settles with the eventual state of the first promise to settle
Kotlin the experimental select expression, which is biased to the first clause when several are ready, unlike Go's random choice
Erlang and Elixir receive takes the first message in the queue that matches any clause, with an optional after timeout
The operating system epoll ↗, like select and poll, monitors many file descriptors to see which can do I/O
Elsewhere Clojure core.async's alts!

Where to read more