/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 | } |