autd3_driver/firmware/driver/async/
strategy.rs

1use std::time::{Duration, Instant};
2
3use crate::firmware::driver::{FixedDelay, FixedSchedule};
4use autd3_core::sleep::r#async::Sleep;
5
6/// A trait for timer strategies.
7pub trait TimerStrategy<S: Sleep>: Send {
8    /// Returns the initial instant.
9    fn initial(&self) -> Instant;
10    /// Sleep until the specified time.
11    /// The first call receives the return value of [`TimerStrategy::initial`] as `old`, and subsequent calls receive the previous return value.
12    fn sleep(
13        &self,
14        old: Instant,
15        interval: Duration,
16    ) -> impl std::future::Future<Output = Instant> + Send;
17}
18
19impl<S: Sleep> TimerStrategy<S> for FixedSchedule<S> {
20    fn initial(&self) -> Instant {
21        Instant::now()
22    }
23
24    async fn sleep(&self, old: Instant, interval: Duration) -> Instant {
25        let new = old + interval;
26        self.0
27            .sleep(new.saturating_duration_since(Instant::now()))
28            .await;
29        new
30    }
31}
32
33impl<S: Sleep> TimerStrategy<S> for FixedDelay<S> {
34    fn initial(&self) -> Instant {
35        Instant::now()
36    }
37
38    async fn sleep(&self, old: Instant, interval: Duration) -> Instant {
39        self.0.sleep(interval).await;
40        old
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use std::sync::{Arc, RwLock};
47
48    use super::*;
49
50    #[derive(Debug)]
51    struct DebugSleep {
52        sleep: Arc<RwLock<Vec<Duration>>>,
53    }
54
55    impl Sleep for DebugSleep {
56        async fn sleep(&self, duration: Duration) {
57            self.sleep.write().unwrap().push(duration);
58        }
59    }
60
61    #[tokio::test]
62    async fn fixed_schedule_test() {
63        let sleep = Arc::new(RwLock::new(Vec::new()));
64
65        let strategy = FixedSchedule(DebugSleep { sleep });
66
67        let start = strategy.initial();
68        let interval = Duration::from_millis(1);
69
70        let next = strategy.sleep(start, interval).await;
71        assert_eq!(next, start + interval);
72
73        let next = strategy.sleep(next, interval).await;
74        assert_eq!(next, start + interval * 2);
75    }
76
77    #[tokio::test]
78    async fn fixed_delay_test() {
79        let sleep = Arc::new(RwLock::new(Vec::new()));
80
81        let strategy = FixedDelay(DebugSleep {
82            sleep: sleep.clone(),
83        });
84
85        let start = strategy.initial();
86        let interval = Duration::from_millis(1);
87
88        let next = strategy.sleep(start, interval).await;
89        assert_eq!(next, start);
90
91        let next = strategy.sleep(start, interval).await;
92        assert_eq!(next, start);
93
94        assert_eq!(*sleep.read().unwrap(), vec![interval, interval]);
95    }
96}