1use core::cmp::Ordering;
8use std::cell::{Cell, RefCell};
9use std::future::Future;
10use std::pin::Pin;
11use std::rc::Rc;
12use std::task::{Context, Poll, Waker};
13
14use crate::traits::{Resolve, Resolver};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct ClockTick {
19 tick: u64,
21
22 #[cfg(feature = "phase")]
24 phase: u32,
25}
26
27impl ClockTick {
28 #[must_use]
29 pub fn new() -> Self {
30 Self {
31 tick: 0,
32
33 #[cfg(feature = "phase")]
34 phase: 0,
35 }
36 }
37
38 #[must_use]
40 pub fn tick(&self) -> u64 {
41 self.tick
42 }
43
44 #[must_use]
46 #[cfg(feature = "phase")]
47 pub fn phase(&self) -> u32 {
48 self.phase
49 }
50
51 pub fn set_tick(&mut self, tick: u64) -> ClockTick {
53 self.tick = tick;
54 *self
55 }
56
57 #[cfg(feature = "phase")]
59 pub fn set_phase(&mut self, phase: u32) -> ClockTick {
60 self.phase = phase;
61 *self
62 }
63}
64
65impl Default for ClockTick {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl Ord for ClockTick {
73 #[cfg(feature = "phase")]
74 fn cmp(&self, other: &Self) -> Ordering {
75 match self.tick.cmp(&other.tick) {
76 Ordering::Greater => Ordering::Greater,
77 Ordering::Less => Ordering::Less,
78 Ordering::Equal => self.phase.cmp(&other.phase),
79 }
80 }
81
82 #[cfg(not(feature = "phase"))]
83 fn cmp(&self, other: &Self) -> Ordering {
84 self.tick.cmp(&other.tick)
85 }
86}
87
88impl PartialOrd for ClockTick {
89 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
90 Some(self.cmp(other))
91 }
92}
93
94impl std::fmt::Display for ClockTick {
95 #[cfg(feature = "phase")]
96 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
97 write!(f, "{}.{:?}", self.tick, self.phase)
98 }
99 #[cfg(not(feature = "phase"))]
100 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
101 write!(f, "{}", self.tick)
102 }
103}
104
105#[derive(Clone)]
107pub struct Clock {
108 freq_mhz: f64,
111
112 pub shared_state: Rc<ClockState>,
113}
114
115pub struct TaskWaker {
116 pub id: u64,
118
119 pub waker: Waker,
121
122 pub can_exit: bool,
126}
127
128pub struct ClockState {
130 now: RefCell<ClockTick>,
131
132 next_waiter_id: Cell<u64>,
133
134 pub waiting: RefCell<Vec<Vec<TaskWaker>>>,
136
137 pub waiting_times: RefCell<Vec<ClockTick>>,
140
141 pub to_resolve: RefCell<Vec<Rc<dyn Resolve + 'static>>>,
143}
144
145impl ClockState {
146 fn schedule(&self, schedule_time: ClockTick, cx: &mut Context<'_>, can_exit: bool) -> u64 {
147 let waiter_id = self.next_waiter_id.get();
148 self.next_waiter_id.set(waiter_id + 1);
149
150 let mut waiting_times = self.waiting_times.borrow_mut();
151 let mut waiting = self.waiting.borrow_mut();
152 if let Some(index) = waiting_times.iter().position(|&x| x == schedule_time) {
153 waiting[index].push(TaskWaker {
155 id: waiter_id,
156 waker: cx.waker().clone(),
157 can_exit,
158 });
159 } else {
160 match waiting_times.iter().position(|x| *x < schedule_time) {
162 Some(index) => {
163 waiting_times.insert(index, schedule_time);
165 waiting.insert(
166 index,
167 vec![TaskWaker {
168 id: waiter_id,
169 waker: cx.waker().clone(),
170 can_exit,
171 }],
172 );
173 }
174 None => {
175 waiting_times.push(schedule_time);
177 waiting.push(vec![TaskWaker {
178 id: waiter_id,
179 waker: cx.waker().clone(),
180 can_exit,
181 }]);
182 }
183 }
184 }
185
186 waiter_id
187 }
188
189 fn unschedule(&self, schedule_time: ClockTick, waiter_id: u64) {
190 let mut waiting_times = self.waiting_times.borrow_mut();
191 let mut waiting = self.waiting.borrow_mut();
192
193 if let Some(time_index) = waiting_times.iter().position(|&x| x == schedule_time)
194 && let Some(waiter_index) = waiting[time_index].iter().position(|w| w.id == waiter_id)
195 {
196 waiting[time_index].remove(waiter_index);
197 if waiting[time_index].is_empty() {
198 waiting.remove(time_index);
199 waiting_times.remove(time_index);
200 }
201 }
202 }
203
204 fn advance_time(&self, to_time: ClockTick) {
205 self.resolve();
206
207 assert!(to_time >= *self.now.borrow(), "Time moving backwards");
208 *self.now.borrow_mut() = to_time;
209 }
210
211 fn resolve(&self) {
212 for r in self.to_resolve.borrow_mut().drain(..) {
213 r.resolve();
214 }
215 }
216}
217
218impl Clock {
219 #[must_use]
221 pub fn new(freq_mhz: f64) -> Self {
222 let shared_state = Rc::new(ClockState {
223 now: RefCell::new(ClockTick {
224 tick: 0,
225 #[cfg(feature = "phase")]
226 phase: 0,
227 }),
228 next_waiter_id: Cell::new(0),
229 waiting: RefCell::new(Vec::new()),
230 waiting_times: RefCell::new(Vec::new()),
231 to_resolve: RefCell::new(Vec::new()),
232 });
233
234 Self {
235 freq_mhz,
236 shared_state,
237 }
238 }
239
240 pub fn advance_time(&self, to_time: ClockTick) {
242 self.shared_state.advance_time(to_time);
243 }
244
245 #[must_use]
247 pub fn freq_mhz(&self) -> f64 {
248 self.freq_mhz
249 }
250
251 #[must_use]
253 pub fn tick_now(&self) -> ClockTick {
254 *self.shared_state.now.borrow()
255 }
256
257 #[must_use]
259 pub fn time_now_ns(&self) -> f64 {
260 let now = *self.shared_state.now.borrow();
261 self.to_ns(&now)
262 }
263
264 #[must_use]
266 pub fn time_of_next(&self) -> f64 {
267 match self.shared_state.waiting_times.borrow().first() {
268 Some(clock_time) => self.to_ns(clock_time),
269 None => f64::MAX,
270 }
271 }
272
273 #[must_use]
275 pub fn to_ns(&self, clock_time: &ClockTick) -> f64 {
276 clock_time.tick as f64 / self.freq_mhz * 1000.0
277 }
278
279 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
282 pub fn wait_ticks(&self, ticks: u64) -> ClockDelay {
283 let mut until = self.tick_now();
284 until.tick += ticks;
285 ClockDelay {
286 shared_state: self.shared_state.clone(),
287 until,
288 can_exit: false,
289 waiter_id: None,
290 }
291 }
292
293 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
299 pub fn wait_ticks_or_exit(&self, ticks: u64) -> ClockDelay {
300 let mut until = self.tick_now();
301 until.tick += ticks;
302 ClockDelay {
303 shared_state: self.shared_state.clone(),
304 until,
305 can_exit: true,
306 waiter_id: None,
307 }
308 }
309
310 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
311 #[cfg(feature = "phase")]
312 pub fn next_tick_and_phase(&self, phase: u32) -> ClockDelay {
313 let mut until = self.tick_now();
314 until.tick += 1;
315 until.phase = phase;
316 ClockDelay {
317 shared_state: self.shared_state.clone(),
318 until,
319 can_exit: false,
320 waiter_id: None,
321 }
322 }
323
324 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
325 #[cfg(feature = "phase")]
326 pub fn wait_phase(&self, phase: u32) -> ClockDelay {
327 let mut until = self.tick_now();
328 assert!(phase > until.phase, "Time going backwards");
329 until.phase = phase;
330 ClockDelay {
331 shared_state: self.shared_state.clone(),
332 until,
333 can_exit: false,
334 waiter_id: None,
335 }
336 }
337
338 pub fn advance_to(&self, time_ns: f64) {
340 let now_ns = self.time_now_ns();
341 assert!(now_ns < time_ns);
342 let diff_ns = time_ns - now_ns;
343 let ticks = (diff_ns * (self.freq_mhz / 1000.0)).ceil();
344
345 let mut until = self.tick_now();
346 until.tick += ticks as u64;
347
348 self.shared_state.advance_time(until);
349 }
350}
351
352impl Default for Clock {
354 fn default() -> Self {
355 Self::new(1000.0)
356 }
357}
358
359impl PartialEq for Clock {
361 fn eq(&self, other: &Self) -> bool {
362 self.time_of_next() == other.time_of_next()
363 }
364}
365impl Eq for Clock {}
366
367impl Ord for Clock {
368 fn cmp(&self, other: &Self) -> Ordering {
369 if self.time_of_next() < other.time_of_next() {
370 Ordering::Less
371 } else {
372 Ordering::Greater
373 }
374 }
375}
376
377impl PartialOrd for Clock {
378 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
379 Some(self.cmp(other))
380 }
381}
382
383impl Resolver for Clock {
384 fn add_resolve(&self, resolve: Rc<dyn Resolve + 'static>) {
385 self.shared_state.to_resolve.borrow_mut().push(resolve);
386 }
387}
388
389pub struct ClockDelay {
391 shared_state: Rc<ClockState>,
392 until: ClockTick,
393 can_exit: bool,
394 waiter_id: Option<u64>,
395}
396
397impl Future for ClockDelay {
398 type Output = ();
399 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
400 if self.until > *self.shared_state.now.borrow() {
401 if let Some(waiter_id) = self.waiter_id {
402 self.shared_state.unschedule(self.until, waiter_id);
403 }
404 let waiter_id = self.shared_state.schedule(self.until, cx, self.can_exit);
405 self.waiter_id = Some(waiter_id);
406 Poll::Pending
407 } else {
408 self.waiter_id = None;
409 Poll::Ready(())
410 }
411 }
412}
413
414impl Drop for ClockDelay {
415 fn drop(&mut self) {
416 if let Some(waiter_id) = self.waiter_id.take() {
417 self.shared_state.unschedule(self.until, waiter_id);
418 }
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 fn convert_to_ns() {
428 let clk_ghz = Clock::new(1000.0);
429 assert_eq!(1.0, clk_ghz.to_ns(&ClockTick::new().set_tick(1)));
430
431 let slow_clk = Clock::new(0.5);
432 assert_eq!(2000.0, slow_clk.to_ns(&ClockTick::new().set_tick(1)));
433 }
434}