/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/util/wake.rs
Line | Count | Source |
1 | | use crate::loom::sync::Arc; |
2 | | |
3 | | use std::marker::PhantomData; |
4 | | use std::mem::ManuallyDrop; |
5 | | use std::ops::Deref; |
6 | | use std::task::{RawWaker, RawWakerVTable, Waker}; |
7 | | |
8 | | /// Simplified waking interface based on Arcs. |
9 | | pub(crate) trait Wake: Send + Sync + Sized + 'static { |
10 | | /// Wake by value. |
11 | | fn wake(arc_self: Arc<Self>); |
12 | | |
13 | | /// Wake by reference. |
14 | | fn wake_by_ref(arc_self: &Arc<Self>); |
15 | | } |
16 | | |
17 | | /// A `Waker` that is only valid for a given lifetime. |
18 | | #[derive(Debug)] |
19 | | pub(crate) struct WakerRef<'a> { |
20 | | waker: ManuallyDrop<Waker>, |
21 | | _p: PhantomData<&'a ()>, |
22 | | } |
23 | | |
24 | | impl Deref for WakerRef<'_> { |
25 | | type Target = Waker; |
26 | | |
27 | 0 | fn deref(&self) -> &Waker { |
28 | 0 | &self.waker |
29 | 0 | } |
30 | | } |
31 | | |
32 | | /// Creates a reference to a `Waker` from a reference to `Arc<impl Wake>`. |
33 | 0 | pub(crate) fn waker_ref<W: Wake>(wake: &Arc<W>) -> WakerRef<'_> { |
34 | 0 | let ptr = Arc::as_ptr(wake).cast::<()>(); |
35 | | |
36 | 0 | let waker = unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<W>())) }; |
37 | | |
38 | 0 | WakerRef { |
39 | 0 | waker: ManuallyDrop::new(waker), |
40 | 0 | _p: PhantomData, |
41 | 0 | } |
42 | 0 | } |
43 | | |
44 | 0 | fn waker_vtable<W: Wake>() -> &'static RawWakerVTable { |
45 | 0 | &RawWakerVTable::new( |
46 | 0 | clone_arc_raw::<W>, |
47 | 0 | wake_arc_raw::<W>, |
48 | 0 | wake_by_ref_arc_raw::<W>, |
49 | 0 | drop_arc_raw::<W>, |
50 | 0 | ) |
51 | 0 | } |
52 | | |
53 | 0 | unsafe fn clone_arc_raw<T: Wake>(data: *const ()) -> RawWaker { |
54 | | // Safety: `data` was created from an `Arc::as_ptr` in function `waker_ref`. |
55 | 0 | unsafe { |
56 | 0 | Arc::<T>::increment_strong_count(data as *const T); |
57 | 0 | } |
58 | 0 | RawWaker::new(data, waker_vtable::<T>()) |
59 | 0 | } |
60 | | |
61 | 0 | unsafe fn wake_arc_raw<T: Wake>(data: *const ()) { |
62 | | // Safety: `data` was created from an `Arc::as_ptr` in function `waker_ref`. |
63 | 0 | let arc: Arc<T> = unsafe { Arc::from_raw(data as *const T) }; |
64 | 0 | Wake::wake(arc); |
65 | 0 | } |
66 | | |
67 | | // used by `waker_ref` |
68 | 0 | unsafe fn wake_by_ref_arc_raw<T: Wake>(data: *const ()) { |
69 | | // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop |
70 | | // Safety: `data` was created from an `Arc::as_ptr` in function `waker_ref`. |
71 | 0 | let arc = ManuallyDrop::new(unsafe { Arc::<T>::from_raw(data.cast()) }); |
72 | 0 | Wake::wake_by_ref(&arc); |
73 | 0 | } |
74 | | |
75 | 0 | unsafe fn drop_arc_raw<T: Wake>(data: *const ()) { |
76 | | // Safety: `data` was created from an `Arc::as_ptr` in function `waker_ref`. |
77 | 0 | drop(unsafe { Arc::<T>::from_raw(data.cast()) }); |
78 | 0 | } |