diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-02-04 21:10:31 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-04 21:10:31 +0100 |
| commit | d20d09712550c820c2d67a9b3ed2a3f9debb9393 (patch) | |
| tree | f4c3ecc3ca708198a103fee5bcc6e631ee73e91c | |
| parent | 822ebfd2c43fbe466da8ae34ffe3ce6cba2e8336 (diff) | |
| parent | 2c8bf1db549d1e70af53b7ff8b8afb80187827e2 (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.rs | 66 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/async-await/issue-73137.rs | 1 |
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; |
