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 futures::future::FusedFuture;
15
16use crate::traits::{Resolve, Resolver};
17
18pub mod phase {
19 pub const BEGIN: u32 = 0;
20 pub const END: u32 = u32::MAX;
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub struct ClockTick {
26 tick: u64,
28
29 phase: u32,
31}
32
33impl ClockTick {
34 #[must_use]
35 pub fn new() -> Self {
36 Self {
37 tick: 0,
38 phase: phase::BEGIN,
39 }
40 }
41
42 #[must_use]
44 pub fn tick(&self) -> u64 {
45 self.tick
46 }
47
48 #[must_use]
50 pub fn phase(&self) -> u32 {
51 self.phase
52 }
53
54 pub fn set_tick(&mut self, tick: u64) -> ClockTick {
56 self.tick = tick;
57 *self
58 }
59
60 pub fn set_phase(&mut self, phase: u32) -> ClockTick {
62 self.phase = phase;
63 *self
64 }
65}
66
67impl Default for ClockTick {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl Ord for ClockTick {
75 fn cmp(&self, other: &Self) -> Ordering {
76 match self.tick.cmp(&other.tick) {
77 Ordering::Greater => Ordering::Greater,
78 Ordering::Less => Ordering::Less,
79 Ordering::Equal => self.phase.cmp(&other.phase),
80 }
81 }
82}
83
84impl PartialOrd for ClockTick {
85 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
86 Some(self.cmp(other))
87 }
88}
89
90impl std::fmt::Display for ClockTick {
91 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
92 write!(f, "{}.{:?}", self.tick, self.phase)
93 }
94}
95
96#[derive(Clone)]
98pub struct Clock {
99 freq_mhz: f64,
102
103 pub shared_state: Rc<ClockState>,
104}
105
106pub struct TaskWaker {
107 pub id: u64,
109
110 pub waker: Waker,
112
113 pub can_exit: bool,
117}
118
119pub struct ClockState {
121 now: RefCell<ClockTick>,
122
123 next_waiter_id: Cell<u64>,
124
125 pub waiting: RefCell<Vec<Vec<TaskWaker>>>,
127
128 pub waiting_times: RefCell<Vec<ClockTick>>,
131
132 pub to_resolve: RefCell<Vec<Rc<dyn Resolve + 'static>>>,
134}
135
136impl ClockState {
137 fn schedule(&self, schedule_time: ClockTick, cx: &mut Context<'_>, can_exit: bool) -> u64 {
138 let waiter_id = self.next_waiter_id.get();
139 self.next_waiter_id.set(waiter_id + 1);
140
141 let mut waiting_times = self.waiting_times.borrow_mut();
142 let mut waiting = self.waiting.borrow_mut();
143 if let Some(index) = waiting_times.iter().position(|&x| x == schedule_time) {
144 waiting[index].push(TaskWaker {
146 id: waiter_id,
147 waker: cx.waker().clone(),
148 can_exit,
149 });
150 } else {
151 match waiting_times.iter().position(|x| *x < schedule_time) {
153 Some(index) => {
154 waiting_times.insert(index, schedule_time);
156 waiting.insert(
157 index,
158 vec![TaskWaker {
159 id: waiter_id,
160 waker: cx.waker().clone(),
161 can_exit,
162 }],
163 );
164 }
165 None => {
166 waiting_times.push(schedule_time);
168 waiting.push(vec![TaskWaker {
169 id: waiter_id,
170 waker: cx.waker().clone(),
171 can_exit,
172 }]);
173 }
174 }
175 }
176
177 waiter_id
178 }
179
180 fn unschedule(&self, schedule_time: ClockTick, waiter_id: u64) {
181 let mut waiting_times = self.waiting_times.borrow_mut();
182 let mut waiting = self.waiting.borrow_mut();
183
184 if let Some(time_index) = waiting_times.iter().position(|&x| x == schedule_time)
185 && let Some(waiter_index) = waiting[time_index].iter().position(|w| w.id == waiter_id)
186 {
187 waiting[time_index].remove(waiter_index);
188 if waiting[time_index].is_empty() {
189 waiting.remove(time_index);
190 waiting_times.remove(time_index);
191 }
192 }
193 }
194
195 fn advance_time(&self, to_time: ClockTick) {
196 self.resolve();
197
198 assert!(to_time >= *self.now.borrow(), "Time moving backwards");
199 *self.now.borrow_mut() = to_time;
200 }
201
202 fn resolve(&self) {
203 for r in self.to_resolve.borrow_mut().drain(..) {
204 r.resolve();
205 }
206 }
207}
208
209impl Clock {
210 #[must_use]
212 pub fn new(freq_mhz: f64) -> Self {
213 let shared_state = Rc::new(ClockState {
214 now: RefCell::new(ClockTick {
215 tick: 0,
216 phase: phase::BEGIN,
217 }),
218 next_waiter_id: Cell::new(0),
219 waiting: RefCell::new(Vec::new()),
220 waiting_times: RefCell::new(Vec::new()),
221 to_resolve: RefCell::new(Vec::new()),
222 });
223
224 Self {
225 freq_mhz,
226 shared_state,
227 }
228 }
229
230 pub fn advance_time(&self, to_time: ClockTick) {
232 self.shared_state.advance_time(to_time);
233 }
234
235 #[must_use]
237 pub fn freq_mhz(&self) -> f64 {
238 self.freq_mhz
239 }
240
241 #[must_use]
243 pub fn tick_now(&self) -> ClockTick {
244 *self.shared_state.now.borrow()
245 }
246
247 #[must_use]
249 pub fn time_now_ns(&self) -> f64 {
250 let now = *self.shared_state.now.borrow();
251 self.to_ns(&now)
252 }
253
254 #[must_use]
256 pub fn time_of_next(&self) -> f64 {
257 match self.shared_state.waiting_times.borrow().last() {
258 Some(clock_time) => self.to_ns(clock_time),
259 None => f64::MAX,
260 }
261 }
262
263 #[must_use]
265 pub fn phase_of_next(&self) -> u32 {
266 match self.shared_state.waiting_times.borrow().last() {
267 Some(clock_time) => clock_time.phase(),
268 None => u32::MAX,
269 }
270 }
271
272 #[must_use]
274 pub fn to_ns(&self, clock_time: &ClockTick) -> f64 {
275 clock_time.tick as f64 / self.freq_mhz * 1000.0
276 }
277
278 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
281 pub fn wait_ticks(&self, ticks: u64) -> ClockDelay {
282 let mut until = self.tick_now();
283 until.tick += ticks;
284 until.phase = phase::BEGIN;
285 ClockDelay {
286 shared_state: self.shared_state.clone(),
287 until,
288 can_exit: false,
289 waiter_id: None,
290 done: false,
291 }
292 }
293
294 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
300 pub fn wait_ticks_or_exit(&self, ticks: u64) -> ClockDelay {
301 let mut until = self.tick_now();
302 until.tick += ticks;
303 until.phase = phase::BEGIN;
304 ClockDelay {
305 shared_state: self.shared_state.clone(),
306 until,
307 can_exit: true,
308 waiter_id: None,
309 done: false,
310 }
311 }
312
313 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
314 pub fn next_tick_and_phase(&self, phase: u32) -> ClockDelay {
315 let mut until = self.tick_now();
316 until.tick += 1;
317 until.phase = phase;
318 ClockDelay {
319 shared_state: self.shared_state.clone(),
320 until,
321 can_exit: false,
322 waiter_id: None,
323 done: false,
324 }
325 }
326
327 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
328 pub fn wait_phase(&self, phase: u32) -> ClockDelay {
329 let mut until = self.tick_now();
330 assert!(phase >= until.phase, "Time going backwards");
331 until.phase = phase;
332 ClockDelay {
333 shared_state: self.shared_state.clone(),
334 until,
335 can_exit: false,
336 waiter_id: None,
337 done: false,
338 }
339 }
340
341 pub fn advance_to(&self, time_ns: f64) {
343 let now_ns = self.time_now_ns();
344 assert!(now_ns < time_ns);
345 let diff_ns = time_ns - now_ns;
346 let ticks = (diff_ns * (self.freq_mhz / 1000.0)).ceil();
347
348 let mut until = self.tick_now();
349 until.tick += ticks as u64;
350 until.phase = phase::BEGIN;
351
352 self.shared_state.advance_time(until);
353 }
354}
355
356impl Default for Clock {
358 fn default() -> Self {
359 Self::new(1000.0)
360 }
361}
362
363impl PartialEq for Clock {
365 fn eq(&self, other: &Self) -> bool {
366 self.time_of_next() == other.time_of_next() && self.phase_of_next() == other.phase_of_next()
367 }
368}
369impl Eq for Clock {}
370
371impl Ord for Clock {
372 fn cmp(&self, other: &Self) -> Ordering {
373 self.time_of_next()
374 .total_cmp(&other.time_of_next())
375 .then_with(|| self.phase_of_next().cmp(&other.phase_of_next()))
376 }
377}
378
379impl PartialOrd for Clock {
380 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
381 Some(self.cmp(other))
382 }
383}
384
385impl Resolver for Clock {
386 fn add_resolve(&self, resolve: Rc<dyn Resolve + 'static>) {
387 self.shared_state.to_resolve.borrow_mut().push(resolve);
388 }
389}
390
391pub struct ClockDelay {
393 shared_state: Rc<ClockState>,
394 until: ClockTick,
395 can_exit: bool,
396 waiter_id: Option<u64>,
397 done: bool,
398}
399
400impl Future for ClockDelay {
401 type Output = ();
402 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
403 if self.done {
404 return Poll::Ready(());
405 }
406
407 if self.until > *self.shared_state.now.borrow() {
408 if let Some(waiter_id) = self.waiter_id {
409 self.shared_state.unschedule(self.until, waiter_id);
410 }
411 let waiter_id = self.shared_state.schedule(self.until, cx, self.can_exit);
412 self.waiter_id = Some(waiter_id);
413 Poll::Pending
414 } else {
415 self.waiter_id = None;
416 self.done = true;
417 Poll::Ready(())
418 }
419 }
420}
421
422impl FusedFuture for ClockDelay {
423 fn is_terminated(&self) -> bool {
424 self.done
425 }
426}
427
428impl Drop for ClockDelay {
429 fn drop(&mut self) {
430 if let Some(waiter_id) = self.waiter_id.take() {
431 self.shared_state.unschedule(self.until, waiter_id);
432 }
433 }
434}
435
436#[cfg(test)]
437mod tests {
438 use std::mem::drop;
439 use std::pin::Pin;
440 use std::task::Context;
441
442 use futures::future::FusedFuture;
443 use futures::task::noop_waker;
444
445 use super::*;
446
447 #[test]
448 fn convert_to_ns() {
449 let clk_ghz = Clock::new(1000.0);
450 assert_eq!(1.0, clk_ghz.to_ns(&ClockTick::new().set_tick(1)));
451
452 let slow_clk = Clock::new(0.5);
453 assert_eq!(2000.0, slow_clk.to_ns(&ClockTick::new().set_tick(1)));
454 }
455
456 #[test]
457 fn clock_tick_accessors_default_display_and_ordering() {
458 let default_tick = ClockTick::default();
459 assert_eq!(default_tick.tick(), 0);
460 assert_eq!(default_tick.phase(), phase::BEGIN);
461 assert_eq!(default_tick.to_string(), "0.0");
462
463 let earlier = ClockTick::new().set_tick(1);
464 let later = ClockTick::new().set_tick(2);
465 assert!(earlier < later);
466 assert_eq!(earlier.partial_cmp(&later), Some(Ordering::Less));
467 }
468
469 #[test]
470 fn clock_tick_phase_accessors_display_and_ordering() {
471 let tick = ClockTick::new().set_tick(1).set_phase(2);
472 assert_eq!(tick.phase(), 2);
473 assert_eq!(tick.to_string(), "1.2");
474
475 let earlier_phase = ClockTick::new().set_tick(1).set_phase(1);
476 assert!(earlier_phase < tick);
477
478 let later_tick = ClockTick::new().set_tick(2).set_phase(0);
479 assert!(later_tick > tick);
480 }
481
482 #[test]
483 fn clock_default_advance_and_ordering() {
484 let clock = Clock::default();
485 assert_eq!(clock.freq_mhz(), 1000.0);
486
487 clock.advance_to(2.1);
488 assert_eq!(clock.tick_now().tick(), 3);
489 assert_eq!(clock.tick_now().phase(), phase::BEGIN);
490 assert_eq!(clock.time_now_ns(), 3.0);
491
492 let earlier = Clock::new(1000.0);
493 let later = Clock::new(1000.0);
494 drop(earlier.wait_ticks(1));
495 drop(later.wait_ticks(2));
496
497 assert!(earlier == later);
498 assert_eq!(earlier.partial_cmp(&later), Some(Ordering::Equal));
499 }
500
501 #[test]
502 fn unschedule_unknown_waiter_is_a_noop() {
503 let clock = Clock::new(1000.0);
504 let scheduled_time = ClockTick::new().set_tick(1);
505
506 clock
507 .shared_state
508 .waiting_times
509 .borrow_mut()
510 .push(scheduled_time);
511 clock.shared_state.waiting.borrow_mut().push(Vec::new());
512
513 clock.shared_state.unschedule(scheduled_time, 7);
514
515 assert_eq!(clock.shared_state.waiting_times.borrow().len(), 1);
516 assert_eq!(clock.shared_state.waiting.borrow().len(), 1);
517 }
518
519 #[test]
520 fn unschedule_waiter_keeps_time_when_other_waiters_remain() {
521 let clock = Clock::new(1000.0);
522 let scheduled_time = ClockTick::new().set_tick(1);
523 let waker = noop_waker();
524 let mut cx = Context::from_waker(&waker);
525
526 let first_waiter_id = clock.shared_state.schedule(scheduled_time, &mut cx, false);
527 let second_waiter_id = clock.shared_state.schedule(scheduled_time, &mut cx, false);
528
529 clock
530 .shared_state
531 .unschedule(scheduled_time, first_waiter_id);
532
533 let waiting_times = clock.shared_state.waiting_times.borrow();
534 let waiting = clock.shared_state.waiting.borrow();
535
536 assert_eq!(waiting_times.as_slice(), &[scheduled_time]);
537 assert_eq!(waiting.len(), 1);
538 assert_eq!(waiting[0].len(), 1);
539 assert_eq!(waiting[0][0].id, second_waiter_id);
540 }
541
542 #[test]
543 fn clock_delay_is_fused_after_completion() {
544 let clock = Clock::new(1000.0);
545 let waker = noop_waker();
546 let mut cx = Context::from_waker(&waker);
547 let mut delay = clock.wait_ticks(1);
548
549 assert!(!delay.is_terminated());
550 assert_eq!(Pin::new(&mut delay).poll(&mut cx), Poll::Pending);
551 assert!(!delay.is_terminated());
552
553 clock.advance_time(ClockTick::new().set_tick(1));
554 assert_eq!(Pin::new(&mut delay).poll(&mut cx), Poll::Ready(()));
555 assert!(delay.is_terminated());
556 assert_eq!(Pin::new(&mut delay).poll(&mut cx), Poll::Ready(()));
557 assert!(delay.is_terminated());
558 }
559
560 #[test]
561 fn phase_wait_helpers_schedule_phase_delays() {
562 let clock = Clock::new(1000.0);
563
564 let next_tick = clock.next_tick_and_phase(3);
565 assert_eq!(next_tick.until.tick(), 1);
566 assert_eq!(next_tick.until.phase(), 3);
567
568 let same_tick = clock.wait_phase(1);
569 assert_eq!(same_tick.until.tick(), 0);
570 assert_eq!(same_tick.until.phase(), 1);
571 }
572
573 #[test]
574 fn tick_waits_resume_in_end_phase() {
575 let clock = Clock::new(1000.0);
576
577 let begin = clock.wait_phase(phase::END);
578 assert_eq!(begin.until.tick(), 0);
579 assert_eq!(begin.until.phase(), phase::END);
580
581 clock.advance_time(ClockTick::new().set_phase(phase::END));
582
583 let delay = clock.wait_ticks(1);
584 assert_eq!(delay.until.tick(), 1);
585 assert_eq!(delay.until.phase(), phase::BEGIN);
586 }
587}