| #![stable(feature = "futures_api", since = "1.36.0")] | |
| use crate::any::Any; | |
| use crate::marker::PhantomData; | |
| use crate::mem::{ManuallyDrop, transmute}; | |
| use crate::panic::AssertUnwindSafe; | |
| use crate::{fmt, ptr}; | |
| /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] | |
| /// or a [`LocalWaker`] which provides customized wakeup behavior. | |
| /// | |
| /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] | |
| /// that customizes the behavior of the `RawWaker`. | |
| /// | |
| /// `RawWaker`s are unsafe to use. | |
| /// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. | |
| /// | |
| /// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table | |
| /// [`Wake`]: ../../alloc/task/trait.Wake.html | |
| #[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. | |
| /// | |
| /// It is important to consider that the `data` pointer must point to a | |
| /// thread safe type such as an `Arc<T: Send + Sync>` | |
| /// when used to construct a [`Waker`]. This restriction is lifted when | |
| /// constructing a [`LocalWaker`], which allows using types that do not implement | |
| /// <code>[Send] + [Sync]</code> like `Rc<T>`. | |
| /// | |
| /// 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 } | |
| } | |
| #[stable(feature = "noop_waker", since = "1.85.0")] | |
| const NOOP: RawWaker = { | |
| const VTABLE: RawWakerVTable = RawWakerVTable::new( | |
| // Cloning just returns a new no-op raw waker | |
| |_| RawWaker::NOOP, | |
| // `wake` does nothing | |
| |_| {}, | |
| // `wake_by_ref` does nothing | |
| |_| {}, | |
| // Dropping does nothing as we don't allocate anything | |
| |_| {}, | |
| ); | |
| RawWaker::new(ptr::null(), &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. | |
| /// | |
| /// Note that while this type implements `PartialEq`, comparing function pointers, and hence | |
| /// comparing structs like this that contain function pointers, is unreliable: pointers to the same | |
| /// function can compare inequal (because functions are duplicated in multiple codegen units), and | |
| /// pointers to *different* functions can compare equal (since identical functions can be | |
| /// deduplicated within a codegen unit). | |
| /// | |
| /// # Thread safety | |
| /// If the [`RawWaker`] will be used to construct a [`Waker`] then | |
| /// these functions must all be thread-safe (even though [`RawWaker`] is | |
| /// <code>\![Send] + \![Sync]</code>). This is because [`Waker`] is <code>[Send] + [Sync]</code>, | |
| /// and it 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. | |
| /// | |
| /// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then | |
| /// these functions don't need to be thread safe. This means that <code>\![Send] + \![Sync]</code> | |
| /// data can be stored in the data pointer, and reference counting does not need any atomic | |
| /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot | |
| /// be sent across threads. | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[allow(unpredictable_function_pointer_comparisons)] | |
| #[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 will be 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 | |
| /// associated task. | |
| drop: unsafe fn(*const ()), | |
| } | |
| impl RawWakerVTable { | |
| /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, | |
| /// `wake_by_ref`, and `drop` functions. | |
| /// | |
| /// If the [`RawWaker`] will be used to construct a [`Waker`] then | |
| /// these functions must all be thread-safe (even though [`RawWaker`] is | |
| /// <code>\![Send] + \![Sync]</code>). This is because [`Waker`] is <code>[Send] + [Sync]</code>, | |
| /// and it 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. | |
| /// | |
| /// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then | |
| /// these functions don't need to be thread safe. This means that <code>\![Send] + \![Sync]</code> | |
| /// data can be stored in the data pointer, and reference counting does not need any atomic | |
| /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot | |
| /// be sent across threads. | |
| /// # `clone` | |
| /// | |
| /// This function will be called when the [`RawWaker`] gets cloned, e.g. when | |
| /// the [`Waker`]/[`LocalWaker`] 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 will be called when a [`Waker`]/[`LocalWaker`] 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 } | |
| } | |
| } | |
| #[derive(Debug)] | |
| enum ExtData<'a> { | |
| Some(&'a mut dyn Any), | |
| None(()), | |
| } | |
| /// The context of an asynchronous task. | |
| /// | |
| /// 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, | |
| local_waker: &'a LocalWaker, | |
| ext: AssertUnwindSafe<ExtData<'a>>, | |
| // 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 ()>, | |
| // Ensure `Context` is `!Send` and `!Sync` in order to allow | |
| // for future `!Send` and / or `!Sync` fields. | |
| _marker2: PhantomData<*mut ()>, | |
| } | |
| impl<'a> Context<'a> { | |
| /// Creates a new `Context` from a [`&Waker`](Waker). | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] | |
| #[must_use] | |
| #[inline] | |
| pub const fn from_waker(waker: &'a Waker) -> Self { | |
| ContextBuilder::from_waker(waker).build() | |
| } | |
| /// Returns a reference to the [`Waker`] for the current task. | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] | |
| pub const fn waker(&self) -> &'a Waker { | |
| self.waker | |
| } | |
| /// Returns a reference to the [`LocalWaker`] for the current task. | |
| #[inline] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const fn local_waker(&self) -> &'a LocalWaker { | |
| self.local_waker | |
| } | |
| /// Returns a reference to the extension data for the current task. | |
| #[inline] | |
| #[unstable(feature = "context_ext", issue = "123392")] | |
| pub const fn ext(&mut self) -> &mut dyn Any { | |
| // FIXME: this field makes Context extra-weird about unwind safety | |
| // can we justify AssertUnwindSafe if we stabilize this? do we care? | |
| match &mut self.ext.0 { | |
| ExtData::Some(data) => *data, | |
| ExtData::None(unit) => unit, | |
| } | |
| } | |
| } | |
| #[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 Builder used to construct a `Context` instance | |
| /// with support for `LocalWaker`. | |
| /// | |
| /// # Examples | |
| /// ``` | |
| /// #![feature(local_waker)] | |
| /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; | |
| /// use std::future::Future; | |
| /// | |
| /// let local_waker = LocalWaker::noop(); | |
| /// let waker = Waker::noop(); | |
| /// | |
| /// let mut cx = ContextBuilder::from_waker(&waker) | |
| /// .local_waker(&local_waker) | |
| /// .build(); | |
| /// | |
| /// let mut future = std::pin::pin!(async { 20 }); | |
| /// let poll = future.as_mut().poll(&mut cx); | |
| /// assert_eq!(poll, Poll::Ready(20)); | |
| /// | |
| /// ``` | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| #[derive(Debug)] | |
| pub struct ContextBuilder<'a> { | |
| waker: &'a Waker, | |
| local_waker: &'a LocalWaker, | |
| ext: ExtData<'a>, | |
| // 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 ()>, | |
| // Ensure `Context` is `!Send` and `!Sync` in order to allow | |
| // for future `!Send` and / or `!Sync` fields. | |
| _marker2: PhantomData<*mut ()>, | |
| } | |
| impl<'a> ContextBuilder<'a> { | |
| /// Creates a ContextBuilder from a Waker. | |
| #[inline] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const fn from_waker(waker: &'a Waker) -> Self { | |
| // SAFETY: LocalWaker is just Waker without thread safety | |
| let local_waker = unsafe { transmute(waker) }; | |
| Self { | |
| waker, | |
| local_waker, | |
| ext: ExtData::None(()), | |
| _marker: PhantomData, | |
| _marker2: PhantomData, | |
| } | |
| } | |
| /// Creates a ContextBuilder from an existing Context. | |
| #[inline] | |
| #[unstable(feature = "context_ext", issue = "123392")] | |
| pub const fn from(cx: &'a mut Context<'_>) -> Self { | |
| let ext = match &mut cx.ext.0 { | |
| ExtData::Some(ext) => ExtData::Some(*ext), | |
| ExtData::None(()) => ExtData::None(()), | |
| }; | |
| Self { | |
| waker: cx.waker, | |
| local_waker: cx.local_waker, | |
| ext, | |
| _marker: PhantomData, | |
| _marker2: PhantomData, | |
| } | |
| } | |
| /// Sets the value for the waker on `Context`. | |
| #[inline] | |
| #[unstable(feature = "context_ext", issue = "123392")] | |
| pub const fn waker(self, waker: &'a Waker) -> Self { | |
| Self { waker, ..self } | |
| } | |
| /// Sets the value for the local waker on `Context`. | |
| #[inline] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { | |
| Self { local_waker, ..self } | |
| } | |
| /// Sets the value for the extension data on `Context`. | |
| #[inline] | |
| #[unstable(feature = "context_ext", issue = "123392")] | |
| pub const fn ext(self, data: &'a mut dyn Any) -> Self { | |
| Self { ext: ExtData::Some(data), ..self } | |
| } | |
| /// Builds the `Context`. | |
| #[inline] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const fn build(self) -> Context<'a> { | |
| let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; | |
| Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } | |
| } | |
| } | |
| /// 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. | |
| /// | |
| /// 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). | |
| /// | |
| /// Constructing a `Waker` from a [`RawWaker`] is unsafe. | |
| /// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. | |
| /// | |
| /// [`Future::poll()`]: core::future::Future::poll | |
| /// [`Poll::Pending`]: core::task::Poll::Pending | |
| /// [`Wake`]: ../../alloc/task/trait.Wake.html | |
| #[repr(transparent)] | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[rustc_diagnostic_item = "Waker"] | |
| 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 { | |
| /// Wakes up the task associated with this `Waker`. | |
| /// | |
| /// 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, such that the call to | |
| /// [`wake()`](Self::wake) (or [`wake_by_ref()`](Self::wake_by_ref)) _happens-before_ | |
| /// the beginning of the invocation of [`poll()`]. 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 executor. | |
| /// | |
| /// 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) { | |
| // The actual wakeup call is delegated through a virtual function call | |
| // to the implementation which is defined by the executor. | |
| // Don't call `drop` -- the waker will be consumed by `wake`. | |
| let this = ManuallyDrop::new(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 { (this.waker.vtable.wake)(this.waker.data) }; | |
| } | |
| /// Wakes up the task associated with this `Waker` without consuming the `Waker`. | |
| /// | |
| /// 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")] | |
| 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` 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 — 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")] | |
| pub fn will_wake(&self, other: &Waker) -> bool { | |
| // We optimize this by comparing vtable addresses instead of vtable contents. | |
| // This is permitted since the function is documented as best-effort. | |
| let RawWaker { data: a_data, vtable: a_vtable } = self.waker; | |
| let RawWaker { data: b_data, vtable: b_vtable } = other.waker; | |
| a_data == b_data && ptr::eq(a_vtable, b_vtable) | |
| } | |
| /// Creates a new `Waker` 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. | |
| /// | |
| /// It is important to consider that the `data` pointer must point to a | |
| /// thread safe type such as an `Arc`. | |
| /// | |
| /// The `vtable` customizes the behavior of a `Waker`. For each operation | |
| /// on the `Waker`, the associated function in the `vtable` will be called. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The behavior of the returned `Waker` is undefined if the contract defined | |
| /// in [`RawWakerVTable`]'s documentation is not upheld. | |
| /// | |
| /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the | |
| /// cost of a required heap allocation.) | |
| /// | |
| /// [`Wake`]: ../../alloc/task/trait.Wake.html | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "waker_getters", since = "1.83.0")] | |
| #[rustc_const_stable(feature = "waker_getters", since = "1.83.0")] | |
| pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { | |
| Waker { waker: RawWaker { data, vtable } } | |
| } | |
| /// Creates a new `Waker` from [`RawWaker`]. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The behavior of the returned `Waker` is undefined if the contract defined | |
| /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. | |
| /// | |
| /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the | |
| /// cost of a required heap allocation.) | |
| /// | |
| /// [`Wake`]: ../../alloc/task/trait.Wake.html | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "futures_api", since = "1.36.0")] | |
| #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] | |
| pub const unsafe fn from_raw(waker: RawWaker) -> Waker { | |
| Waker { waker } | |
| } | |
| /// Returns a reference to a `Waker` that does nothing when used. | |
| /// | |
| // Note! Much of the documentation for this method is duplicated | |
| // in the docs for `LocalWaker::noop`. | |
| // If you edit it, consider editing the other copy too. | |
| // | |
| /// 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. | |
| /// | |
| /// More generally, using `Waker::noop()` to poll a future | |
| /// means discarding the notification of when the future should be polled again. | |
| /// So it should only be used when such a notification will not be needed to make progress. | |
| /// | |
| /// If an owned `Waker` is needed, `clone()` this one. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::future::Future; | |
| /// use std::task; | |
| /// | |
| /// let mut cx = task::Context::from_waker(task::Waker::noop()); | |
| /// | |
| /// let mut future = Box::pin(async { 10 }); | |
| /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); | |
| /// ``` | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "noop_waker", since = "1.85.0")] | |
| #[rustc_const_stable(feature = "noop_waker", since = "1.85.0")] | |
| pub const fn noop() -> &'static Waker { | |
| const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; | |
| WAKER | |
| } | |
| /// Gets the `data` pointer used to create this `Waker`. | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "waker_getters", since = "1.83.0")] | |
| pub fn data(&self) -> *const () { | |
| self.waker.data | |
| } | |
| /// Gets the `vtable` pointer used to create this `Waker`. | |
| #[inline] | |
| #[must_use] | |
| #[stable(feature = "waker_getters", since = "1.83.0")] | |
| pub fn vtable(&self) -> &'static RawWakerVTable { | |
| self.waker.vtable | |
| } | |
| /// Constructs a `Waker` from a function pointer. | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "waker_from_fn_ptr", issue = "148457")] | |
| pub const fn from_fn_ptr(f: fn()) -> Self { | |
| // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it | |
| // is sound to transmute it back to `fn()`. | |
| static VTABLE: RawWakerVTable = unsafe { | |
| RawWakerVTable::new( | |
| |this| RawWaker::new(this, &VTABLE), | |
| |this| transmute::<*const (), fn()>(this)(), | |
| |this| transmute::<*const (), fn()>(this)(), | |
| |_| {}, | |
| ) | |
| }; | |
| let raw = RawWaker::new(f as *const (), &VTABLE); | |
| // SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and | |
| // `wake_by_ref` just call the function pointer. | |
| unsafe { Self::from_raw(raw) } | |
| } | |
| } | |
| #[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) }, | |
| } | |
| } | |
| /// Assigns a clone of `source` to `self`, unless [`self.will_wake(source)`][Waker::will_wake] anyway. | |
| /// | |
| /// This method is preferred over simply assigning `source.clone()` to `self`, | |
| /// as it avoids cloning the waker if `self` is already the same waker. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::future::Future; | |
| /// use std::pin::Pin; | |
| /// use std::sync::{Arc, Mutex}; | |
| /// use std::task::{Context, Poll, Waker}; | |
| /// | |
| /// struct Waiter { | |
| /// shared: Arc<Mutex<Shared>>, | |
| /// } | |
| /// | |
| /// struct Shared { | |
| /// waker: Waker, | |
| /// // ... | |
| /// } | |
| /// | |
| /// impl Future for Waiter { | |
| /// type Output = (); | |
| /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { | |
| /// let mut shared = self.shared.lock().unwrap(); | |
| /// | |
| /// // update the waker | |
| /// shared.waker.clone_from(cx.waker()); | |
| /// | |
| /// // readiness logic ... | |
| /// # Poll::Ready(()) | |
| /// } | |
| /// } | |
| /// | |
| /// ``` | |
| #[inline] | |
| fn clone_from(&mut self, source: &Self) { | |
| if !self.will_wake(source) { | |
| *self = source.clone(); | |
| } | |
| } | |
| } | |
| #[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() | |
| } | |
| } | |
| /// A `LocalWaker` is analogous to a [`Waker`], but it does not implement [`Send`] or [`Sync`]. | |
| /// | |
| /// This handle encapsulates a [`RawWaker`] instance, which defines the | |
| /// executor-specific wakeup behavior. | |
| /// | |
| /// Local wakers can be requested from a `Context` with the [`local_waker`] method. | |
| /// | |
| /// The typical life of a `LocalWaker` is that it is constructed by an executor, wrapped in a | |
| /// [`Context`] using [`ContextBuilder`], then passed to [`Future::poll()`]. Then, if the future chooses to return | |
| /// [`Poll::Pending`], it must also store the waker somehow and call [`LocalWaker::wake()`] when | |
| /// the future should be polled again. | |
| /// | |
| /// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may | |
| /// not be moved to other threads. In general, when deciding to use wakers or local wakers, | |
| /// local wakers are preferable unless the waker needs to be sent across threads. This is because | |
| /// wakers can incur in additional cost related to memory synchronization. | |
| /// | |
| /// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead | |
| /// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker | |
| /// unnecessarily if the two wakers [wake the same task](Self::will_wake). | |
| /// | |
| /// # Examples | |
| /// Usage of a local waker to implement a future analogous to `std::thread::yield_now()`. | |
| /// ``` | |
| /// #![feature(local_waker)] | |
| /// use std::future::{Future, poll_fn}; | |
| /// use std::task::Poll; | |
| /// | |
| /// // a future that returns pending once. | |
| /// fn yield_now() -> impl Future<Output=()> + Unpin { | |
| /// let mut yielded = false; | |
| /// poll_fn(move |cx| { | |
| /// if !yielded { | |
| /// yielded = true; | |
| /// cx.local_waker().wake_by_ref(); | |
| /// return Poll::Pending; | |
| /// } | |
| /// return Poll::Ready(()) | |
| /// }) | |
| /// } | |
| /// | |
| /// # async fn __() { | |
| /// yield_now().await; | |
| /// # } | |
| /// ``` | |
| /// | |
| /// [`Future::poll()`]: core::future::Future::poll | |
| /// [`Poll::Pending`]: core::task::Poll::Pending | |
| /// [`local_waker`]: core::task::Context::local_waker | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| #[repr(transparent)] | |
| pub struct LocalWaker { | |
| waker: RawWaker, | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl Unpin for LocalWaker {} | |
| impl LocalWaker { | |
| /// Wakes up the task associated with this `LocalWaker`. | |
| /// | |
| /// 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 `LocalWaker` 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. | |
| /// | |
| /// [`poll()`]: crate::future::Future::poll | |
| #[inline] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub fn wake(self) { | |
| // The actual wakeup call is delegated through a virtual function call | |
| // to the implementation which is defined by the executor. | |
| // Don't call `drop` -- the waker will be consumed by `wake`. | |
| let this = ManuallyDrop::new(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 { (this.waker.vtable.wake)(this.waker.data) }; | |
| } | |
| /// Wakes up the task associated with this `LocalWaker` without consuming the `LocalWaker`. | |
| /// | |
| /// 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] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| 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 `LocalWaker` and another `LocalWaker` 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 — 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] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub fn will_wake(&self, other: &LocalWaker) -> bool { | |
| // We optimize this by comparing vtable addresses instead of vtable contents. | |
| // This is permitted since the function is documented as best-effort. | |
| let RawWaker { data: a_data, vtable: a_vtable } = self.waker; | |
| let RawWaker { data: b_data, vtable: b_vtable } = other.waker; | |
| a_data == b_data && ptr::eq(a_vtable, b_vtable) | |
| } | |
| /// Creates a new `LocalWaker` 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 `LocalWaker`. For each | |
| /// operation on the `LocalWaker`, the associated function in the `vtable` | |
| /// will be called. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The behavior of the returned `Waker` is undefined if the contract defined | |
| /// in [`RawWakerVTable`]'s documentation is not upheld. | |
| /// | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { | |
| LocalWaker { waker: RawWaker { data, vtable } } | |
| } | |
| /// Creates a new `LocalWaker` from [`RawWaker`]. | |
| /// | |
| /// The behavior of the returned `LocalWaker` is undefined if the contract defined | |
| /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. | |
| /// Therefore this method is unsafe. | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { | |
| Self { waker } | |
| } | |
| /// Returns a reference to a `LocalWaker` that does nothing when used. | |
| /// | |
| // Note! Much of the documentation for this method is duplicated | |
| // in the docs for `Waker::noop`. | |
| // If you edit it, consider editing the other copy too. | |
| // | |
| /// 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. | |
| /// | |
| /// More generally, using `LocalWaker::noop()` to poll a future | |
| /// means discarding the notification of when the future should be polled again, | |
| /// So it should only be used when such a notification will not be needed to make progress. | |
| /// | |
| /// If an owned `LocalWaker` is needed, `clone()` this one. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(local_waker)] | |
| /// use std::future::Future; | |
| /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; | |
| /// | |
| /// let mut cx = ContextBuilder::from_waker(Waker::noop()) | |
| /// .local_waker(LocalWaker::noop()) | |
| /// .build(); | |
| /// | |
| /// let mut future = Box::pin(async { 10 }); | |
| /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(10)); | |
| /// ``` | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub const fn noop() -> &'static LocalWaker { | |
| const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP }; | |
| WAKER | |
| } | |
| /// Gets the `data` pointer used to create this `LocalWaker`. | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub fn data(&self) -> *const () { | |
| self.waker.data | |
| } | |
| /// Gets the `vtable` pointer used to create this `LocalWaker`. | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| pub fn vtable(&self) -> &'static RawWakerVTable { | |
| self.waker.vtable | |
| } | |
| /// Constructs a `LocalWaker` from a function pointer. | |
| #[inline] | |
| #[must_use] | |
| #[unstable(feature = "waker_from_fn_ptr", issue = "148457")] | |
| pub const fn from_fn_ptr(f: fn()) -> Self { | |
| // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it | |
| // is sound to transmute it back to `fn()`. | |
| static VTABLE: RawWakerVTable = unsafe { | |
| RawWakerVTable::new( | |
| |this| RawWaker::new(this, &VTABLE), | |
| |this| transmute::<*const (), fn()>(this)(), | |
| |this| transmute::<*const (), fn()>(this)(), | |
| |_| {}, | |
| ) | |
| }; | |
| let raw = RawWaker::new(f as *const (), &VTABLE); | |
| // SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and | |
| // `wake_by_ref` just call the function pointer. | |
| unsafe { Self::from_raw(raw) } | |
| } | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl Clone for LocalWaker { | |
| #[inline] | |
| fn clone(&self) -> Self { | |
| LocalWaker { | |
| // 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) }, | |
| } | |
| } | |
| #[inline] | |
| fn clone_from(&mut self, source: &Self) { | |
| if !self.will_wake(source) { | |
| *self = source.clone(); | |
| } | |
| } | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| #[rustc_const_unstable(feature = "const_convert", issue = "143773")] | |
| const impl AsRef<LocalWaker> for Waker { | |
| fn as_ref(&self) -> &LocalWaker { | |
| // SAFETY: LocalWaker is just Waker without thread safety | |
| unsafe { transmute(self) } | |
| } | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl Drop for LocalWaker { | |
| #[inline] | |
| fn drop(&mut self) { | |
| // SAFETY: This is safe because `LocalWaker::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) } | |
| } | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl fmt::Debug for LocalWaker { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| let vtable_ptr = self.waker.vtable as *const RawWakerVTable; | |
| f.debug_struct("LocalWaker") | |
| .field("data", &self.waker.data) | |
| .field("vtable", &vtable_ptr) | |
| .finish() | |
| } | |
| } | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl !Send for LocalWaker {} | |
| #[unstable(feature = "local_waker", issue = "118959")] | |
| impl !Sync for LocalWaker {} |