Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/futures-task-0.3.31/src/waker_ref.rs
Line
Count
Source (jump to first uncovered line)
1
use super::arc_wake::ArcWake;
2
use super::waker::waker_vtable;
3
use alloc::sync::Arc;
4
use core::marker::PhantomData;
5
use core::mem::ManuallyDrop;
6
use core::ops::Deref;
7
use core::task::{RawWaker, Waker};
8
9
/// A [`Waker`] that is only valid for a given lifetime.
10
///
11
/// Note: this type implements [`Deref<Target = Waker>`](std::ops::Deref),
12
/// so it can be used to get a `&Waker`.
13
#[derive(Debug)]
14
pub struct WakerRef<'a> {
15
    waker: ManuallyDrop<Waker>,
16
    _marker: PhantomData<&'a ()>,
17
}
18
19
impl<'a> WakerRef<'a> {
20
    /// Create a new [`WakerRef`] from a [`Waker`] reference.
21
    #[inline]
22
0
    pub fn new(waker: &'a Waker) -> Self {
23
0
        // copy the underlying (raw) waker without calling a clone,
24
0
        // as we won't call Waker::drop either.
25
0
        let waker = ManuallyDrop::new(unsafe { core::ptr::read(waker) });
26
0
        Self { waker, _marker: PhantomData }
27
0
    }
28
29
    /// Create a new [`WakerRef`] from a [`Waker`] that must not be dropped.
30
    ///
31
    /// Note: this if for rare cases where the caller created a [`Waker`] in
32
    /// an unsafe way (that will be valid only for a lifetime to be determined
33
    /// by the caller), and the [`Waker`] doesn't need to or must not be
34
    /// destroyed.
35
    #[inline]
36
0
    pub fn new_unowned(waker: ManuallyDrop<Waker>) -> Self {
37
0
        Self { waker, _marker: PhantomData }
38
0
    }
39
}
40
41
impl Deref for WakerRef<'_> {
42
    type Target = Waker;
43
44
    #[inline]
45
0
    fn deref(&self) -> &Waker {
46
0
        &self.waker
47
0
    }
48
}
49
50
/// Creates a reference to a [`Waker`] from a reference to `Arc<impl ArcWake>`.
51
///
52
/// The resulting [`Waker`] will call
53
/// [`ArcWake.wake()`](ArcWake::wake) if awoken.
54
#[inline]
55
0
pub fn waker_ref<W>(wake: &Arc<W>) -> WakerRef<'_>
56
0
where
57
0
    W: ArcWake + 'static,
58
0
{
59
0
    // simply copy the pointer instead of using Arc::into_raw,
60
0
    // as we don't actually keep a refcount by using ManuallyDrop.<
61
0
    let ptr = Arc::as_ptr(wake).cast::<()>();
62
0
63
0
    let waker =
64
0
        ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<W>())) });
65
0
    WakerRef::new_unowned(waker)
66
0
}