about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-07 06:04:32 +0000
committerbors <bors@rust-lang.org>2023-06-07 06:04:32 +0000
commit10b7e468f3cc263b8df8ff0212d0911ed5a3c090 (patch)
tree4638537e2fa54b9e0954a04c081528e5dbb04abb
parentb3dd578767299e6bcb617fbb28724fe32b31cf3b (diff)
parent1818ed7cfe8182c14cf05265d7af21ebd987b71e (diff)
downloadrust-10b7e468f3cc263b8df8ff0212d0911ed5a3c090.tar.gz
rust-10b7e468f3cc263b8df8ff0212d0911ed5a3c090.zip
Auto merge of #96875 - SabrinaJewson:noop-waker, r=m-ou-se
Add `task::Waker::noop`

I have found myself reimplementing this function many times when I need a `Context` but don't have a runtime or `futures` to hand.

Prior art: [`futures::task::noop_waker`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker.html) and [`futures::task::noop_waker_ref`](https://docs.rs/futures/0.3/futures/task/fn.noop_waker_ref.html)

Tracking issue: https://github.com/rust-lang/rust/issues/98286

Unresolved questions:
1. Should we also add `RawWaker::noop()`? (I don't think so, I can't think of a use case for it)
2. Should we also add `Context::noop()`? Depending on the future direction `Context` goes a "noop context" might not even make sense in future.
3. Should it be an associated constant instead? That would allow for `let cx = &mut Context::from_waker(&Waker::NOOP);` to work on one line which is pretty nice. I don't really know what the guideline is here.

r? rust-lang/libs-api `@rustbot` label +T-libs-api -T-libs
-rw-r--r--library/core/src/task/wake.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 7043ab5ff2b..b63fd5c9095 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -2,6 +2,7 @@
 
 use crate::fmt;
 use crate::marker::{PhantomData, Unpin};
+use crate::ptr;
 
 /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
 /// which provides customized wakeup behavior.
@@ -322,6 +323,45 @@ impl Waker {
         Waker { waker }
     }
 
+    /// Creates a new `Waker` that does nothing when `wake` is called.
+    ///
+    /// This is mostly useful for writing tests that need a [`Context`] to poll
+    /// some futures, but are not expecting those futures to wake the waker or
+    /// do not need to do anything specific if it happens.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(noop_waker)]
+    ///
+    /// use std::future::Future;
+    /// use std::task;
+    ///
+    /// let waker = task::Waker::noop();
+    /// let mut cx = task::Context::from_waker(&waker);
+    ///
+    /// let mut future = Box::pin(async { 10 });
+    /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10));
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "noop_waker", issue = "98286")]
+    pub const fn noop() -> Waker {
+        const VTABLE: RawWakerVTable = RawWakerVTable::new(
+            // Cloning just returns a new no-op raw waker
+            |_| RAW,
+            // `wake` does nothing
+            |_| {},
+            // `wake_by_ref` does nothing
+            |_| {},
+            // Dropping does nothing as we don't allocate anything
+            |_| {},
+        );
+        const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
+
+        Waker { waker: RAW }
+    }
+
     /// Get a reference to the underlying [`RawWaker`].
     #[inline]
     #[must_use]