cros_async/sys/linux/
timer.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use base::TimerTrait;
6
7use crate::AsyncError;
8use crate::AsyncResult;
9use crate::IntoAsync;
10use crate::TimerAsync;
11
12impl<T: TimerTrait + IntoAsync> TimerAsync<T> {
13    pub async fn wait_sys(&self) -> AsyncResult<()> {
14        let (n, _) = self
15            .io_source
16            .read_to_vec(None, 0u64.to_ne_bytes().to_vec())
17            .await?;
18        if n != 8 {
19            return Err(AsyncError::EventAsync(base::Error::new(libc::ENODATA)));
20        }
21        Ok(())
22    }
23}
24
25#[cfg(test)]
26mod tests {
27    use std::sync::Arc;
28    use std::time::Duration;
29    use std::time::Instant;
30
31    use base::Timer;
32
33    use super::super::fd_executor::EpollReactor;
34    use super::super::uring_executor::UringReactor;
35    use super::*;
36    use crate::common_executor::RawExecutor;
37    use crate::sys::linux::uring_executor::is_uring_stable;
38    use crate::Executor;
39    use crate::ExecutorTrait;
40
41    impl TimerAsync<Timer> {
42        pub(crate) fn new_poll(
43            timer: Timer,
44            ex: &Arc<RawExecutor<EpollReactor>>,
45        ) -> AsyncResult<TimerAsync<Timer>> {
46            ex.async_from(timer)
47                .map(|io_source| TimerAsync { io_source })
48        }
49
50        pub(crate) fn new_uring(
51            timer: Timer,
52            ex: &Arc<RawExecutor<UringReactor>>,
53        ) -> AsyncResult<TimerAsync<Timer>> {
54            ex.async_from(timer)
55                .map(|io_source| TimerAsync { io_source })
56        }
57    }
58
59    #[test]
60    fn timer() {
61        async fn this_test(ex: &Executor) {
62            let dur = Duration::from_millis(200);
63            let now = Instant::now();
64            TimerAsync::sleep(ex, dur).await.expect("unable to sleep");
65            assert!(now.elapsed() >= dur);
66        }
67
68        let ex = Executor::new().expect("creating an executor failed");
69        ex.run_until(this_test(&ex)).unwrap();
70    }
71
72    #[test]
73    fn one_shot() {
74        if !is_uring_stable() {
75            return;
76        }
77
78        async fn this_test(ex: &Arc<RawExecutor<UringReactor>>) {
79            let mut tfd = Timer::new().expect("failed to create timerfd");
80
81            let dur = Duration::from_millis(200);
82            let now = Instant::now();
83            tfd.reset_oneshot(dur).expect("failed to arm timer");
84
85            let t = TimerAsync::new_uring(tfd, ex).unwrap();
86            t.wait().await.expect("unable to wait for timer");
87
88            assert!(now.elapsed() >= dur);
89        }
90
91        let ex = RawExecutor::<UringReactor>::new().unwrap();
92        ex.run_until(this_test(&ex)).unwrap();
93    }
94
95    #[test]
96    fn one_shot_fd() {
97        async fn this_test(ex: &Arc<RawExecutor<EpollReactor>>) {
98            let mut tfd = Timer::new().expect("failed to create timerfd");
99
100            let dur = Duration::from_millis(200);
101            let now = Instant::now();
102            tfd.reset_oneshot(dur).expect("failed to arm timer");
103
104            let t = TimerAsync::new_poll(tfd, ex).unwrap();
105            t.wait().await.expect("unable to wait for timer");
106
107            assert!(now.elapsed() >= dur);
108        }
109
110        let ex = RawExecutor::<EpollReactor>::new().unwrap();
111        ex.run_until(this_test(&ex)).unwrap();
112    }
113}