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