1 // Copyright 2020 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::time::Duration; 6 7 use sys_util::{Result as SysResult, TimerFd}; 8 9 use crate::{AsyncResult, Executor, IntoAsync, IoSourceExt}; 10 #[cfg(test)] 11 use crate::{FdExecutor, URingExecutor}; 12 13 /// An async version of sys_util::TimerFd. 14 pub struct TimerAsync { 15 io_source: Box<dyn IoSourceExt<TimerFd>>, 16 } 17 18 impl TimerAsync { new(timer: TimerFd, ex: &Executor) -> AsyncResult<TimerAsync>19 pub fn new(timer: TimerFd, ex: &Executor) -> AsyncResult<TimerAsync> { 20 ex.async_from(timer) 21 .map(|io_source| TimerAsync { io_source }) 22 } 23 24 #[cfg(test)] new_poll(timer: TimerFd, ex: &FdExecutor) -> AsyncResult<TimerAsync>25 pub(crate) fn new_poll(timer: TimerFd, ex: &FdExecutor) -> AsyncResult<TimerAsync> { 26 crate::executor::async_poll_from(timer, ex).map(|io_source| TimerAsync { io_source }) 27 } 28 29 #[cfg(test)] new_uring(timer: TimerFd, ex: &URingExecutor) -> AsyncResult<TimerAsync>30 pub(crate) fn new_uring(timer: TimerFd, ex: &URingExecutor) -> AsyncResult<TimerAsync> { 31 crate::executor::async_uring_from(timer, ex).map(|io_source| TimerAsync { io_source }) 32 } 33 34 /// Gets the next value from the timer. next_val(&self) -> AsyncResult<u64>35 pub async fn next_val(&self) -> AsyncResult<u64> { 36 self.io_source.read_u64().await 37 } 38 39 /// Sets the timer to expire after `dur`. If `interval` is not `None` it represents 40 /// the period for repeated expirations after the initial expiration. Otherwise 41 /// the timer will expire just once. Cancels any existing duration and repeating interval. reset(&mut self, dur: Duration, interval: Option<Duration>) -> SysResult<()>42 pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> SysResult<()> { 43 self.io_source.as_source_mut().reset(dur, interval) 44 } 45 } 46 47 impl IntoAsync for TimerFd {} 48 49 #[cfg(test)] 50 mod tests { 51 use super::*; 52 use std::time::{Duration, Instant}; 53 54 #[test] one_shot()55 fn one_shot() { 56 async fn this_test(ex: &URingExecutor) -> () { 57 let tfd = TimerFd::new().expect("failed to create timerfd"); 58 assert_eq!(tfd.is_armed().unwrap(), false); 59 60 let dur = Duration::from_millis(200); 61 let now = Instant::now(); 62 tfd.reset(dur, None).expect("failed to arm timer"); 63 64 assert_eq!(tfd.is_armed().unwrap(), true); 65 66 let t = TimerAsync::new_uring(tfd, ex).unwrap(); 67 let count = t.next_val().await.expect("unable to wait for timer"); 68 69 assert_eq!(count, 1); 70 assert!(now.elapsed() >= dur); 71 } 72 73 let ex = URingExecutor::new().unwrap(); 74 ex.run_until(this_test(&ex)).unwrap(); 75 } 76 77 #[test] one_shot_fd()78 fn one_shot_fd() { 79 async fn this_test(ex: &FdExecutor) -> () { 80 let tfd = TimerFd::new().expect("failed to create timerfd"); 81 assert_eq!(tfd.is_armed().unwrap(), false); 82 83 let dur = Duration::from_millis(200); 84 let now = Instant::now(); 85 tfd.reset(dur, None).expect("failed to arm timer"); 86 87 assert_eq!(tfd.is_armed().unwrap(), true); 88 89 let t = TimerAsync::new_poll(tfd, ex).unwrap(); 90 let count = t.next_val().await.expect("unable to wait for timer"); 91 92 assert_eq!(count, 1); 93 assert!(now.elapsed() >= dur); 94 } 95 96 let ex = FdExecutor::new().unwrap(); 97 ex.run_until(this_test(&ex)).unwrap(); 98 } 99 } 100