futures_core/task/
wake.rs

1use core::fmt;
2
3/// An unsafe trait for implementing custom memory management for a
4/// [`Waker`](::task::Waker).
5///
6/// A [`Waker`](::task::Waker) is a cloneable trait object for `Wake`, and is
7/// most often essentially just `Arc<Wake>`. However, in some contexts
8/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
9/// custom memory management strategy. This trait is designed to allow for such
10/// customization.
11///
12/// A default implementation of the `UnsafeWake` trait is provided for the
13/// `Arc` type in the standard library. If the `std` feature of this crate
14/// is not available however, you'll be required to implement your own
15/// instance of this trait to pass it into `Waker::new`.
16///
17/// # Unsafety
18///
19/// This trait manually encodes the memory management of the underlying trait
20/// object. Implementors of this trait must guarantee:
21///
22/// * Calls to `clone_raw` produce uniquely owned `Waker` handles. These handles
23/// should be independently usable and droppable.
24///
25/// * Calls to `drop_raw` work with `self` as a raw pointer, deallocating
26///   resources associated with it. This is a pretty unsafe operation as it's
27///   invalidating the `self` pointer, so extreme care needs to be taken.
28///
29/// In general it's recommended to review the trait documentation as well as the
30/// implementation for `Arc` in this crate before attempting a custom
31/// implementation.
32pub unsafe trait UnsafeWake {
33    /// Creates a new `Waker` from this instance of `UnsafeWake`.
34    ///
35    /// This function will create a new uniquely owned handle that under the
36    /// hood references the same notification instance. In other words calls
37    /// to `wake` on the returned handle should be equivalent to calls to
38    /// `wake` on this handle.
39    ///
40    /// # Unsafety
41    ///
42    /// This is also unsafe to call because it's asserting the `UnsafeWake`
43    /// value is in a consistent state, i.e. hasn't been dropped.
44    unsafe fn clone_raw(&self) -> Waker;
45
46    /// Drops this instance of `UnsafeWake`, deallocating resources
47    /// associated with it.
48    ///
49    /// This method is intended to have a signature such as:
50    ///
51    /// ```ignore
52    /// fn drop_raw(self: *mut Self);
53    /// ```
54    ///
55    /// Unfortunately in Rust today that signature is not object safe.
56    /// Nevertheless it's recommended to implement this function *as if* that
57    /// were its signature. As such it is not safe to call on an invalid
58    /// pointer, nor is the validity of the pointer guaranteed after this
59    /// function returns.
60    ///
61    /// # Unsafety
62    ///
63    /// This is also unsafe to call because it's asserting the `UnsafeWake`
64    /// value is in a consistent state, i.e. hasn't been dropped
65    unsafe fn drop_raw(&self);
66
67    /// Indicates that the associated task is ready to make progress and should
68    /// be `poll`ed.
69    ///
70    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
71    /// the associated task onto this queue.
72    ///
73    /// # Panics
74    ///
75    /// Implementations should avoid panicking, but clients should also be prepared
76    /// for panics.
77    ///
78    /// # Unsafety
79    ///
80    /// This is also unsafe to call because it's asserting the `UnsafeWake`
81    /// value is in a consistent state, i.e. hasn't been dropped
82    unsafe fn wake(&self);
83}
84
85/// A `Waker` is a handle for waking up a task by notifying its executor that it
86/// is ready to be run.
87///
88/// This handle contains a trait object pointing to an instance of the `Wake`
89/// trait, allowing notifications to get routed through it. Usually `Waker`
90/// instances are provided by an executor.
91///
92/// If you're implementing an executor, the recommended way to create a `Waker`
93/// is via `Waker::from` applied to an `Arc<T>` value where `T: Wake`. The
94/// unsafe `new` constructor should be used only in niche, `no_std` settings.
95pub struct Waker {
96    inner: *const UnsafeWake,
97}
98
99unsafe impl Send for Waker {}
100unsafe impl Sync for Waker {}
101
102impl Waker {
103    /// Constructs a new `Waker` directly.
104    ///
105    /// Note that most code will not need to call this. Implementers of the
106    /// `UnsafeWake` trait will typically provide a wrapper that calls this
107    /// but you otherwise shouldn't call it directly.
108    ///
109    /// If you're working with the standard library then it's recommended to
110    /// use the `Waker::from` function instead which works with the safe
111    /// `Arc` type and the safe `Wake` trait.
112    #[inline]
113    pub unsafe fn new(inner: *const UnsafeWake) -> Waker {
114        Waker { inner: inner }
115    }
116
117    /// Wake up the task associated with this `Waker`.
118    pub fn wake(&self) {
119        unsafe { (*self.inner).wake() }
120    }
121
122    /// Returns whether or not this `Waker` and `other` awaken the same task.
123    ///
124    /// This function works on a best-effort basis, and may return false even
125    /// when the `Waker`s would awaken the same task. However, if this function
126    /// returns true, it is guaranteed that the `Waker`s will awaken the same
127    /// task.
128    ///
129    /// This function is primarily used for optimization purposes.
130    pub fn will_wake(&self, other: &Waker) -> bool {
131        self.inner == other.inner
132    }
133}
134
135impl Clone for Waker {
136    #[inline]
137    fn clone(&self) -> Self {
138        unsafe {
139            (*self.inner).clone_raw()
140        }
141    }
142}
143
144impl fmt::Debug for Waker {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        f.debug_struct("Waker")
147            .finish()
148    }
149}
150
151impl Drop for Waker {
152    fn drop(&mut self) {
153        unsafe {
154            (*self.inner).drop_raw()
155        }
156    }
157}
158
159if_std! {
160    use std::mem;
161    use std::ptr;
162    use std::sync::Arc;
163    use core::marker::PhantomData;
164
165    /// A way of waking up a specific task.
166    ///
167    /// Any task executor must provide a way of signaling that a task it owns
168    /// is ready to be `poll`ed again. Executors do so by implementing this trait.
169    ///
170    /// Note that, rather than working directly with `Wake` trait objects, this
171    /// library instead uses a custom [`Waker`](::task::Waker) to allow for
172    /// customization of memory management.
173    pub trait Wake: Send + Sync {
174        /// Indicates that the associated task is ready to make progress and should
175        /// be `poll`ed.
176        ///
177        /// Executors generally maintain a queue of "ready" tasks; `wake` should place
178        /// the associated task onto this queue.
179        ///
180        /// # Panics
181        ///
182        /// Implementations should avoid panicking, but clients should also be prepared
183        /// for panics.
184        fn wake(arc_self: &Arc<Self>);
185    }
186
187    // Safe implementation of `UnsafeWake` for `Arc` in the standard library.
188    //
189    // Note that this is a very unsafe implementation! The crucial pieces is that
190    // these two values are considered equivalent:
191    //
192    // * Arc<T>
193    // * *const ArcWrapped<T>
194    //
195    // We don't actually know the layout of `ArcWrapped<T>` as it's an
196    // implementation detail in the standard library. We can work, though, by
197    // casting it through and back an `Arc<T>`.
198    //
199    // This also means that you won't actually find `UnsafeWake for Arc<T>`
200    // because it's the wrong level of indirection. These methods are sort of
201    // receiving Arc<T>, but not an owned version. It's... complicated. We may be
202    // one of the first users of unsafe trait objects!
203
204    struct ArcWrapped<T>(PhantomData<T>);
205
206    unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
207        unsafe fn clone_raw(&self) -> Waker {
208            let me: *const ArcWrapped<T> = self;
209            let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
210            Waker::from(arc)
211        }
212
213        unsafe fn drop_raw(&self) {
214            let mut me: *const ArcWrapped<T> = self;
215            let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
216            ptr::drop_in_place(me);
217        }
218
219        unsafe fn wake(&self) {
220            let me: *const ArcWrapped<T> = self;
221            T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
222        }
223    }
224
225    impl<T> From<Arc<T>> for Waker
226        where T: Wake + 'static,
227    {
228        fn from(rc: Arc<T>) -> Waker {
229            unsafe {
230                let ptr = mem::transmute::<Arc<T>, *const ArcWrapped<T>>(rc);
231                Waker::new(ptr)
232            }
233        }
234    }
235}