]> git.proxmox.com Git - rustc.git/blobdiff - library/core/src/task/wake.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / library / core / src / task / wake.rs
index 87d4a25afd5867a00f5c54d63f1d6c3d180b3305..9c41b8b4f46a6d9b675586770761d0eb3742a1cd 100644 (file)
@@ -1,7 +1,8 @@
 #![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::fmt;
-use crate::marker::{PhantomData, Unpin};
+use crate::marker::PhantomData;
+use crate::ptr;
 
 /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
 /// which provides customized wakeup behavior.
@@ -47,7 +48,7 @@ impl RawWaker {
     /// Get the `data` pointer used to create this `RawWaker`.
     #[inline]
     #[must_use]
-    #[unstable(feature = "waker_getters", issue = "87021")]
+    #[unstable(feature = "waker_getters", issue = "96992")]
     pub fn data(&self) -> *const () {
         self.data
     }
@@ -55,7 +56,7 @@ impl RawWaker {
     /// Get the `vtable` pointer used to create this `RawWaker`.
     #[inline]
     #[must_use]
-    #[unstable(feature = "waker_getters", issue = "87021")]
+    #[unstable(feature = "waker_getters", issue = "96992")]
     pub fn vtable(&self) -> &'static RawWakerVTable {
         self.vtable
     }
@@ -71,6 +72,12 @@ impl RawWaker {
 /// pointer of a properly constructed [`RawWaker`] object from inside the
 /// [`RawWaker`] implementation. Calling one of the contained functions using
 /// any other `data` pointer will cause undefined behavior.
+///
+/// These functions must all be thread-safe (even though [`RawWaker`] is
+/// <code>\![Send] + \![Sync]</code>)
+/// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
+/// arbitrary threads or invoked by `&` reference. For example, this means that if the
+/// `clone` and `drop` functions manage a reference count, they must do so atomically.
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[derive(PartialEq, Copy, Clone, Debug)]
 pub struct RawWakerVTable {
@@ -98,7 +105,7 @@ pub struct RawWakerVTable {
     /// pointer.
     wake_by_ref: unsafe fn(*const ()),
 
-    /// This function gets called when a [`RawWaker`] gets dropped.
+    /// This function gets called when a [`Waker`] gets dropped.
     ///
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
@@ -110,6 +117,12 @@ impl RawWakerVTable {
     /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
     /// `wake_by_ref`, and `drop` functions.
     ///
+    /// These functions must all be thread-safe (even though [`RawWaker`] is
+    /// <code>\![Send] + \![Sync]</code>)
+    /// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
+    /// arbitrary threads or invoked by `&` reference. For example, this means that if the
+    /// `clone` and `drop` functions manage a reference count, they must do so atomically.
+    ///
     /// # `clone`
     ///
     /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
@@ -139,7 +152,7 @@ impl RawWakerVTable {
     ///
     /// # `drop`
     ///
-    /// This function gets called when a [`RawWaker`] gets dropped.
+    /// This function gets called when a [`Waker`] gets dropped.
     ///
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
@@ -157,11 +170,12 @@ impl RawWakerVTable {
     }
 }
 
-/// The `Context` of an asynchronous task.
+/// The context of an asynchronous task.
 ///
-/// Currently, `Context` only serves to provide access to a `&Waker`
+/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
 /// which can be used to wake the current task.
 #[stable(feature = "futures_api", since = "1.36.0")]
+#[lang = "Context"]
 pub struct Context<'a> {
     waker: &'a Waker,
     // Ensure we future-proof against variance changes by forcing
@@ -169,22 +183,27 @@ pub struct Context<'a> {
     // are contravariant while return-position lifetimes are
     // covariant).
     _marker: PhantomData<fn(&'a ()) -> &'a ()>,
+    // Ensure `Context` is `!Send` and `!Sync` in order to allow
+    // for future `!Send` and / or `!Sync` fields.
+    _marker2: PhantomData<*mut ()>,
 }
 
 impl<'a> Context<'a> {
-    /// Create a new `Context` from a `&Waker`.
+    /// Create a new `Context` from a [`&Waker`](Waker).
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     #[must_use]
     #[inline]
-    pub fn from_waker(waker: &'a Waker) -> Self {
-        Context { waker, _marker: PhantomData }
+    pub const fn from_waker(waker: &'a Waker) -> Self {
+        Context { waker, _marker: PhantomData, _marker2: PhantomData }
     }
 
-    /// Returns a reference to the `Waker` for the current task.
+    /// Returns a reference to the [`Waker`] for the current task.
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     #[must_use]
     #[inline]
-    pub fn waker(&self) -> &'a Waker {
+    pub const fn waker(&self) -> &'a Waker {
         &self.waker
     }
 }
@@ -202,8 +221,23 @@ impl fmt::Debug for Context<'_> {
 /// This handle encapsulates a [`RawWaker`] instance, which defines the
 /// executor-specific wakeup behavior.
 ///
-/// Implements [`Clone`], [`Send`], and [`Sync`].
-#[repr(transparent)]
+/// The typical life of a `Waker` is that it is constructed by an executor, wrapped in a
+/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return
+/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when
+/// the future should be polled again.
+///
+/// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked
+/// from any thread, including ones not in any way managed by the executor. For example,
+/// this might be done to wake a future when a blocking function call completes on another
+/// thread.
+///
+/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead
+/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker
+/// unnecessarily if the two wakers [wake the same task](Self::will_wake).
+///
+/// [`Future::poll()`]: core::future::Future::poll
+/// [`Poll::Pending`]: core::task::Poll::Pending
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
     waker: RawWaker,
@@ -219,18 +253,21 @@ unsafe impl Sync for Waker {}
 impl Waker {
     /// Wake up the task associated with this `Waker`.
     ///
-    /// As long as the runtime keeps running and the task is not finished, it is
-    /// guaranteed that each invocation of `wake` (or `wake_by_ref`) will be followed
-    /// by at least one `poll` of the task to which this `Waker` belongs. This makes
+    /// As long as the executor keeps running and the task is not finished, it is
+    /// guaranteed that each invocation of [`wake()`](Self::wake) (or
+    /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one
+    /// [`poll()`] of the task to which this `Waker` belongs. This makes
     /// it possible to temporarily yield to other tasks while running potentially
     /// unbounded processing loops.
     ///
     /// Note that the above implies that multiple wake-ups may be coalesced into a
-    /// single `poll` invocation by the runtime.
+    /// single [`poll()`] invocation by the runtime.
     ///
     /// Also note that yielding to competing tasks is not guaranteed: it is the
     /// executor’s choice which task to run and the executor may choose to run the
     /// current task again.
+    ///
+    /// [`poll()`]: crate::future::Future::poll
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn wake(self) {
@@ -250,8 +287,8 @@ impl Waker {
 
     /// Wake up the task associated with this `Waker` without consuming the `Waker`.
     ///
-    /// This is similar to `wake`, but may be slightly less efficient in the case
-    /// where an owned `Waker` is available. This method should be preferred to
+    /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in
+    /// the case where an owned `Waker` is available. This method should be preferred to
     /// calling `waker.clone().wake()`.
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
@@ -263,13 +300,15 @@ impl Waker {
         unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
     }
 
-    /// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
+    /// Returns `true` if this `Waker` and another `Waker` would awake the same task.
     ///
     /// This function works on a best-effort basis, and may return false even
     /// when the `Waker`s would awaken the same task. However, if this function
     /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
     ///
-    /// This function is primarily used for optimization purposes.
+    /// This function is primarily used for optimization purposes — for example,
+    /// this type's [`clone_from`](Self::clone_from) implementation uses it to
+    /// avoid cloning the waker when they would wake the same task anyway.
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
@@ -285,14 +324,54 @@ impl Waker {
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
-    pub unsafe fn from_raw(waker: RawWaker) -> Waker {
+    #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+    pub const unsafe fn from_raw(waker: RawWaker) -> 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]
-    #[unstable(feature = "waker_getters", issue = "87021")]
+    #[unstable(feature = "waker_getters", issue = "96992")]
     pub fn as_raw(&self) -> &RawWaker {
         &self.waker
     }
@@ -309,6 +388,13 @@ impl Clone for Waker {
             waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
         }
     }
+
+    #[inline]
+    fn clone_from(&mut self, source: &Self) {
+        if !self.will_wake(source) {
+            *self = source.clone();
+        }
+    }
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]