Skip to main content

strontium_core/
futures.rs

1use 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}