use std::{
marker::PhantomData,
mem::ManuallyDrop,
ops::Deref,
sync::Arc,
task::{RawWaker, RawWakerVTable, Waker},
};
use super::ArcWake;
#[derive(Debug)]
pub struct WakerRef<'a> {
waker: ManuallyDrop<Waker>,
_marker: PhantomData<&'a ()>,
}
impl<'a> WakerRef<'a> {
pub fn new_unowned(waker: ManuallyDrop<Waker>) -> Self {
Self {
waker,
_marker: PhantomData,
}
}
}
impl Deref for WakerRef<'_> {
type Target = Waker;
fn deref(&self) -> &Waker {
&self.waker
}
}
#[allow(clippy::needless_lifetimes)] pub fn waker_ref<T: ArcWake>(this: &Arc<T>) -> WakerRef<'_> {
let ptr = (&**this as *const T) as *const ();
let waker = ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<T>())) });
WakerRef::new_unowned(waker)
}
pub fn waker_vtable<T: ArcWake>() -> &'static RawWakerVTable {
&RawWakerVTable::new(
clone_arc_raw::<T>,
wake_arc_raw::<T>,
wake_by_ref_arc_raw::<T>,
drop_arc_raw::<T>,
)
}
#[allow(clippy::redundant_clone)] unsafe fn increase_refcount<T>(data: *const ()) {
let arc = ManuallyDrop::new(Arc::<T>::from_raw(data as *const T));
let _arc_clone: ManuallyDrop<_> = arc.clone();
}
unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
increase_refcount::<T>(data);
RawWaker::new(data, waker_vtable::<T>())
}
unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake(arc);
}
unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
let arc = ManuallyDrop::new(Arc::<T>::from_raw(data as *const T));
ArcWake::wake_by_ref(&arc)
}
unsafe fn drop_arc_raw<T>(data: *const ()) {
drop(Arc::<T>::from_raw(data as *const T))
}