simcore/async_mode/
waker.rs1use std::rc::Rc;
7use std::task::{RawWaker, RawWakerVTable, Waker};
8
9use core::mem::ManuallyDrop;
10use futures::task::WakerRef;
11
12pub(super) trait RcWake {
16 fn wake(self: Rc<Self>) {
18 Self::wake_by_ref(&self)
19 }
20
21 fn wake_by_ref(rc_self: &Rc<Self>);
24}
25
26pub(super) fn waker_ref<W>(wake: &Rc<W>) -> WakerRef<'_>
29where
30 W: RcWake + 'static,
31{
32 let ptr = Rc::as_ptr(wake).cast::<()>();
35
36 let waker = ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<W>())) });
37 WakerRef::new_unowned(waker)
38}
39
40fn waker_vtable<W: RcWake + 'static>() -> &'static RawWakerVTable {
41 &RawWakerVTable::new(
42 clone_rc_raw::<W>,
43 wake_rc_raw::<W>,
44 wake_by_ref_rc_raw::<W>,
45 drop_rc_raw::<W>,
46 )
47}
48
49#[allow(clippy::redundant_clone)] unsafe fn increase_refcount<T: RcWake + 'static>(data: *const ()) {
51 let rc = ManuallyDrop::new(unsafe { Rc::<T>::from_raw(data.cast::<T>()) });
53 let _rc_clone: ManuallyDrop<_> = rc.clone();
55}
56
57unsafe fn clone_rc_raw<T: RcWake + 'static>(data: *const ()) -> RawWaker {
58 unsafe { increase_refcount::<T>(data) };
59 RawWaker::new(data, waker_vtable::<T>())
60}
61
62unsafe fn wake_rc_raw<T: RcWake + 'static>(data: *const ()) {
63 let rc: Rc<T> = unsafe { Rc::from_raw(data.cast::<T>()) };
64 RcWake::wake(rc);
65}
66
67unsafe fn wake_by_ref_rc_raw<T: RcWake + 'static>(data: *const ()) {
68 let rc = ManuallyDrop::new(unsafe { Rc::<T>::from_raw(data.cast::<T>()) });
70 RcWake::wake_by_ref(&rc);
71}
72
73unsafe fn drop_rc_raw<T: RcWake + 'static>(data: *const ()) {
74 drop(unsafe { Rc::<T>::from_raw(data.cast::<T>()) })
75}