🦀 Rust Advanced

How does the async runtime work internally in Rust (Waker, Poll, Executor)?

Answer

Rust's async system is built on the Future trait: fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>. Poll is either Ready(value) (the future is done) or Pending (not done yet). When a future returns Pending, it is responsible for ensuring the Waker (obtained from cx.waker()) will be called when the future is ready to make progress — typically by registering it with an I/O event loop (like epoll/kqueue). An Executor (the runtime, e.g., Tokio) maintains a queue of tasks. It polls a task; if it returns Pending, the executor parks it and moves on. When the Waker is invoked (by an I/O event), it re-queues the task for polling. This cooperative scheduling allows thousands of tasks to run efficiently on a small thread pool, with no overhead per idle task.