Coverage Report

Created: 2025-07-11 06:53

/rust/registry/src/index.crates.io-6f17d22bba15001f/futures-task-0.3.31/src/waker.rs
Line
Count
Source (jump to first uncovered line)
1
use super::arc_wake::ArcWake;
2
use alloc::sync::Arc;
3
use core::mem;
4
use core::task::{RawWaker, RawWakerVTable, Waker};
5
6
0
pub(super) fn waker_vtable<W: ArcWake + 'static>() -> &'static RawWakerVTable {
7
0
    &RawWakerVTable::new(
8
0
        clone_arc_raw::<W>,
9
0
        wake_arc_raw::<W>,
10
0
        wake_by_ref_arc_raw::<W>,
11
0
        drop_arc_raw::<W>,
12
0
    )
13
0
}
14
15
/// Creates a [`Waker`] from an `Arc<impl ArcWake>`.
16
///
17
/// The returned [`Waker`] will call
18
/// [`ArcWake.wake()`](ArcWake::wake) if awoken.
19
0
pub fn waker<W>(wake: Arc<W>) -> Waker
20
0
where
21
0
    W: ArcWake + 'static,
22
0
{
23
0
    let ptr = Arc::into_raw(wake).cast::<()>();
24
0
25
0
    unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::<W>())) }
26
0
}
27
28
// FIXME: panics on Arc::clone / refcount changes could wreak havoc on the
29
// code here. We should guard against this by aborting.
30
31
#[allow(clippy::redundant_clone)] // The clone here isn't actually redundant.
32
0
unsafe fn increase_refcount<T: ArcWake + 'static>(data: *const ()) {
33
0
    // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
34
0
    let arc = mem::ManuallyDrop::new(unsafe { Arc::<T>::from_raw(data.cast::<T>()) });
35
0
    // Now increase refcount, but don't drop new refcount either
36
0
    let _arc_clone: mem::ManuallyDrop<_> = arc.clone();
37
0
}
38
39
// used by `waker_ref`
40
#[inline(always)]
41
0
unsafe fn clone_arc_raw<T: ArcWake + 'static>(data: *const ()) -> RawWaker {
42
0
    unsafe { increase_refcount::<T>(data) }
43
0
    RawWaker::new(data, waker_vtable::<T>())
44
0
}
45
46
0
unsafe fn wake_arc_raw<T: ArcWake + 'static>(data: *const ()) {
47
0
    let arc: Arc<T> = unsafe { Arc::from_raw(data.cast::<T>()) };
48
0
    ArcWake::wake(arc);
49
0
}
50
51
// used by `waker_ref`
52
0
unsafe fn wake_by_ref_arc_raw<T: ArcWake + 'static>(data: *const ()) {
53
0
    // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
54
0
    let arc = mem::ManuallyDrop::new(unsafe { Arc::<T>::from_raw(data.cast::<T>()) });
55
0
    ArcWake::wake_by_ref(&arc);
56
0
}
57
58
0
unsafe fn drop_arc_raw<T: ArcWake + 'static>(data: *const ()) {
59
0
    drop(unsafe { Arc::<T>::from_raw(data.cast::<T>()) })
60
0
}