async_tick/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4mod interval;
5mod sleep;
6mod timeout;
7mod waiter;
8
9use core::time::Duration;
10use core::u64::MAX;
11pub use interval::*;
12pub use sleep::*;
13pub use timeout::*;
14use waiter::Waiter;
15
16const WAITS_NUM: usize = 64;
17static WAITS: Waiter<WAITS_NUM> = Waiter::new();
18
19/// Nanosecond since `app start time` or `os start time`
20pub fn now() -> u64 {
21    tick_clock::now()
22}
23
24pub struct Tick {
25    tick: tick_clock::Tick,
26}
27impl Tick {
28    /// returns nanosecond
29    pub fn tick(&mut self, interval: Duration) -> u64 {
30        let now = self.tick.tick(interval);
31        if let Some(next) = WAITS.take_next() {
32            if now < next {
33                WAITS.set_next(next);
34                return now;
35            }
36        } else {
37            return now;
38        }
39        let mut min = MAX;
40        WAITS.retain(|entity| {
41            if **entity <= now {
42                entity.wake();
43                false
44            } else {
45                min = min.min(**entity);
46                true
47            }
48        });
49        WAITS.set_next(min);
50        now
51    }
52}
53pub fn take_tick() -> Option<Tick> {
54    if let Some(tick) = tick_clock::take_tick() {
55        Some(Tick { tick })
56    } else {
57        None
58    }
59}
60
61#[cfg(feature = "std")]
62#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
63pub fn auto_tick(interval: Duration) {
64    use std::thread;
65    use std::time::Instant;
66
67    let mut ticker = take_tick().unwrap();
68    let mut last = Instant::now();
69    thread::Builder::new()
70        .name("async-tick".into())
71        .spawn(move || loop {
72            let now = Instant::now();
73            ticker.tick(now.saturating_duration_since(last));
74            last = now;
75            thread::sleep(interval);
76        })
77        .unwrap();
78}