use super::arc_wake::ArcWake; use super::waker::waker_vtable; use alloc::sync::Arc; use core::marker::PhantomData; use core::mem::ManuallyDrop; use core::ops::Deref; use core::task::{RawWaker, Waker}; /// A [`Waker`] that is only valid for a given lifetime. /// /// Note: this type implements [`Deref`](std::ops::Deref), /// so it can be used to get a `&Waker`. #[derive(Debug)] pub struct WakerRef<'a> { waker: ManuallyDrop, _marker: PhantomData<&'a ()>, } impl<'a> WakerRef<'a> { /// Create a new [`WakerRef`] from a [`Waker`] reference. pub fn new(waker: &'a Waker) -> Self { // copy the underlying (raw) waker without calling a clone, // as we won't call Waker::drop either. let waker = ManuallyDrop::new(unsafe { core::ptr::read(waker) }); Self { waker, _marker: PhantomData } } /// Create a new [`WakerRef`] from a [`Waker`] that must not be dropped. /// /// Note: this if for rare cases where the caller created a [`Waker`] in /// an unsafe way (that will be valid only for a lifetime to be determined /// by the caller), and the [`Waker`] doesn't need to or must not be /// destroyed. pub fn new_unowned(waker: ManuallyDrop) -> Self { Self { waker, _marker: PhantomData } } } impl Deref for WakerRef<'_> { type Target = Waker; fn deref(&self) -> &Waker { &self.waker } } /// Creates a reference to a [`Waker`] from a reference to `Arc`. /// /// The resulting [`Waker`] will call /// [`ArcWake.wake()`](ArcWake::wake) if awoken. #[inline] pub fn waker_ref(wake: &Arc) -> WakerRef<'_> where W: ArcWake, { // simply copy the pointer instead of using Arc::into_raw, // as we don't actually keep a refcount by using ManuallyDrop.< let ptr = (&**wake as *const W) as *const (); let waker = ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::())) }); WakerRef::new_unowned(waker) }