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}