Skip to main content

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