]>
Commit | Line | Data |
---|---|---|
48663c56 | 1 | #![stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 2 | |
48663c56 XL |
3 | use crate::fmt; |
4 | use crate::marker::{PhantomData, Unpin}; | |
9fa01778 XL |
5 | |
6 | /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] | |
7 | /// which provides customized wakeup behavior. | |
8 | /// | |
9 | /// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table | |
10 | /// | |
1b1a35ee XL |
11 | /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] |
12 | /// that customizes the behavior of the `RawWaker`. | |
9fa01778 | 13 | #[derive(PartialEq, Debug)] |
48663c56 | 14 | #[stable(feature = "futures_api", since = "1.36.0")] |
9fa01778 XL |
15 | pub struct RawWaker { |
16 | /// A data pointer, which can be used to store arbitrary data as required | |
17 | /// by the executor. This could be e.g. a type-erased pointer to an `Arc` | |
18 | /// that is associated with the task. | |
19 | /// The value of this field gets passed to all functions that are part of | |
20 | /// the vtable as the first parameter. | |
21 | data: *const (), | |
22 | /// Virtual function pointer table that customizes the behavior of this waker. | |
23 | vtable: &'static RawWakerVTable, | |
24 | } | |
25 | ||
26 | impl RawWaker { | |
27 | /// Creates a new `RawWaker` from the provided `data` pointer and `vtable`. | |
28 | /// | |
29 | /// The `data` pointer can be used to store arbitrary data as required | |
30 | /// by the executor. This could be e.g. a type-erased pointer to an `Arc` | |
31 | /// that is associated with the task. | |
416331ca | 32 | /// The value of this pointer will get passed to all functions that are part |
9fa01778 XL |
33 | /// of the `vtable` as the first parameter. |
34 | /// | |
35 | /// The `vtable` customizes the behavior of a `Waker` which gets created | |
36 | /// from a `RawWaker`. For each operation on the `Waker`, the associated | |
37 | /// function in the `vtable` of the underlying `RawWaker` will be called. | |
3dfed10e | 38 | #[inline] |
532ac7d7 | 39 | #[rustc_promotable] |
48663c56 | 40 | #[stable(feature = "futures_api", since = "1.36.0")] |
dfeec247 | 41 | #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] |
c295e0f8 | 42 | #[must_use] |
9fa01778 | 43 | pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker { |
60c5eb7d | 44 | RawWaker { data, vtable } |
9fa01778 | 45 | } |
5099ac24 FG |
46 | |
47 | /// Get the `data` pointer used to create this `RawWaker`. | |
48 | #[inline] | |
49 | #[must_use] | |
50 | #[unstable(feature = "waker_getters", issue = "87021")] | |
51 | pub fn data(&self) -> *const () { | |
52 | self.data | |
53 | } | |
54 | ||
55 | /// Get the `vtable` pointer used to create this `RawWaker`. | |
56 | #[inline] | |
57 | #[must_use] | |
58 | #[unstable(feature = "waker_getters", issue = "87021")] | |
59 | pub fn vtable(&self) -> &'static RawWakerVTable { | |
60 | self.vtable | |
61 | } | |
9fa01778 XL |
62 | } |
63 | ||
64 | /// A virtual function pointer table (vtable) that specifies the behavior | |
65 | /// of a [`RawWaker`]. | |
66 | /// | |
67 | /// The pointer passed to all functions inside the vtable is the `data` pointer | |
68 | /// from the enclosing [`RawWaker`] object. | |
69 | /// | |
1b1a35ee | 70 | /// The functions inside this struct are only intended to be called on the `data` |
9fa01778 XL |
71 | /// pointer of a properly constructed [`RawWaker`] object from inside the |
72 | /// [`RawWaker`] implementation. Calling one of the contained functions using | |
73 | /// any other `data` pointer will cause undefined behavior. | |
48663c56 | 74 | #[stable(feature = "futures_api", since = "1.36.0")] |
9fa01778 XL |
75 | #[derive(PartialEq, Copy, Clone, Debug)] |
76 | pub struct RawWakerVTable { | |
77 | /// This function will be called when the [`RawWaker`] gets cloned, e.g. when | |
78 | /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. | |
79 | /// | |
80 | /// The implementation of this function must retain all resources that are | |
81 | /// required for this additional instance of a [`RawWaker`] and associated | |
82 | /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup | |
83 | /// of the same task that would have been awoken by the original [`RawWaker`]. | |
532ac7d7 | 84 | clone: unsafe fn(*const ()) -> RawWaker, |
9fa01778 XL |
85 | |
86 | /// This function will be called when `wake` is called on the [`Waker`]. | |
87 | /// It must wake up the task associated with this [`RawWaker`]. | |
88 | /// | |
48663c56 XL |
89 | /// The implementation of this function must make sure to release any |
90 | /// resources that are associated with this instance of a [`RawWaker`] and | |
91 | /// associated task. | |
532ac7d7 XL |
92 | wake: unsafe fn(*const ()), |
93 | ||
48663c56 XL |
94 | /// This function will be called when `wake_by_ref` is called on the [`Waker`]. |
95 | /// It must wake up the task associated with this [`RawWaker`]. | |
96 | /// | |
97 | /// This function is similar to `wake`, but must not consume the provided data | |
98 | /// pointer. | |
48663c56 XL |
99 | wake_by_ref: unsafe fn(*const ()), |
100 | ||
532ac7d7 XL |
101 | /// This function gets called when a [`RawWaker`] gets dropped. |
102 | /// | |
103 | /// The implementation of this function must make sure to release any | |
104 | /// resources that are associated with this instance of a [`RawWaker`] and | |
105 | /// associated task. | |
106 | drop: unsafe fn(*const ()), | |
107 | } | |
9fa01778 | 108 | |
532ac7d7 | 109 | impl RawWakerVTable { |
48663c56 XL |
110 | /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, |
111 | /// `wake_by_ref`, and `drop` functions. | |
532ac7d7 XL |
112 | /// |
113 | /// # `clone` | |
114 | /// | |
115 | /// This function will be called when the [`RawWaker`] gets cloned, e.g. when | |
116 | /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. | |
117 | /// | |
118 | /// The implementation of this function must retain all resources that are | |
119 | /// required for this additional instance of a [`RawWaker`] and associated | |
120 | /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup | |
121 | /// of the same task that would have been awoken by the original [`RawWaker`]. | |
122 | /// | |
123 | /// # `wake` | |
124 | /// | |
125 | /// This function will be called when `wake` is called on the [`Waker`]. | |
126 | /// It must wake up the task associated with this [`RawWaker`]. | |
127 | /// | |
48663c56 XL |
128 | /// The implementation of this function must make sure to release any |
129 | /// resources that are associated with this instance of a [`RawWaker`] and | |
130 | /// associated task. | |
131 | /// | |
132 | /// # `wake_by_ref` | |
133 | /// | |
134 | /// This function will be called when `wake_by_ref` is called on the [`Waker`]. | |
135 | /// It must wake up the task associated with this [`RawWaker`]. | |
136 | /// | |
137 | /// This function is similar to `wake`, but must not consume the provided data | |
532ac7d7 XL |
138 | /// pointer. |
139 | /// | |
140 | /// # `drop` | |
141 | /// | |
9fa01778 XL |
142 | /// This function gets called when a [`RawWaker`] gets dropped. |
143 | /// | |
144 | /// The implementation of this function must make sure to release any | |
145 | /// resources that are associated with this instance of a [`RawWaker`] and | |
146 | /// associated task. | |
532ac7d7 | 147 | #[rustc_promotable] |
dc9dc135 | 148 | #[stable(feature = "futures_api", since = "1.36.0")] |
dfeec247 | 149 | #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] |
532ac7d7 XL |
150 | pub const fn new( |
151 | clone: unsafe fn(*const ()) -> RawWaker, | |
152 | wake: unsafe fn(*const ()), | |
48663c56 | 153 | wake_by_ref: unsafe fn(*const ()), |
532ac7d7 XL |
154 | drop: unsafe fn(*const ()), |
155 | ) -> Self { | |
60c5eb7d | 156 | Self { clone, wake, wake_by_ref, drop } |
532ac7d7 XL |
157 | } |
158 | } | |
159 | ||
160 | /// The `Context` of an asynchronous task. | |
161 | /// | |
162 | /// Currently, `Context` only serves to provide access to a `&Waker` | |
163 | /// which can be used to wake the current task. | |
48663c56 | 164 | #[stable(feature = "futures_api", since = "1.36.0")] |
532ac7d7 XL |
165 | pub struct Context<'a> { |
166 | waker: &'a Waker, | |
167 | // Ensure we future-proof against variance changes by forcing | |
168 | // the lifetime to be invariant (argument-position lifetimes | |
169 | // are contravariant while return-position lifetimes are | |
170 | // covariant). | |
171 | _marker: PhantomData<fn(&'a ()) -> &'a ()>, | |
172 | } | |
173 | ||
174 | impl<'a> Context<'a> { | |
175 | /// Create a new `Context` from a `&Waker`. | |
48663c56 | 176 | #[stable(feature = "futures_api", since = "1.36.0")] |
c295e0f8 | 177 | #[must_use] |
532ac7d7 XL |
178 | #[inline] |
179 | pub fn from_waker(waker: &'a Waker) -> Self { | |
60c5eb7d | 180 | Context { waker, _marker: PhantomData } |
532ac7d7 XL |
181 | } |
182 | ||
183 | /// Returns a reference to the `Waker` for the current task. | |
48663c56 | 184 | #[stable(feature = "futures_api", since = "1.36.0")] |
3c0e092e | 185 | #[must_use] |
532ac7d7 XL |
186 | #[inline] |
187 | pub fn waker(&self) -> &'a Waker { | |
188 | &self.waker | |
189 | } | |
190 | } | |
191 | ||
48663c56 | 192 | #[stable(feature = "futures_api", since = "1.36.0")] |
532ac7d7 | 193 | impl fmt::Debug for Context<'_> { |
48663c56 | 194 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
60c5eb7d | 195 | f.debug_struct("Context").field("waker", &self.waker).finish() |
532ac7d7 | 196 | } |
9fa01778 | 197 | } |
8faf50e0 XL |
198 | |
199 | /// A `Waker` is a handle for waking up a task by notifying its executor that it | |
200 | /// is ready to be run. | |
201 | /// | |
9fa01778 XL |
202 | /// This handle encapsulates a [`RawWaker`] instance, which defines the |
203 | /// executor-specific wakeup behavior. | |
204 | /// | |
e74abb32 | 205 | /// Implements [`Clone`], [`Send`], and [`Sync`]. |
8faf50e0 | 206 | #[repr(transparent)] |
48663c56 | 207 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 208 | pub struct Waker { |
9fa01778 | 209 | waker: RawWaker, |
8faf50e0 XL |
210 | } |
211 | ||
48663c56 | 212 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 213 | impl Unpin for Waker {} |
48663c56 | 214 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 215 | unsafe impl Send for Waker {} |
48663c56 | 216 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 XL |
217 | unsafe impl Sync for Waker {} |
218 | ||
219 | impl Waker { | |
8faf50e0 | 220 | /// Wake up the task associated with this `Waker`. |
532ac7d7 | 221 | #[inline] |
48663c56 XL |
222 | #[stable(feature = "futures_api", since = "1.36.0")] |
223 | pub fn wake(self) { | |
9fa01778 XL |
224 | // The actual wakeup call is delegated through a virtual function call |
225 | // to the implementation which is defined by the executor. | |
48663c56 XL |
226 | let wake = self.waker.vtable.wake; |
227 | let data = self.waker.data; | |
228 | ||
229 | // Don't call `drop` -- the waker will be consumed by `wake`. | |
230 | crate::mem::forget(self); | |
9fa01778 | 231 | |
48663c56 | 232 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
9fa01778 XL |
233 | // to initialize `wake` and `data` requiring the user to acknowledge |
234 | // that the contract of `RawWaker` is upheld. | |
48663c56 XL |
235 | unsafe { (wake)(data) }; |
236 | } | |
237 | ||
238 | /// Wake up the task associated with this `Waker` without consuming the `Waker`. | |
239 | /// | |
240 | /// This is similar to `wake`, but may be slightly less efficient in the case | |
241 | /// where an owned `Waker` is available. This method should be preferred to | |
242 | /// calling `waker.clone().wake()`. | |
243 | #[inline] | |
244 | #[stable(feature = "futures_api", since = "1.36.0")] | |
245 | pub fn wake_by_ref(&self) { | |
246 | // The actual wakeup call is delegated through a virtual function call | |
247 | // to the implementation which is defined by the executor. | |
248 | ||
249 | // SAFETY: see `wake` | |
250 | unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } | |
8faf50e0 XL |
251 | } |
252 | ||
532ac7d7 | 253 | /// Returns `true` if this `Waker` and another `Waker` have awoken the same task. |
8faf50e0 XL |
254 | /// |
255 | /// This function works on a best-effort basis, and may return false even | |
256 | /// when the `Waker`s would awaken the same task. However, if this function | |
9fa01778 | 257 | /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. |
8faf50e0 XL |
258 | /// |
259 | /// This function is primarily used for optimization purposes. | |
532ac7d7 | 260 | #[inline] |
3c0e092e | 261 | #[must_use] |
48663c56 | 262 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 263 | pub fn will_wake(&self, other: &Waker) -> bool { |
9fa01778 | 264 | self.waker == other.waker |
8faf50e0 | 265 | } |
0bf4aa26 | 266 | |
9fa01778 | 267 | /// Creates a new `Waker` from [`RawWaker`]. |
0bf4aa26 | 268 | /// |
9fa01778 XL |
269 | /// The behavior of the returned `Waker` is undefined if the contract defined |
270 | /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. | |
271 | /// Therefore this method is unsafe. | |
532ac7d7 | 272 | #[inline] |
c295e0f8 | 273 | #[must_use] |
48663c56 XL |
274 | #[stable(feature = "futures_api", since = "1.36.0")] |
275 | pub unsafe fn from_raw(waker: RawWaker) -> Waker { | |
60c5eb7d | 276 | Waker { waker } |
0bf4aa26 | 277 | } |
5099ac24 FG |
278 | |
279 | /// Get a reference to the underlying [`RawWaker`]. | |
280 | #[inline] | |
281 | #[must_use] | |
282 | #[unstable(feature = "waker_getters", issue = "87021")] | |
283 | pub fn as_raw(&self) -> &RawWaker { | |
284 | &self.waker | |
285 | } | |
8faf50e0 XL |
286 | } |
287 | ||
48663c56 | 288 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 289 | impl Clone for Waker { |
532ac7d7 | 290 | #[inline] |
8faf50e0 | 291 | fn clone(&self) -> Self { |
9fa01778 | 292 | Waker { |
48663c56 | 293 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
9fa01778 XL |
294 | // to initialize `clone` and `data` requiring the user to acknowledge |
295 | // that the contract of [`RawWaker`] is upheld. | |
296 | waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, | |
8faf50e0 XL |
297 | } |
298 | } | |
299 | } | |
300 | ||
48663c56 | 301 | #[stable(feature = "futures_api", since = "1.36.0")] |
8faf50e0 | 302 | impl Drop for Waker { |
532ac7d7 | 303 | #[inline] |
8faf50e0 | 304 | fn drop(&mut self) { |
48663c56 | 305 | // SAFETY: This is safe because `Waker::from_raw` is the only way |
9fa01778 XL |
306 | // to initialize `drop` and `data` requiring the user to acknowledge |
307 | // that the contract of `RawWaker` is upheld. | |
308 | unsafe { (self.waker.vtable.drop)(self.waker.data) } | |
8faf50e0 XL |
309 | } |
310 | } | |
311 | ||
48663c56 | 312 | #[stable(feature = "futures_api", since = "1.36.0")] |
9fa01778 | 313 | impl fmt::Debug for Waker { |
48663c56 | 314 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
9fa01778 XL |
315 | let vtable_ptr = self.waker.vtable as *const RawWakerVTable; |
316 | f.debug_struct("Waker") | |
317 | .field("data", &self.waker.data) | |
318 | .field("vtable", &vtable_ptr) | |
8faf50e0 XL |
319 | .finish() |
320 | } | |
321 | } |