Skip to main content

rtc_interval/
lib.rs

1#[cfg(feature = "async")]
2pub use async_interval::AsyncRtcInterval;
3
4use std::time::Duration;
5
6use bma_ts::Timestamp;
7
8pub struct RtcInterval {
9    interval: rtsc::time::Interval,
10    d: Duration,
11    tick_prev: u64,
12}
13
14impl RtcInterval {
15    pub fn new(d: Duration) -> Self {
16        let mut interval = rtsc::time::interval(if d >= Duration::from_secs(1) {
17            Duration::from_millis(200)
18        } else {
19            d
20        });
21        interval = interval.set_missing_tick_behavior(rtsc::time::MissedTickBehavior::Skip);
22        Self {
23            interval,
24            d,
25            tick_prev: 0,
26        }
27    }
28    pub fn tick(&mut self) -> Timestamp {
29        if self.d >= Duration::from_secs(1) {
30            loop {
31                self.interval.tick();
32                let t_secs = Timestamp::now().as_secs();
33                if t_secs.is_multiple_of(self.d.as_secs()) && t_secs != self.tick_prev {
34                    self.tick_prev = t_secs;
35                    break Timestamp::from_secs(t_secs);
36                }
37            }
38        } else {
39            self.interval.tick();
40            Timestamp::now()
41        }
42    }
43}
44
45#[cfg(feature = "async")]
46mod async_interval {
47    use std::time::Duration;
48
49    use bma_ts::Timestamp;
50
51    pub struct AsyncRtcInterval {
52        interval: tokio::time::Interval,
53        d: Duration,
54        tick_prev: u64,
55    }
56
57    impl AsyncRtcInterval {
58        pub fn new(d: Duration) -> Self {
59            let mut interval = tokio::time::interval(if d >= Duration::from_secs(1) {
60                Duration::from_millis(200)
61            } else {
62                d
63            });
64            interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
65            Self {
66                interval,
67                d,
68                tick_prev: 0,
69            }
70        }
71        pub async fn tick(&mut self) -> Timestamp {
72            if self.d >= Duration::from_secs(1) {
73                loop {
74                    self.interval.tick().await;
75                    let t_secs = Timestamp::now().as_secs();
76                    if t_secs.is_multiple_of(self.d.as_secs()) && t_secs != self.tick_prev {
77                        self.tick_prev = t_secs;
78                        break Timestamp::from_secs(t_secs);
79                    }
80                }
81            } else {
82                self.interval.tick().await;
83                Timestamp::now()
84            }
85        }
86    }
87}