about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-02-04 21:10:31 +0100
committerGitHub <noreply@github.com>2021-02-04 21:10:31 +0100
commitd20d09712550c820c2d67a9b3ed2a3f9debb9393 (patch)
treef4c3ecc3ca708198a103fee5bcc6e631ee73e91c
parent822ebfd2c43fbe466da8ae34ffe3ce6cba2e8336 (diff)
parent2c8bf1db549d1e70af53b7ff8b8afb80187827e2 (diff)
Rollup merge of #74304 - yoshuawuyts:stabilize-wake, r=KodrAus
Stabilize the Wake trait

This PR proposes stabilizing the `wake_trait` feature, tracking issue https://github.com/rust-lang/rust/issues/69912.

## Motivation

The surface area this trait introduces is small, and it has been on nightly for 4 months without any reported issues. Given the surface area of this trait is small and only serves to provide a safe interface around the already stable [`std::task::RawWakerVTable`](https://doc.rust-lang.org/std/task/struct.RawWaker.html) it seems unlikely this trait will require any further changes. So I'm proposing we stabilize this.

Personally I would love to have this available on stable, since it would enable cleaning up some runtime internals by removing the tedious pointer required to construct a [`RawWakerVTable`](https://doc.rust-lang.org/std/task/struct.RawWakerVTable.html). I believe the intent was always to introduce a `Wake` counterpart to `RawWaker` in order to safely construct `Waker` instances. And the `Wake` trait feels like it does that job as intended.

## Implementation notes

This PR itself fixes a link in the docs, and introduces an example of how to use the trait: a minimal `block_on` example that runs a future to completion on the current thread. It doesn't include fancier features such as support for nesting, but is intended to serve as a teaching device for both `task::Wake` and futures alike.
-rw-r--r--library/alloc/src/task.rs66
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--src/test/ui/async-await/issue-73137.rs1
3 files changed, 60 insertions, 10 deletions
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index a80550a9653..ab7611ae071 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -1,4 +1,4 @@
-#![unstable(feature = "wake_trait", issue = "69912")]
+#![stable(feature = "wake_trait", since = "1.51.0")]
 //! Types and Traits for working with asynchronous tasks.
 use core::mem::ManuallyDrop;
 use core::task::{RawWaker, RawWakerVTable, Waker};
@@ -16,18 +16,70 @@ use crate::sync::Arc;
 /// to wake up a task is stored in an [`Arc`]. Some executors (especially
 /// those for embedded systems) cannot use this API, which is why [`RawWaker`]
 /// exists as an alternative for those systems.
-#[unstable(feature = "wake_trait", issue = "69912")]
+///
+/// [arc]: ../../std/sync/struct.Arc.html
+///
+/// # Examples
+///
+/// A basic `block_on` function that takes a future and runs it to completion on
+/// the current thread.
+///
+/// **Note:** This example trades correctness for simplicity. In order to prevent
+/// deadlocks, production-grade implementations will also need to handle
+/// intermediate calls to `thread::unpark` as well as nested invocations.
+///
+/// ```rust
+/// use std::future::Future;
+/// use std::sync::Arc;
+/// use std::task::{Context, Poll, Wake};
+/// use std::thread::{self, Thread};
+///
+/// /// A waker that wakes up the current thread when called.
+/// struct ThreadWaker(Thread);
+///
+/// impl Wake for ThreadWaker {
+///     fn wake(self: Arc<Self>) {
+///         self.0.unpark();
+///     }
+/// }
+///
+/// /// Run a future to completion on the current thread.
+/// fn block_on<T>(fut: impl Future<Output = T>) -> T {
+///     // Pin the future so it can be polled.
+///     let mut fut = Box::pin(fut);
+///
+///     // Create a new context to be passed to the future.
+///     let t = thread::current();
+///     let waker = Arc::new(ThreadWaker(t)).into();
+///     let mut cx = Context::from_waker(&waker);
+///
+///     // Run the future to completion.
+///     loop {
+///         match fut.as_mut().poll(&mut cx) {
+///             Poll::Ready(res) => return res,
+///             Poll::Pending => thread::park(),
+///         }
+///     }
+/// }
+///
+/// block_on(async {
+///     println!("Hi from inside a future!");
+/// });
+/// ```
+#[stable(feature = "wake_trait", since = "1.51.0")]
 pub trait Wake {
     /// Wake this task.
-    #[unstable(feature = "wake_trait", issue = "69912")]
+    #[stable(feature = "wake_trait", since = "1.51.0")]
     fn wake(self: Arc<Self>);
 
     /// Wake this task without consuming the waker.
     ///
     /// If an executor supports a cheaper way to wake without consuming the
     /// waker, it should override this method. By default, it clones the
-    /// [`Arc`] and calls `wake` on the clone.
-    #[unstable(feature = "wake_trait", issue = "69912")]
+    /// [`Arc`] and calls [`wake`] on the clone.
+    ///
+    /// [`wake`]: Wake::wake
+    #[stable(feature = "wake_trait", since = "1.51.0")]
     fn wake_by_ref(self: &Arc<Self>) {
         self.clone().wake();
     }
@@ -35,7 +87,7 @@ pub trait Wake {
 
 #[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
 #[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
-#[unstable(feature = "wake_trait", issue = "69912")]
+#[stable(feature = "wake_trait", since = "1.51.0")]
 impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
     fn from(waker: Arc<W>) -> Waker {
         // SAFETY: This is safe because raw_waker safely constructs
@@ -46,7 +98,7 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
 
 #[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
 #[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
-#[unstable(feature = "wake_trait", issue = "69912")]
+#[stable(feature = "wake_trait", since = "1.51.0")]
 impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
     fn from(waker: Arc<W>) -> RawWaker {
         raw_waker(waker)
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b6929f59395..961cff661e3 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -329,7 +329,6 @@
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
 #![feature(vec_spare_capacity)]
-#![feature(wake_trait)]
 // NB: the above list is sorted to minimize merge conflicts.
 #![default_lib_allocator]
 
@@ -508,7 +507,7 @@ pub mod task {
     pub use core::task::*;
 
     #[doc(inline)]
-    #[unstable(feature = "wake_trait", issue = "69912")]
+    #[stable(feature = "wake_trait", since = "1.51.0")]
     pub use alloc::task::*;
 }
 
diff --git a/src/test/ui/async-await/issue-73137.rs b/src/test/ui/async-await/issue-73137.rs
index 18374460df7..c43ce2cadba 100644
--- a/src/test/ui/async-await/issue-73137.rs
+++ b/src/test/ui/async-await/issue-73137.rs
@@ -4,7 +4,6 @@
 // edition:2018
 
 #![allow(dead_code)]
-#![feature(wake_trait)]
 use std::future::Future;
 use std::task::{Waker, Wake, Context};
 use std::sync::Arc;