File: timer.rs

package info (click to toggle)
rust-async-io 2.3.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 388 kB
  • sloc: makefile: 2
file content (99 lines) | stat: -rw-r--r-- 2,629 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};

use async_io::Timer;
use futures_lite::{future, FutureExt, StreamExt};

fn spawn<T: Send + 'static>(
    f: impl Future<Output = T> + Send + 'static,
) -> impl Future<Output = T> + Send + 'static {
    let (s, r) = async_channel::bounded(1);

    thread::spawn(move || {
        future::block_on(async {
            s.send(f.await).await.ok();
        })
    });

    Box::pin(async move { r.recv().await.unwrap() })
}

#[test]
fn smoke() {
    future::block_on(async {
        let start = Instant::now();
        Timer::after(Duration::from_secs(1)).await;
        assert!(start.elapsed() >= Duration::from_secs(1));
    });
}

#[test]
fn interval() {
    future::block_on(async {
        let period = Duration::from_secs(1);
        let jitter = Duration::from_millis(500);
        let start = Instant::now();
        let mut timer = Timer::interval(period);
        timer.next().await;
        let elapsed = start.elapsed();
        assert!(elapsed >= period && elapsed - period < jitter);
        timer.next().await;
        let elapsed = start.elapsed();
        assert!(elapsed >= period * 2 && elapsed - period * 2 < jitter);
    });
}

#[test]
fn poll_across_tasks() {
    future::block_on(async {
        let start = Instant::now();
        let (sender, receiver) = async_channel::bounded(1);

        let task1 = spawn(async move {
            let mut timer = Timer::after(Duration::from_secs(1));

            async {
                (&mut timer).await;
                panic!("timer should not be ready")
            }
            .or(async {})
            .await;

            sender.send(timer).await.ok();
        });

        let task2 = spawn(async move {
            let timer = receiver.recv().await.unwrap();
            timer.await;
        });

        task1.await;
        task2.await;

        assert!(start.elapsed() >= Duration::from_secs(1));
    });
}

#[test]
fn set() {
    future::block_on(async {
        let start = Instant::now();
        let timer = Arc::new(Mutex::new(Timer::after(Duration::from_secs(10))));

        thread::spawn({
            let timer = timer.clone();
            move || {
                thread::sleep(Duration::from_secs(1));
                timer.lock().unwrap().set_after(Duration::from_secs(2));
            }
        });

        future::poll_fn(|cx| Pin::new(&mut *timer.lock().unwrap()).poll(cx)).await;

        assert!(start.elapsed() >= Duration::from_secs(2));
        assert!(start.elapsed() < Duration::from_secs(10));
    });
}