1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use core::{
any::Provider,
task::{RawWaker, RawWakerVTable, Waker},
};
#[derive(Copy, Clone)]
pub struct ProviderWaker<'a, 'b> {
waker: &'a Waker,
provider: &'b dyn Provider,
}
impl<'a, 'b> ProviderWaker<'a, 'b> {
pub fn new(waker: &'a Waker, provider: &'b dyn Provider) -> Self {
Self { waker, provider }
}
}
static VTABLE: RawWakerVTable = {
unsafe fn clone(waker: *const ()) -> RawWaker {
let inner = (*waker.cast::<ProviderWaker>()).waker.clone();
core::mem::transmute(inner)
}
unsafe fn wake(waker: *const ()) {
(*waker.cast::<ProviderWaker>()).waker.wake_by_ref()
}
unsafe fn wake_by_ref(waker: *const ()) {
(*waker.cast::<ProviderWaker>()).waker.wake_by_ref()
}
unsafe fn drop(_: *const ()) { }
RawWakerVTable::new(clone, wake, wake_by_ref, drop)
};
impl<'a, 'b> ProviderWaker<'a, 'b> {
pub fn use_waker_with<R>(&self, f: impl for<'w> FnOnce(&'w Waker) -> R) -> R {
let ptr = (self as *const Self).cast();
let waker = unsafe { &Waker::from_raw(RawWaker::new(ptr, &VTABLE)) };
f(waker)
}
pub fn from_waker_ref(waker: &Waker) -> Option<&Self> {
if waker.as_raw().vtable() == &VTABLE {
Some(unsafe { &*waker.as_raw().data().cast::<Self>() })
} else {
None
}
}
}
impl Provider for ProviderWaker<'_, '_> {
fn provide<'a>(&'a self, demand: &mut core::any::Demand<'a>) {
self.provider.provide(demand);
if let Some(cx) = Self::from_waker_ref(self.waker) {
cx.provide(demand)
}
}
}