strontium_core/
futures.rs1use crate::clock::Clock;
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::{Arc, Mutex};
5use std::task::Poll;
6use std::time::Duration;
7
8pub(crate) struct SimSleep {
9 pub(crate) duration: Duration,
10 pub(crate) deadline: Option<Duration>,
11 pub(crate) clock: Arc<Mutex<Clock>>,
12}
13
14impl Future for SimSleep {
15 type Output = ();
16
17 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()> {
18 let this = self.get_mut();
19 let mut clock = this.clock.lock().expect("sim clock");
20
21 if this.deadline.is_none() {
22 this.deadline = Some(clock.now + this.duration);
23 }
24 let deadline = this.deadline.expect("deadline");
25
26 if clock.now >= deadline {
27 return Poll::Ready(());
28 }
29
30 clock.register_timer(deadline, cx.waker().clone());
31 Poll::Pending
32 }
33}
34
35pub struct Interval {
36 duration: Duration,
37 next_deadline: Duration,
38 clock: Arc<Mutex<Clock>>,
39}
40
41impl Interval {
42 pub(crate) fn new(
43 duration: Duration,
44 next_deadline: Duration,
45 clock: Arc<Mutex<Clock>>,
46 ) -> Self {
47 Self {
48 duration,
49 next_deadline,
50 clock,
51 }
52 }
53
54 pub fn tick(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
55 Box::pin(IntervalFuture { interval: self })
56 }
57}
58
59struct IntervalFuture<'a> {
60 interval: &'a mut Interval,
61}
62
63impl<'a> Future for IntervalFuture<'a> {
64 type Output = ();
65
66 fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()> {
67 let now = { self.interval.clock.lock().expect("sim clock").now };
68 if now >= self.interval.next_deadline {
69 self.interval.next_deadline = now + self.interval.duration;
70 return Poll::Ready(());
71 }
72 self.interval
73 .clock
74 .lock()
75 .expect("sim clock")
76 .register_timer(self.interval.next_deadline, cx.waker().clone());
77 Poll::Pending
78 }
79}
80
81pub(crate) struct SimYield {
82 pub(crate) yielded: bool,
83}
84
85impl Future for SimYield {
86 type Output = ();
87
88 fn poll(mut self: Pin<&mut Self>, _cx: &mut std::task::Context<'_>) -> Poll<()> {
89 if self.yielded {
90 Poll::Ready(())
91 } else {
92 self.yielded = true;
93 Poll::Pending
94 }
95 }
96}