In this lesson, you will learn how Rust’s async runtime drives progress by treating every Future as a manual state machine that must be explicitly polled to reach completion.
The Mechanism of Progress
In synchronous code, a function runs from start to finish without interruption. In Rust’s async model, a Future is essentially an opaque state machine. When you write an async block, the compiler generates a struct representing every point where your code could pause (e.g., waiting for a socket or timer).
However, this state machine is "lazy." It does nothing on its own. It requires an external actor—the Executor—to drive it. This is where poll comes in.
The poll Contract
The Future trait defines a single poll method. When an executor calls poll, it asks the state machine: "Are you done yet?"
Poll::Ready(val): The state machine has reached its final state and returned a value.Poll::Pending: The state machine hit an "await point" that isn't ready. Crucially, the future must register aWakerbefore returningPending. This ensures that when the resource finally becomes available (like a network packet arriving), the system knows exactly which state machine to resume.
Consider this simplified mental model:
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.state {
State::Start => {
if resource_ready() {
self.state = State::Done;
Poll::Ready(result)
} else {
// Register interest and yield control back to the runtime
cx.waker().wake_by_ref();
Poll::Pending
}
}
State::Done => panic!("Polled after completion"),
}
}
Why This Matters
By using a poll-based model, Rust avoids the overhead of allocating a dedicated thread stack for every single concurrent operation. Instead of blocking a thread until work is done, the executor polls the future, receives a Pending signal, and immediately moves on to poll a different task. When the original task is ready, the Waker notifies the executor, which places the task back on the "to-be-polled" queue.
This state machine approach transforms concurrency from a "waiting" problem into a "scheduling" problem, allowing thousands of tasks to coexist on a handful of hardware threads.
Key Takeaway: A Rust Future is a passive state machine that relies on an external executor to repeatedly call poll until it transitions into a Ready state.