summaryrefslogtreecommitdiffstats
path: root/library/core/src/task
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/task')
-rw-r--r--library/core/src/task/mod.rs17
-rw-r--r--library/core/src/task/poll.rs320
-rw-r--r--library/core/src/task/ready.rs114
-rw-r--r--library/core/src/task/wake.rs334
4 files changed, 785 insertions, 0 deletions
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
new file mode 100644
index 000000000..c5f89b9a2
--- /dev/null
+++ b/library/core/src/task/mod.rs
@@ -0,0 +1,17 @@
+#![stable(feature = "futures_api", since = "1.36.0")]
+
+//! Types and Traits for working with asynchronous tasks.
+
+mod poll;
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub use self::poll::Poll;
+
+mod wake;
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
+
+mod ready;
+#[stable(feature = "ready_macro", since = "1.64.0")]
+pub use ready::ready;
+#[unstable(feature = "poll_ready", issue = "89780")]
+pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
new file mode 100644
index 000000000..41f0a25db
--- /dev/null
+++ b/library/core/src/task/poll.rs
@@ -0,0 +1,320 @@
+#![stable(feature = "futures_api", since = "1.36.0")]
+
+use crate::convert;
+use crate::ops::{self, ControlFlow};
+use crate::result::Result;
+use crate::task::Ready;
+
+/// Indicates whether a value is available or if the current task has been
+/// scheduled to receive a wakeup instead.
+#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub enum Poll<T> {
+ /// Represents that a value is immediately ready.
+ #[lang = "Ready"]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),
+
+ /// Represents that a value is not ready yet.
+ ///
+ /// When a function returns `Pending`, the function *must* also
+ /// ensure that the current task is scheduled to be awoken when
+ /// progress can be made.
+ #[lang = "Pending"]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ Pending,
+}
+
+impl<T> Poll<T> {
+ /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
+ ///
+ /// # Examples
+ ///
+ /// Converts a <code>Poll<[String]></code> into a <code>Poll<[usize]></code>, consuming
+ /// the original:
+ ///
+ /// [String]: ../../std/string/struct.String.html "String"
+ /// ```
+ /// # use core::task::Poll;
+ /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
+ /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
+ /// let poll_some_len = poll_some_string.map(|s| s.len());
+ ///
+ /// assert_eq!(poll_some_len, Poll::Ready(13));
+ /// ```
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn map<U, F>(self, f: F) -> Poll<U>
+ where
+ F: FnOnce(T) -> U,
+ {
+ match self {
+ Poll::Ready(t) => Poll::Ready(f(t)),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ /// Returns `true` if the poll is a [`Poll::Ready`] value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let x: Poll<u32> = Poll::Ready(2);
+ /// assert_eq!(x.is_ready(), true);
+ ///
+ /// let x: Poll<u32> = Poll::Pending;
+ /// assert_eq!(x.is_ready(), false);
+ /// ```
+ #[inline]
+ #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub const fn is_ready(&self) -> bool {
+ matches!(*self, Poll::Ready(_))
+ }
+
+ /// Returns `true` if the poll is a [`Pending`] value.
+ ///
+ /// [`Pending`]: Poll::Pending
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let x: Poll<u32> = Poll::Ready(2);
+ /// assert_eq!(x.is_pending(), false);
+ ///
+ /// let x: Poll<u32> = Poll::Pending;
+ /// assert_eq!(x.is_pending(), true);
+ /// ```
+ #[inline]
+ #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub const fn is_pending(&self) -> bool {
+ !self.is_ready()
+ }
+
+ /// Extracts the successful type of a [`Poll<T>`].
+ ///
+ /// When combined with the `?` operator, this function will
+ /// propagate any [`Poll::Pending`] values to the caller, and
+ /// extract the `T` from [`Poll::Ready`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(poll_ready)]
+ ///
+ /// use std::task::{Context, Poll};
+ /// use std::future::{self, Future};
+ /// use std::pin::Pin;
+ ///
+ /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+ /// let mut fut = future::ready(42);
+ /// let fut = Pin::new(&mut fut);
+ ///
+ /// let num = fut.poll(cx).ready()?;
+ /// # drop(num);
+ /// // ... use num
+ ///
+ /// Poll::Ready(())
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "poll_ready", issue = "89780")]
+ pub fn ready(self) -> Ready<T> {
+ Ready(self)
+ }
+}
+
+impl<T, E> Poll<Result<T, E>> {
+ /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
+ /// function to a contained `Poll::Ready(Ok)` value, leaving all other
+ /// variants untouched.
+ ///
+ /// This function can be used to compose the results of two functions.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
+ /// let squared = res.map_ok(|n| n * n);
+ /// assert_eq!(squared, Poll::Ready(Ok(144)));
+ /// ```
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
+ where
+ F: FnOnce(T) -> U,
+ {
+ match self {
+ Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
+ Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
+ /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
+ /// variants untouched.
+ ///
+ /// This function can be used to pass through a successful result while handling
+ /// an error.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
+ /// let res = res.map_err(|_| 0_u8);
+ /// assert_eq!(res, Poll::Ready(Err(0)));
+ /// ```
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
+ where
+ F: FnOnce(E) -> U,
+ {
+ match self {
+ Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
+ Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+impl<T, E> Poll<Option<Result<T, E>>> {
+ /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
+ /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
+ /// leaving all other variants untouched.
+ ///
+ /// This function can be used to compose the results of two functions.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
+ /// let squared = res.map_ok(|n| n * n);
+ /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
+ /// ```
+ #[stable(feature = "poll_map", since = "1.51.0")]
+ pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
+ where
+ F: FnOnce(T) -> U,
+ {
+ match self {
+ Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
+ Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
+ Poll::Ready(None) => Poll::Ready(None),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
+ /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
+ /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
+ /// untouched.
+ ///
+ /// This function can be used to pass through a successful result while handling
+ /// an error.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
+ /// let res = res.map_err(|_| 0_u8);
+ /// assert_eq!(res, Poll::Ready(Some(Err(0))));
+ /// ```
+ #[stable(feature = "poll_map", since = "1.51.0")]
+ pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
+ where
+ F: FnOnce(E) -> U,
+ {
+ match self {
+ Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
+ Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
+ Poll::Ready(None) => Poll::Ready(None),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T> const From<T> for Poll<T> {
+ /// Moves the value into a [`Poll::Ready`] to make a `Poll<T>`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use core::task::Poll;
+ /// assert_eq!(Poll::from(true), Poll::Ready(true));
+ /// ```
+ fn from(t: T) -> Poll<T> {
+ Poll::Ready(t)
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E> ops::Try for Poll<Result<T, E>> {
+ type Output = Poll<T>;
+ type Residual = Result<convert::Infallible, E>;
+
+ #[inline]
+ fn from_output(c: Self::Output) -> Self {
+ c.map(Ok)
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
+ Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
+ Poll::Pending => ControlFlow::Continue(Poll::Pending),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
+ #[inline]
+ fn from_residual(x: Result<convert::Infallible, E>) -> Self {
+ match x {
+ Err(e) => Poll::Ready(Err(From::from(e))),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
+ type Output = Poll<Option<T>>;
+ type Residual = Result<convert::Infallible, E>;
+
+ #[inline]
+ fn from_output(c: Self::Output) -> Self {
+ c.map(|x| x.map(Ok))
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
+ Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
+ Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
+ Poll::Pending => ControlFlow::Continue(Poll::Pending),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
+ for Poll<Option<Result<T, F>>>
+{
+ #[inline]
+ fn from_residual(x: Result<convert::Infallible, E>) -> Self {
+ match x {
+ Err(e) => Poll::Ready(Some(Err(From::from(e)))),
+ }
+ }
+}
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
new file mode 100644
index 000000000..b1daf545f
--- /dev/null
+++ b/library/core/src/task/ready.rs
@@ -0,0 +1,114 @@
+use core::convert;
+use core::fmt;
+use core::ops::{ControlFlow, FromResidual, Try};
+use core::task::Poll;
+
+/// Extracts the successful type of a [`Poll<T>`].
+///
+/// This macro bakes in propagation of [`Pending`] signals by returning early.
+///
+/// [`Poll<T>`]: crate::task::Poll
+/// [`Pending`]: crate::task::Poll::Pending
+///
+/// # Examples
+///
+/// ```
+/// use std::task::{ready, Context, Poll};
+/// use std::future::{self, Future};
+/// use std::pin::Pin;
+///
+/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+/// let mut fut = future::ready(42);
+/// let fut = Pin::new(&mut fut);
+///
+/// let num = ready!(fut.poll(cx));
+/// # drop(num);
+/// // ... use num
+///
+/// Poll::Ready(())
+/// }
+/// ```
+///
+/// The `ready!` call expands to:
+///
+/// ```
+/// # use std::task::{Context, Poll};
+/// # use std::future::{self, Future};
+/// # use std::pin::Pin;
+/// #
+/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+/// # let mut fut = future::ready(42);
+/// # let fut = Pin::new(&mut fut);
+/// #
+/// let num = match fut.poll(cx) {
+/// Poll::Ready(t) => t,
+/// Poll::Pending => return Poll::Pending,
+/// };
+/// # drop(num);
+/// # // ... use num
+/// #
+/// # Poll::Ready(())
+/// # }
+/// ```
+#[stable(feature = "ready_macro", since = "1.64.0")]
+#[rustc_macro_transparency = "semitransparent"]
+pub macro ready($e:expr) {
+ match $e {
+ $crate::task::Poll::Ready(t) => t,
+ $crate::task::Poll::Pending => {
+ return $crate::task::Poll::Pending;
+ }
+ }
+}
+
+/// Extracts the successful type of a [`Poll<T>`].
+///
+/// See [`Poll::ready`] for details.
+#[unstable(feature = "poll_ready", issue = "89780")]
+pub struct Ready<T>(pub(crate) Poll<T>);
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> Try for Ready<T> {
+ type Output = T;
+ type Residual = Ready<convert::Infallible>;
+
+ #[inline]
+ fn from_output(output: Self::Output) -> Self {
+ Ready(Poll::Ready(output))
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self.0 {
+ Poll::Ready(v) => ControlFlow::Continue(v),
+ Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
+ }
+ }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> FromResidual for Ready<T> {
+ #[inline]
+ fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+ match residual.0 {
+ Poll::Pending => Ready(Poll::Pending),
+ }
+ }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
+ #[inline]
+ fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+ match residual.0 {
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> fmt::Debug for Ready<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Ready").finish()
+ }
+}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
new file mode 100644
index 000000000..87d4a25af
--- /dev/null
+++ b/library/core/src/task/wake.rs
@@ -0,0 +1,334 @@
+#![stable(feature = "futures_api", since = "1.36.0")]
+
+use crate::fmt;
+use crate::marker::{PhantomData, Unpin};
+
+/// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
+/// which provides customized wakeup behavior.
+///
+/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table
+///
+/// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable]
+/// that customizes the behavior of the `RawWaker`.
+#[derive(PartialEq, Debug)]
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub struct RawWaker {
+ /// A data pointer, which can be used to store arbitrary data as required
+ /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
+ /// that is associated with the task.
+ /// The value of this field gets passed to all functions that are part of
+ /// the vtable as the first parameter.
+ data: *const (),
+ /// Virtual function pointer table that customizes the behavior of this waker.
+ vtable: &'static RawWakerVTable,
+}
+
+impl RawWaker {
+ /// Creates a new `RawWaker` from the provided `data` pointer and `vtable`.
+ ///
+ /// The `data` pointer can be used to store arbitrary data as required
+ /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
+ /// that is associated with the task.
+ /// The value of this pointer will get passed to all functions that are part
+ /// of the `vtable` as the first parameter.
+ ///
+ /// The `vtable` customizes the behavior of a `Waker` which gets created
+ /// from a `RawWaker`. For each operation on the `Waker`, the associated
+ /// function in the `vtable` of the underlying `RawWaker` will be called.
+ #[inline]
+ #[rustc_promotable]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ #[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
+ #[must_use]
+ pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
+ RawWaker { data, vtable }
+ }
+
+ /// Get the `data` pointer used to create this `RawWaker`.
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "waker_getters", issue = "87021")]
+ 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")]
+ pub fn vtable(&self) -> &'static RawWakerVTable {
+ self.vtable
+ }
+}
+
+/// A virtual function pointer table (vtable) that specifies the behavior
+/// of a [`RawWaker`].
+///
+/// The pointer passed to all functions inside the vtable is the `data` pointer
+/// from the enclosing [`RawWaker`] object.
+///
+/// The functions inside this struct are only intended to be called on the `data`
+/// 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.
+#[stable(feature = "futures_api", since = "1.36.0")]
+#[derive(PartialEq, Copy, Clone, Debug)]
+pub struct RawWakerVTable {
+ /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
+ /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned.
+ ///
+ /// The implementation of this function must retain all resources that are
+ /// required for this additional instance of a [`RawWaker`] and associated
+ /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
+ /// of the same task that would have been awoken by the original [`RawWaker`].
+ clone: unsafe fn(*const ()) -> RawWaker,
+
+ /// This function will be called when `wake` is called on the [`Waker`].
+ /// It must wake up the task associated with this [`RawWaker`].
+ ///
+ /// The implementation of this function must make sure to release any
+ /// resources that are associated with this instance of a [`RawWaker`] and
+ /// associated task.
+ wake: unsafe fn(*const ()),
+
+ /// This function will be called when `wake_by_ref` is called on the [`Waker`].
+ /// It must wake up the task associated with this [`RawWaker`].
+ ///
+ /// This function is similar to `wake`, but must not consume the provided data
+ /// pointer.
+ wake_by_ref: unsafe fn(*const ()),
+
+ /// This function gets called when a [`RawWaker`] gets dropped.
+ ///
+ /// The implementation of this function must make sure to release any
+ /// resources that are associated with this instance of a [`RawWaker`] and
+ /// associated task.
+ drop: unsafe fn(*const ()),
+}
+
+impl RawWakerVTable {
+ /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
+ /// `wake_by_ref`, and `drop` functions.
+ ///
+ /// # `clone`
+ ///
+ /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
+ /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned.
+ ///
+ /// The implementation of this function must retain all resources that are
+ /// required for this additional instance of a [`RawWaker`] and associated
+ /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
+ /// of the same task that would have been awoken by the original [`RawWaker`].
+ ///
+ /// # `wake`
+ ///
+ /// This function will be called when `wake` is called on the [`Waker`].
+ /// It must wake up the task associated with this [`RawWaker`].
+ ///
+ /// The implementation of this function must make sure to release any
+ /// resources that are associated with this instance of a [`RawWaker`] and
+ /// associated task.
+ ///
+ /// # `wake_by_ref`
+ ///
+ /// This function will be called when `wake_by_ref` is called on the [`Waker`].
+ /// It must wake up the task associated with this [`RawWaker`].
+ ///
+ /// This function is similar to `wake`, but must not consume the provided data
+ /// pointer.
+ ///
+ /// # `drop`
+ ///
+ /// This function gets called when a [`RawWaker`] gets dropped.
+ ///
+ /// The implementation of this function must make sure to release any
+ /// resources that are associated with this instance of a [`RawWaker`] and
+ /// associated task.
+ #[rustc_promotable]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ #[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
+ pub const fn new(
+ clone: unsafe fn(*const ()) -> RawWaker,
+ wake: unsafe fn(*const ()),
+ wake_by_ref: unsafe fn(*const ()),
+ drop: unsafe fn(*const ()),
+ ) -> Self {
+ Self { clone, wake, wake_by_ref, drop }
+ }
+}
+
+/// The `Context` of an asynchronous task.
+///
+/// Currently, `Context` only serves to provide access to a `&Waker`
+/// which can be used to wake the current task.
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub struct Context<'a> {
+ waker: &'a Waker,
+ // Ensure we future-proof against variance changes by forcing
+ // the lifetime to be invariant (argument-position lifetimes
+ // are contravariant while return-position lifetimes are
+ // covariant).
+ _marker: PhantomData<fn(&'a ()) -> &'a ()>,
+}
+
+impl<'a> Context<'a> {
+ /// Create a new `Context` from a `&Waker`.
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ #[must_use]
+ #[inline]
+ pub fn from_waker(waker: &'a Waker) -> Self {
+ Context { waker, _marker: PhantomData }
+ }
+
+ /// Returns a reference to the `Waker` for the current task.
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ #[must_use]
+ #[inline]
+ pub fn waker(&self) -> &'a Waker {
+ &self.waker
+ }
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+impl fmt::Debug for Context<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Context").field("waker", &self.waker).finish()
+ }
+}
+
+/// A `Waker` is a handle for waking up a task by notifying its executor that it
+/// is ready to be run.
+///
+/// This handle encapsulates a [`RawWaker`] instance, which defines the
+/// executor-specific wakeup behavior.
+///
+/// Implements [`Clone`], [`Send`], and [`Sync`].
+#[repr(transparent)]
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub struct Waker {
+ waker: RawWaker,
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+impl Unpin for Waker {}
+#[stable(feature = "futures_api", since = "1.36.0")]
+unsafe impl Send for Waker {}
+#[stable(feature = "futures_api", since = "1.36.0")]
+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
+ /// 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.
+ ///
+ /// 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.
+ #[inline]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn wake(self) {
+ // The actual wakeup call is delegated through a virtual function call
+ // to the implementation which is defined by the executor.
+ let wake = self.waker.vtable.wake;
+ let data = self.waker.data;
+
+ // Don't call `drop` -- the waker will be consumed by `wake`.
+ crate::mem::forget(self);
+
+ // SAFETY: This is safe because `Waker::from_raw` is the only way
+ // to initialize `wake` and `data` requiring the user to acknowledge
+ // that the contract of `RawWaker` is upheld.
+ unsafe { (wake)(data) };
+ }
+
+ /// 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
+ /// calling `waker.clone().wake()`.
+ #[inline]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn wake_by_ref(&self) {
+ // The actual wakeup call is delegated through a virtual function call
+ // to the implementation which is defined by the executor.
+
+ // SAFETY: see `wake`
+ unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
+ }
+
+ /// Returns `true` if this `Waker` and another `Waker` have awoken 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.
+ #[inline]
+ #[must_use]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub fn will_wake(&self, other: &Waker) -> bool {
+ self.waker == other.waker
+ }
+
+ /// Creates a new `Waker` from [`RawWaker`].
+ ///
+ /// The behavior of the returned `Waker` is undefined if the contract defined
+ /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
+ /// Therefore this method is unsafe.
+ #[inline]
+ #[must_use]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub unsafe fn from_raw(waker: RawWaker) -> Waker {
+ Waker { waker }
+ }
+
+ /// Get a reference to the underlying [`RawWaker`].
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "waker_getters", issue = "87021")]
+ pub fn as_raw(&self) -> &RawWaker {
+ &self.waker
+ }
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+impl Clone for Waker {
+ #[inline]
+ fn clone(&self) -> Self {
+ Waker {
+ // SAFETY: This is safe because `Waker::from_raw` is the only way
+ // to initialize `clone` and `data` requiring the user to acknowledge
+ // that the contract of [`RawWaker`] is upheld.
+ waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
+ }
+ }
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+impl Drop for Waker {
+ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: This is safe because `Waker::from_raw` is the only way
+ // to initialize `drop` and `data` requiring the user to acknowledge
+ // that the contract of `RawWaker` is upheld.
+ unsafe { (self.waker.vtable.drop)(self.waker.data) }
+ }
+}
+
+#[stable(feature = "futures_api", since = "1.36.0")]
+impl fmt::Debug for Waker {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
+ f.debug_struct("Waker")
+ .field("data", &self.waker.data)
+ .field("vtable", &vtable_ptr)
+ .finish()
+ }
+}