Skip to content

Q060. What is a Waker, and why does a future need one?

Short Answer

A Waker is a thread-safe handle that tells an executor a task may be able to make progress and should be polled again. When a future returns Pending, it registers or stores the current task's waker with the event source. The event source later calls wake or wake_by_ref. A wake-up schedules a poll; it does not complete the future, carry its output, or guarantee that the next poll returns Ready.

Deep Dive

Without wake-ups, an executor would need to repeatedly poll every pending future, wasting CPU, or risk never polling a future after its resource becomes ready.

The event source may be an I/O driver, timer, channel, or another future. It records a waker while the operation is not ready and triggers it when state changes. Implementations must avoid races between checking readiness and registering the waker, otherwise a notification can be lost.

A future should retain the current waker, not assume the first one is permanent. Wake-ups may be coalesced, and extra wake-ups are allowed. Correctness must come from checking the actual state again during poll.

Internal Model

Waker is built on a type-erased raw wake implementation and supports cloning, waking, and dropping. Executor-specific task metadata usually sits behind it. Calling wake places or marks the task in a ready queue.

Constructing a Waker manually through RawWaker is unsafe because its virtual table must uphold ownership and thread-safety contracts. Most application code uses wakers only through Context.

Example

rust
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
use std::task::{Wake, Waker};

struct FlagWake(AtomicBool);

impl Wake for FlagWake {
    fn wake(self: Arc<Self>) {
        self.0.store(true, Ordering::Release);
    }
}

fn main() {
    let state = Arc::new(FlagWake(AtomicBool::new(false)));
    let waker = Waker::from(Arc::clone(&state));

    waker.wake_by_ref();
    assert!(state.0.load(Ordering::Acquire));
}

Common Mistakes

  • Saying wake immediately polls or completes the future.
  • Returning Pending without registering a waker.
  • Treating one stored waker as valid forever without checking for replacement.

Follow-ups

  • How can a lost wake-up race occur?
  • Why may executors coalesce several wake calls?
  • What contracts make implementing RawWaker unsafe?

References

  • Rust Standard Library
  • Async Book