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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::cell::{Cell, RefCell};
use std::future::Future;
use std::mem::ManuallyDrop;
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
struct Inner {
future: Pin<Box<dyn Future<Output = ()> + 'static>>,
waker: Waker,
}
pub(crate) struct Task {
inner: RefCell<Option<Inner>>,
is_queued: Cell<bool>,
}
impl Task {
pub(crate) fn spawn(future: Pin<Box<dyn Future<Output = ()> + 'static>>) {
let this = Rc::new(Self {
inner: RefCell::new(None),
is_queued: Cell::new(false),
});
let waker = unsafe { Waker::from_raw(Task::into_raw_waker(Rc::clone(&this))) };
*this.inner.borrow_mut() = Some(Inner { future, waker });
Task::wake_by_ref(&this);
}
fn wake_by_ref(this: &Rc<Self>) {
if this.is_queued.replace(true) {
return;
}
crate::queue::QUEUE.with(|queue| {
queue.push_task(Rc::clone(this));
});
}
unsafe fn into_raw_waker(this: Rc<Self>) -> RawWaker {
unsafe fn raw_clone(ptr: *const ()) -> RawWaker {
let ptr = ManuallyDrop::new(Rc::from_raw(ptr as *const Task));
Task::into_raw_waker((*ptr).clone())
}
unsafe fn raw_wake(ptr: *const ()) {
let ptr = Rc::from_raw(ptr as *const Task);
Task::wake_by_ref(&ptr);
}
unsafe fn raw_wake_by_ref(ptr: *const ()) {
let ptr = ManuallyDrop::new(Rc::from_raw(ptr as *const Task));
Task::wake_by_ref(&ptr);
}
unsafe fn raw_drop(ptr: *const ()) {
drop(Rc::from_raw(ptr as *const Task));
}
const VTABLE: RawWakerVTable =
RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop);
RawWaker::new(Rc::into_raw(this) as *const (), &VTABLE)
}
pub(crate) fn run(&self) {
let mut borrow = self.inner.borrow_mut();
let inner = match borrow.as_mut() {
Some(inner) => inner,
None => return,
};
self.is_queued.set(false);
let poll = {
let mut cx = Context::from_waker(&inner.waker);
inner.future.as_mut().poll(&mut cx)
};
if let Poll::Ready(_) = poll {
*borrow = None;
}
}
}