Skip to content

Select

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

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