xref: /aosp_15_r20/external/crosvm/cros_async/src/waker.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::drop;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::ManuallyDrop;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Weak;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::task::RawWaker;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::task::RawWakerVTable;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::task::Waker;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper around a usize used as a token to uniquely identify a pending waker.
13*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
14*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct WakerToken(pub(crate) usize);
15*bb4ee6a4SAndroid Build Coastguard Worker 
16*bb4ee6a4SAndroid Build Coastguard Worker /// Like `futures::task::ArcWake` but uses `Weak<T>` instead of `Arc<T>`.
17*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) trait WeakWake: Send + Sync {
wake_by_ref(weak_self: &Weak<Self>)18*bb4ee6a4SAndroid Build Coastguard Worker     fn wake_by_ref(weak_self: &Weak<Self>);
19*bb4ee6a4SAndroid Build Coastguard Worker 
wake(weak_self: Weak<Self>)20*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(weak_self: Weak<Self>) {
21*bb4ee6a4SAndroid Build Coastguard Worker         Self::wake_by_ref(&weak_self)
22*bb4ee6a4SAndroid Build Coastguard Worker     }
23*bb4ee6a4SAndroid Build Coastguard Worker }
24*bb4ee6a4SAndroid Build Coastguard Worker 
waker_vtable<W: WeakWake>() -> &'static RawWakerVTable25*bb4ee6a4SAndroid Build Coastguard Worker fn waker_vtable<W: WeakWake>() -> &'static RawWakerVTable {
26*bb4ee6a4SAndroid Build Coastguard Worker     &RawWakerVTable::new(
27*bb4ee6a4SAndroid Build Coastguard Worker         clone_weak_raw::<W>,
28*bb4ee6a4SAndroid Build Coastguard Worker         wake_weak_raw::<W>,
29*bb4ee6a4SAndroid Build Coastguard Worker         wake_by_ref_weak_raw::<W>,
30*bb4ee6a4SAndroid Build Coastguard Worker         drop_weak_raw::<W>,
31*bb4ee6a4SAndroid Build Coastguard Worker     )
32*bb4ee6a4SAndroid Build Coastguard Worker }
33*bb4ee6a4SAndroid Build Coastguard Worker 
clone_weak_raw<W: WeakWake>(data: *const ()) -> RawWaker34*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn clone_weak_raw<W: WeakWake>(data: *const ()) -> RawWaker {
35*bb4ee6a4SAndroid Build Coastguard Worker     // Get a handle to the Weak<T> but wrap it in a ManuallyDrop so that we don't reduce the
36*bb4ee6a4SAndroid Build Coastguard Worker     // refcount at the end of this function.
37*bb4ee6a4SAndroid Build Coastguard Worker     let weak = ManuallyDrop::new(Weak::<W>::from_raw(data as *const W));
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker     // Now increase the weak count and keep it in a ManuallyDrop so that it doesn't get decreased
40*bb4ee6a4SAndroid Build Coastguard Worker     // at the end of this function.
41*bb4ee6a4SAndroid Build Coastguard Worker     let _weak_clone: ManuallyDrop<_> = weak.clone();
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker     RawWaker::new(data, waker_vtable::<W>())
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker 
wake_weak_raw<W: WeakWake>(data: *const ())46*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn wake_weak_raw<W: WeakWake>(data: *const ()) {
47*bb4ee6a4SAndroid Build Coastguard Worker     let weak: Weak<W> = Weak::from_raw(data as *const W);
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker     WeakWake::wake(weak)
50*bb4ee6a4SAndroid Build Coastguard Worker }
51*bb4ee6a4SAndroid Build Coastguard Worker 
wake_by_ref_weak_raw<W: WeakWake>(data: *const ())52*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn wake_by_ref_weak_raw<W: WeakWake>(data: *const ()) {
53*bb4ee6a4SAndroid Build Coastguard Worker     // Get a handle to the Weak<T> but wrap it in a ManuallyDrop so that we don't reduce the
54*bb4ee6a4SAndroid Build Coastguard Worker     // refcount at the end of this function.
55*bb4ee6a4SAndroid Build Coastguard Worker     let weak = ManuallyDrop::new(Weak::<W>::from_raw(data as *const W));
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker     WeakWake::wake_by_ref(&weak)
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
drop_weak_raw<W: WeakWake>(data: *const ())60*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn drop_weak_raw<W: WeakWake>(data: *const ()) {
61*bb4ee6a4SAndroid Build Coastguard Worker     drop(Weak::from_raw(data as *const W))
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker 
new_waker<W: WeakWake>(w: Weak<W>) -> Waker64*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn new_waker<W: WeakWake>(w: Weak<W>) -> Waker {
65*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(b/315998194): Add safety comment
66*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::undocumented_unsafe_blocks)]
67*bb4ee6a4SAndroid Build Coastguard Worker     unsafe {
68*bb4ee6a4SAndroid Build Coastguard Worker         Waker::from_raw(RawWaker::new(
69*bb4ee6a4SAndroid Build Coastguard Worker             w.into_raw() as *const (),
70*bb4ee6a4SAndroid Build Coastguard Worker             waker_vtable::<W>(),
71*bb4ee6a4SAndroid Build Coastguard Worker         ))
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker }
74