1 | #![stable (feature = "futures_api" , since = "1.36.0" )] |
2 | |
3 | use crate::fmt; |
4 | use crate::marker::PhantomData; |
5 | use crate::ptr; |
6 | |
7 | /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] |
8 | /// which provides customized wakeup behavior. |
9 | /// |
10 | /// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table |
11 | /// |
12 | /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] |
13 | /// that customizes the behavior of the `RawWaker`. |
14 | #[derive (PartialEq, Debug)] |
15 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
16 | pub struct RawWaker { |
17 | /// A data pointer, which can be used to store arbitrary data as required |
18 | /// by the executor. This could be e.g. a type-erased pointer to an `Arc` |
19 | /// that is associated with the task. |
20 | /// The value of this field gets passed to all functions that are part of |
21 | /// the vtable as the first parameter. |
22 | data: *const (), |
23 | /// Virtual function pointer table that customizes the behavior of this waker. |
24 | vtable: &'static RawWakerVTable, |
25 | } |
26 | |
27 | impl RawWaker { |
28 | /// Creates a new `RawWaker` from the provided `data` pointer and `vtable`. |
29 | /// |
30 | /// The `data` pointer can be used to store arbitrary data as required |
31 | /// by the executor. This could be e.g. a type-erased pointer to an `Arc` |
32 | /// that is associated with the task. |
33 | /// The value of this pointer will get passed to all functions that are part |
34 | /// of the `vtable` as the first parameter. |
35 | /// |
36 | /// The `vtable` customizes the behavior of a `Waker` which gets created |
37 | /// from a `RawWaker`. For each operation on the `Waker`, the associated |
38 | /// function in the `vtable` of the underlying `RawWaker` will be called. |
39 | #[inline ] |
40 | #[rustc_promotable ] |
41 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
42 | #[rustc_const_stable (feature = "futures_api" , since = "1.36.0" )] |
43 | #[must_use ] |
44 | pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker { |
45 | RawWaker { data, vtable } |
46 | } |
47 | |
48 | /// Get the `data` pointer used to create this `RawWaker`. |
49 | #[inline ] |
50 | #[must_use ] |
51 | #[unstable (feature = "waker_getters" , issue = "96992" )] |
52 | pub fn data(&self) -> *const () { |
53 | self.data |
54 | } |
55 | |
56 | /// Get the `vtable` pointer used to create this `RawWaker`. |
57 | #[inline ] |
58 | #[must_use ] |
59 | #[unstable (feature = "waker_getters" , issue = "96992" )] |
60 | pub fn vtable(&self) -> &'static RawWakerVTable { |
61 | self.vtable |
62 | } |
63 | } |
64 | |
65 | /// A virtual function pointer table (vtable) that specifies the behavior |
66 | /// of a [`RawWaker`]. |
67 | /// |
68 | /// The pointer passed to all functions inside the vtable is the `data` pointer |
69 | /// from the enclosing [`RawWaker`] object. |
70 | /// |
71 | /// The functions inside this struct are only intended to be called on the `data` |
72 | /// pointer of a properly constructed [`RawWaker`] object from inside the |
73 | /// [`RawWaker`] implementation. Calling one of the contained functions using |
74 | /// any other `data` pointer will cause undefined behavior. |
75 | /// |
76 | /// These functions must all be thread-safe (even though [`RawWaker`] is |
77 | /// <code>\![Send] + \![Sync]</code>) |
78 | /// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to |
79 | /// arbitrary threads or invoked by `&` reference. For example, this means that if the |
80 | /// `clone` and `drop` functions manage a reference count, they must do so atomically. |
81 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
82 | #[derive (PartialEq, Copy, Clone, Debug)] |
83 | pub struct RawWakerVTable { |
84 | /// This function will be called when the [`RawWaker`] gets cloned, e.g. when |
85 | /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. |
86 | /// |
87 | /// The implementation of this function must retain all resources that are |
88 | /// required for this additional instance of a [`RawWaker`] and associated |
89 | /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup |
90 | /// of the same task that would have been awoken by the original [`RawWaker`]. |
91 | clone: unsafe fn(*const ()) -> RawWaker, |
92 | |
93 | /// This function will be called when `wake` is called on the [`Waker`]. |
94 | /// It must wake up the task associated with this [`RawWaker`]. |
95 | /// |
96 | /// The implementation of this function must make sure to release any |
97 | /// resources that are associated with this instance of a [`RawWaker`] and |
98 | /// associated task. |
99 | wake: unsafe fn(*const ()), |
100 | |
101 | /// This function will be called when `wake_by_ref` is called on the [`Waker`]. |
102 | /// It must wake up the task associated with this [`RawWaker`]. |
103 | /// |
104 | /// This function is similar to `wake`, but must not consume the provided data |
105 | /// pointer. |
106 | wake_by_ref: unsafe fn(*const ()), |
107 | |
108 | /// This function gets called when a [`Waker`] gets dropped. |
109 | /// |
110 | /// The implementation of this function must make sure to release any |
111 | /// resources that are associated with this instance of a [`RawWaker`] and |
112 | /// associated task. |
113 | drop: unsafe fn(*const ()), |
114 | } |
115 | |
116 | impl RawWakerVTable { |
117 | /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, |
118 | /// `wake_by_ref`, and `drop` functions. |
119 | /// |
120 | /// These functions must all be thread-safe (even though [`RawWaker`] is |
121 | /// <code>\![Send] + \![Sync]</code>) |
122 | /// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to |
123 | /// arbitrary threads or invoked by `&` reference. For example, this means that if the |
124 | /// `clone` and `drop` functions manage a reference count, they must do so atomically. |
125 | /// |
126 | /// # `clone` |
127 | /// |
128 | /// This function will be called when the [`RawWaker`] gets cloned, e.g. when |
129 | /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. |
130 | /// |
131 | /// The implementation of this function must retain all resources that are |
132 | /// required for this additional instance of a [`RawWaker`] and associated |
133 | /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup |
134 | /// of the same task that would have been awoken by the original [`RawWaker`]. |
135 | /// |
136 | /// # `wake` |
137 | /// |
138 | /// This function will be called when `wake` is called on the [`Waker`]. |
139 | /// It must wake up the task associated with this [`RawWaker`]. |
140 | /// |
141 | /// The implementation of this function must make sure to release any |
142 | /// resources that are associated with this instance of a [`RawWaker`] and |
143 | /// associated task. |
144 | /// |
145 | /// # `wake_by_ref` |
146 | /// |
147 | /// This function will be called when `wake_by_ref` is called on the [`Waker`]. |
148 | /// It must wake up the task associated with this [`RawWaker`]. |
149 | /// |
150 | /// This function is similar to `wake`, but must not consume the provided data |
151 | /// pointer. |
152 | /// |
153 | /// # `drop` |
154 | /// |
155 | /// This function gets called when a [`Waker`] gets dropped. |
156 | /// |
157 | /// The implementation of this function must make sure to release any |
158 | /// resources that are associated with this instance of a [`RawWaker`] and |
159 | /// associated task. |
160 | #[rustc_promotable ] |
161 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
162 | #[rustc_const_stable (feature = "futures_api" , since = "1.36.0" )] |
163 | pub const fn new( |
164 | clone: unsafe fn(*const ()) -> RawWaker, |
165 | wake: unsafe fn(*const ()), |
166 | wake_by_ref: unsafe fn(*const ()), |
167 | drop: unsafe fn(*const ()), |
168 | ) -> Self { |
169 | Self { clone, wake, wake_by_ref, drop } |
170 | } |
171 | } |
172 | |
173 | /// The context of an asynchronous task. |
174 | /// |
175 | /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) |
176 | /// which can be used to wake the current task. |
177 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
178 | #[lang = "Context" ] |
179 | pub struct Context<'a> { |
180 | waker: &'a Waker, |
181 | // Ensure we future-proof against variance changes by forcing |
182 | // the lifetime to be invariant (argument-position lifetimes |
183 | // are contravariant while return-position lifetimes are |
184 | // covariant). |
185 | _marker: PhantomData<fn(&'a ()) -> &'a ()>, |
186 | // Ensure `Context` is `!Send` and `!Sync` in order to allow |
187 | // for future `!Send` and / or `!Sync` fields. |
188 | _marker2: PhantomData<*mut ()>, |
189 | } |
190 | |
191 | impl<'a> Context<'a> { |
192 | /// Create a new `Context` from a [`&Waker`](Waker). |
193 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
194 | #[rustc_const_unstable (feature = "const_waker" , issue = "102012" )] |
195 | #[must_use ] |
196 | #[inline ] |
197 | pub const fn from_waker(waker: &'a Waker) -> Self { |
198 | Context { waker, _marker: PhantomData, _marker2: PhantomData } |
199 | } |
200 | |
201 | /// Returns a reference to the [`Waker`] for the current task. |
202 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
203 | #[rustc_const_unstable (feature = "const_waker" , issue = "102012" )] |
204 | #[must_use ] |
205 | #[inline ] |
206 | pub const fn waker(&self) -> &'a Waker { |
207 | &self.waker |
208 | } |
209 | } |
210 | |
211 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
212 | impl fmt::Debug for Context<'_> { |
213 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
214 | f.debug_struct("Context" ).field(name:"waker" , &self.waker).finish() |
215 | } |
216 | } |
217 | |
218 | /// A `Waker` is a handle for waking up a task by notifying its executor that it |
219 | /// is ready to be run. |
220 | /// |
221 | /// This handle encapsulates a [`RawWaker`] instance, which defines the |
222 | /// executor-specific wakeup behavior. |
223 | /// |
224 | /// The typical life of a `Waker` is that it is constructed by an executor, wrapped in a |
225 | /// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return |
226 | /// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when |
227 | /// the future should be polled again. |
228 | /// |
229 | /// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked |
230 | /// from any thread, including ones not in any way managed by the executor. For example, |
231 | /// this might be done to wake a future when a blocking function call completes on another |
232 | /// thread. |
233 | /// |
234 | /// Note that it is preferable to use `waker.clone_from(&new_waker)` instead |
235 | /// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker |
236 | /// unnecessarily if the two wakers [wake the same task](Self::will_wake). |
237 | /// |
238 | /// [`Future::poll()`]: core::future::Future::poll |
239 | /// [`Poll::Pending`]: core::task::Poll::Pending |
240 | #[cfg_attr (not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 |
241 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
242 | pub struct Waker { |
243 | waker: RawWaker, |
244 | } |
245 | |
246 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
247 | impl Unpin for Waker {} |
248 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
249 | unsafe impl Send for Waker {} |
250 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
251 | unsafe impl Sync for Waker {} |
252 | |
253 | impl Waker { |
254 | /// Wake up the task associated with this `Waker`. |
255 | /// |
256 | /// As long as the executor keeps running and the task is not finished, it is |
257 | /// guaranteed that each invocation of [`wake()`](Self::wake) (or |
258 | /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one |
259 | /// [`poll()`] of the task to which this `Waker` belongs. This makes |
260 | /// it possible to temporarily yield to other tasks while running potentially |
261 | /// unbounded processing loops. |
262 | /// |
263 | /// Note that the above implies that multiple wake-ups may be coalesced into a |
264 | /// single [`poll()`] invocation by the runtime. |
265 | /// |
266 | /// Also note that yielding to competing tasks is not guaranteed: it is the |
267 | /// executor’s choice which task to run and the executor may choose to run the |
268 | /// current task again. |
269 | /// |
270 | /// [`poll()`]: crate::future::Future::poll |
271 | #[inline ] |
272 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
273 | pub fn wake(self) { |
274 | // The actual wakeup call is delegated through a virtual function call |
275 | // to the implementation which is defined by the executor. |
276 | let wake = self.waker.vtable.wake; |
277 | let data = self.waker.data; |
278 | |
279 | // Don't call `drop` -- the waker will be consumed by `wake`. |
280 | crate::mem::forget(self); |
281 | |
282 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
283 | // to initialize `wake` and `data` requiring the user to acknowledge |
284 | // that the contract of `RawWaker` is upheld. |
285 | unsafe { (wake)(data) }; |
286 | } |
287 | |
288 | /// Wake up the task associated with this `Waker` without consuming the `Waker`. |
289 | /// |
290 | /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in |
291 | /// the case where an owned `Waker` is available. This method should be preferred to |
292 | /// calling `waker.clone().wake()`. |
293 | #[inline ] |
294 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
295 | pub fn wake_by_ref(&self) { |
296 | // The actual wakeup call is delegated through a virtual function call |
297 | // to the implementation which is defined by the executor. |
298 | |
299 | // SAFETY: see `wake` |
300 | unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } |
301 | } |
302 | |
303 | /// Returns `true` if this `Waker` and another `Waker` would awake the same task. |
304 | /// |
305 | /// This function works on a best-effort basis, and may return false even |
306 | /// when the `Waker`s would awaken the same task. However, if this function |
307 | /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. |
308 | /// |
309 | /// This function is primarily used for optimization purposes — for example, |
310 | /// this type's [`clone_from`](Self::clone_from) implementation uses it to |
311 | /// avoid cloning the waker when they would wake the same task anyway. |
312 | #[inline ] |
313 | #[must_use ] |
314 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
315 | pub fn will_wake(&self, other: &Waker) -> bool { |
316 | self.waker == other.waker |
317 | } |
318 | |
319 | /// Creates a new `Waker` from [`RawWaker`]. |
320 | /// |
321 | /// The behavior of the returned `Waker` is undefined if the contract defined |
322 | /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. |
323 | /// Therefore this method is unsafe. |
324 | #[inline ] |
325 | #[must_use ] |
326 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
327 | #[rustc_const_unstable (feature = "const_waker" , issue = "102012" )] |
328 | pub const unsafe fn from_raw(waker: RawWaker) -> Waker { |
329 | Waker { waker } |
330 | } |
331 | |
332 | /// Returns a reference to a `Waker` that does nothing when used. |
333 | /// |
334 | /// This is mostly useful for writing tests that need a [`Context`] to poll |
335 | /// some futures, but are not expecting those futures to wake the waker or |
336 | /// do not need to do anything specific if it happens. |
337 | /// |
338 | /// If an owned `Waker` is needed, `clone()` this one. |
339 | /// |
340 | /// # Examples |
341 | /// |
342 | /// ``` |
343 | /// #![feature(noop_waker)] |
344 | /// |
345 | /// use std::future::Future; |
346 | /// use std::task; |
347 | /// |
348 | /// let mut cx = task::Context::from_waker(task::Waker::noop()); |
349 | /// |
350 | /// let mut future = Box::pin(async { 10 }); |
351 | /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); |
352 | /// ``` |
353 | #[inline ] |
354 | #[must_use ] |
355 | #[unstable (feature = "noop_waker" , issue = "98286" )] |
356 | pub const fn noop() -> &'static Waker { |
357 | // Ideally all this data would be explicitly `static` because it is used by reference and |
358 | // only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics, |
359 | // even though their values can be promoted to static. (That might change; see #119618.) |
360 | // An alternative would be a `pub static NOOP: &Waker`, but associated static items are not |
361 | // currently allowed either, and making it non-associated would be unergonomic. |
362 | const VTABLE: RawWakerVTable = RawWakerVTable::new( |
363 | // Cloning just returns a new no-op raw waker |
364 | |_| RAW, |
365 | // `wake` does nothing |
366 | |_| {}, |
367 | // `wake_by_ref` does nothing |
368 | |_| {}, |
369 | // Dropping does nothing as we don't allocate anything |
370 | |_| {}, |
371 | ); |
372 | const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); |
373 | const WAKER_REF: &Waker = &Waker { waker: RAW }; |
374 | |
375 | WAKER_REF |
376 | } |
377 | |
378 | /// Get a reference to the underlying [`RawWaker`]. |
379 | #[inline ] |
380 | #[must_use ] |
381 | #[unstable (feature = "waker_getters" , issue = "96992" )] |
382 | pub fn as_raw(&self) -> &RawWaker { |
383 | &self.waker |
384 | } |
385 | } |
386 | |
387 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
388 | impl Clone for Waker { |
389 | #[inline ] |
390 | fn clone(&self) -> Self { |
391 | Waker { |
392 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
393 | // to initialize `clone` and `data` requiring the user to acknowledge |
394 | // that the contract of [`RawWaker`] is upheld. |
395 | waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, |
396 | } |
397 | } |
398 | |
399 | #[inline ] |
400 | fn clone_from(&mut self, source: &Self) { |
401 | if !self.will_wake(source) { |
402 | *self = source.clone(); |
403 | } |
404 | } |
405 | } |
406 | |
407 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
408 | impl Drop for Waker { |
409 | #[inline ] |
410 | fn drop(&mut self) { |
411 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
412 | // to initialize `drop` and `data` requiring the user to acknowledge |
413 | // that the contract of `RawWaker` is upheld. |
414 | unsafe { (self.waker.vtable.drop)(self.waker.data) } |
415 | } |
416 | } |
417 | |
418 | #[stable (feature = "futures_api" , since = "1.36.0" )] |
419 | impl fmt::Debug for Waker { |
420 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
421 | let vtable_ptr: *const RawWakerVTable = self.waker.vtable as *const RawWakerVTable; |
422 | f&mut DebugStruct<'_, '_>.debug_struct("Waker" ) |
423 | .field("data" , &self.waker.data) |
424 | .field(name:"vtable" , &vtable_ptr) |
425 | .finish() |
426 | } |
427 | } |
428 | |