CONCEPT Cited by 1 source
Async Rust Future¶
Definition¶
A Future in async Rust (std::future::Future) is a
lazy state machine representing the eventual value of an
asynchronous computation. Futures expose one operation —
poll(&mut self, cx: &mut Context<'_>) -> Poll<T> — which an
executor (e.g. Tokio) calls to advance the
state machine. poll returns either Poll::Pending (not ready,
will wake when it is) or Poll::Ready(T) (done, value here).
The laziness is crucial: Futures do not run on construction.
Without an executor calling poll, nothing happens. This is what
lets Rust compose Futures into deeply nested state machines at
zero runtime allocation cost — and why the executor / event-loop
layer (Tokio, async-std, smol) is the
load-bearing integration point.
Ordinary Future vs streaming Future¶
"An ordinary Future is a one-shot value. Once it's Ready, it can't be polled anymore." (Source: sources/2025-02-26-flyio-taming-a-voracious-rust-proxy.)
For network I/O that isn't what you want — data arrives as a
stream and you want to consume it incrementally. Async Rust
addresses this with AsyncRead /
AsyncWrite, which build on top of Futures but have a
different contract: poll_read can return Ready every time
there's data ready, so the caller keeps polling until it stops
being Ready.
This split — one-shot Futures vs streaming AsyncRead — is exactly where the two async-Rust footguns live (see concepts/spurious-wakeup-busy-loop).
Integration with the executor¶
When an executor calls poll, it passes a Context containing a
Waker. The Future clones the Waker and
hands it to whatever is blocking it (a socket, a timer, an inner
Future). When that thing progresses, it wakes the Waker,
which tells the executor to re-poll this Future.
Skipping or accidentally double-firing the Waker breaks the abstraction — the executor either never re-polls (deadlock) or re-polls in a tight loop (busy-poll).
Seen in¶
- sources/2025-02-26-flyio-taming-a-voracious-rust-proxy —
Fly.io walks through the Future model as a primer, because
their production incident is exactly a Waker mis-signal at
the TLS layer. The flamegraph showed a specific Future type
—
&mut fp_io::copy::Duplex<… tokio_rustls::server::TlsStream …>— being poll'd in a tight loop, which is the executor's-eye-view of spurious-wakeup busy-looping.
Related¶
- systems/tokio — the canonical executor.
- concepts/rust-waker — the wake-up handle executors pass
into
poll. - concepts/asyncread-contract — the streaming extension.
- concepts/spurious-wakeup-busy-loop — what happens when Futures lie about readiness.
- systems/rustls / systems/tokio-rustls — the Rust TLS stack whose Futures Fly.io's proxy poll'd.
- companies/flyio