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
|
use std::sync::Mutex;
use embassy_time_driver::Driver;
use embassy_time_queue_driver::Queue;
use wasm_bindgen::prelude::*;
use wasm_timer::Instant as StdInstant;
struct AlarmState {
token: Option<f64>,
}
impl AlarmState {
const fn new() -> Self {
Self { token: None }
}
}
#[wasm_bindgen]
extern "C" {
fn setTimeout(closure: &Closure<dyn FnMut()>, millis: u32) -> f64;
fn clearTimeout(token: f64);
}
struct TimeDriver {
inner: Mutex<Inner>,
}
struct Inner {
alarm: AlarmState,
zero_instant: Option<StdInstant>,
queue: Queue,
closure: Option<Closure<dyn FnMut()>>,
}
unsafe impl Send for Inner {}
embassy_time_driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver {
inner: Mutex::new(Inner{
zero_instant: None,
queue: Queue::new(),
alarm: AlarmState::new(),
closure: None,
}),
});
impl Inner {
fn init(&mut self) -> StdInstant {
*self.zero_instant.get_or_insert_with(StdInstant::now)
}
fn now(&mut self) -> u64 {
StdInstant::now().duration_since(self.zero_instant.unwrap()).as_micros() as u64
}
fn set_alarm(&mut self, timestamp: u64) -> bool {
if let Some(token) = self.alarm.token {
clearTimeout(token);
}
let now = self.now();
if timestamp <= now {
false
} else {
let timeout = (timestamp - now) as u32;
let closure = self.closure.get_or_insert_with(|| Closure::new(dispatch));
self.alarm.token = Some(setTimeout(closure, timeout / 1000));
true
}
}
}
impl Driver for TimeDriver {
fn now(&self) -> u64 {
let mut inner = self.inner.lock().unwrap();
let zero = inner.init();
StdInstant::now().duration_since(zero).as_micros() as u64
}
fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
let mut inner = self.inner.lock().unwrap();
inner.init();
if inner.queue.schedule_wake(at, waker) {
let now = inner.now();
let mut next = inner.queue.next_expiration(now);
while !inner.set_alarm(next) {
let now = inner.now();
next = inner.queue.next_expiration(now);
}
}
}
}
fn dispatch() {
let inner = &mut *DRIVER.inner.lock().unwrap();
let now = inner.now();
let mut next = inner.queue.next_expiration(now);
while !inner.set_alarm(next) {
let now = inner.now();
next = inner.queue.next_expiration(now);
}
}
|