Futures need to be polled to completion. This is the job of an executor.
Some futures may need to wait for events from the kernel, for example to know when there might be data ready to read from a network channel.
A reactor handles this (by using
poll) to register for events
from the kernel and know when things might be able to progress.
std::future has the core futures functionality needed to implement async/await
std::future::Future is a trait representing an asyncronous computation.
The core method of future,
poll, attemps to resolve the future into a final
value. This method does not block if the value is not ready. Instead, the
current task is scheduled to be woken up when it's possible to make further
progress by polling again.
poll function returns:
Poll::Pendingif the future is not ready yet;
Poll::Ready(val)if the future has finished.
When the future has finished, clients should not
When using a future, you generally won't
poll directy, but instead
std::task::Waker is a handle for waking up a task by notifying its executor
that it is ready to be run (implements
The context passed to the
Future::poll method can provide a
Waker for waking
up the current task.
When future is not ready yet,
Poll::Pending and stores a clone
Waker copied from the current
Waker is then woken-up
once the future can make progress.
Futures alone are inert; they must be actively
polled to make progress,
meaning that each time the current task is woken up, it should actively re-poll
pending futures that it still has interest in.
Runtimes are not included in the standard library and is typically provided by an external crate.
futures-rs is a crate which adds utility and abstraction over futures:
FutureExt, TryFutureExt, Stream, StreamExt, TryStreamExt, Sink, SinkExt.
Tokio brings an async runtime and some additional utility to interact with
environment in async way: IO, time, unix signals, sync primitives.
Tokio is built over
Has an executor and a reactor bundled within it.
Futures that rely on the
tokio::io/fs need to be run inside the context of a
tokio runtime (which makes the tokio reactor available to them and allows
Brings an API very similar to standard lib, but for async programming. Somehow like futures-rs and tokio merged together.
Uses a different executor than tokio.
A small and fast async runtime implemented around
Doesn't come with a reactor itself.
Has a compatibility layer to interact withh tokio-based libraries.
Waker is not implemented as a trait object?
If you make
Waker a trait, then you must use it as a trait object, because if
the Future trait is generic over the kind of waker, then it becomes non-object
Box<dyn Future> impossible.
If you make it an ordinary trait object, then what should clone return? It can't return Self, as that makes the Waker trait non-object safe, so it must return a trait object. However returning a trait object is not possible without allocating, and we want async/await to be feasible on embedded systems without allocations.
Proudly self-hosted on a cheap Raspberry Pi