#![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.
/// 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
}
/// 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
}
/// 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 {
/// 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
/// 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
///
/// # `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
}
}
-/// 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
// 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
}
}
/// 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,
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) {
/// 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")]
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")]
#[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
}
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")]