noop_waker/
lib.rs

1// MIT/Apache2 License
2
3//! A waker that does nothing when it is woken. Useful for "now or never" type scenarioes where a future is
4//! unlikely to be polled more than once, or for "spinning" executors.
5//! 
6//! # Example
7//! 
8//! A very inefficient implementation of the `block_on` function that polls the future over and over.
9//! 
10//! ```
11//! use core::{future::Future, hint::spin_loop, task::{Context, Poll}};
12//! use futures_lite::future::poll_fn;
13//! use noop_waker::noop_waker;
14//! 
15//! fn block_on<R>(f: impl Future<Output = R>) -> R {
16//!     // pin the future to the stack
17//!     futures_lite::pin!(f);
18//! 
19//!     // create the context
20//!     let waker = noop_waker();
21//!     let mut ctx = Context::from_waker(&waker);
22//! 
23//!     // poll future in a loop
24//!     loop {
25//!         match f.as_mut().poll(&mut ctx) {
26//!             Poll::Ready(o) => return o,
27//!             Poll::Pending => spin_loop(),
28//!         }
29//!     }
30//! }
31//! 
32//! // this future returns pending 5 times before returning ready
33//! 
34//! let mut counter = 0;
35//! let my_future = poll_fn(|ctx| {
36//!     if counter < 5 {
37//!         counter += 1;
38//!         ctx.waker().wake_by_ref();
39//!         Poll::Pending
40//!     } else {
41//!         Poll::Ready(7)
42//!     }
43//! });
44//! 
45//! assert_eq!(block_on(my_future), 7);
46//! ```
47
48#![no_std]
49#![warn(clippy::pedantic)]
50
51use core::{ptr, task::{Waker, RawWaker, RawWakerVTable}};
52
53/// The whole point. Returns a waker that does nothing.
54#[inline]
55#[must_use]
56pub fn noop_waker() -> Waker {
57    let raw = RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE);
58    
59    // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
60    unsafe { Waker::from_raw(raw) }
61}
62
63const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
64
65unsafe fn noop_clone(_p: *const ()) -> RawWaker {
66    // SAFETY: this retains all of the waker's resources, of which there are none
67    RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE)
68}
69
70unsafe fn noop(_p: *const ()) {}