cros_async: Add TimerAsync::sleep

to reduce boilerplate code.

BUG=None
TEST=cargo test

Change-Id: Ia1485b63453145e0b0dfaa6730caee34b52bc0b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2960408
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Commit-Queue: Woody Chow <woodychow@google.com>
This commit is contained in:
Woody Chow 2021-06-14 15:49:54 +09:00 committed by Commit Bot
parent bb95fc4512
commit e6bf005d26
2 changed files with 30 additions and 1 deletions

View file

@ -83,6 +83,7 @@ pub use io_ext::{
pub use mem::{BackingMemory, MemRegion};
pub use poll_source::PollSource;
pub use select::SelectResult;
pub use sys_util;
pub use timer::TimerAsync;
pub use uring_executor::URingExecutor;
pub use uring_source::UringSource;
@ -102,6 +103,12 @@ pub enum Error {
/// Error from the uring executor.
#[error("Failure in the uring executor: {0}")]
URingExecutor(uring_executor::Error),
/// Error from TimerFd.
#[error("Failure in TimerFd: {0}")]
TimerFd(sys_util::Error),
/// Error from TimerFd.
#[error("Failure in TimerAsync: {0}")]
TimerAsync(AsyncError),
}
pub type Result<T> = std::result::Result<T, Error>;

View file

@ -6,7 +6,7 @@ use std::time::Duration;
use sys_util::{Result as SysResult, TimerFd};
use crate::{AsyncResult, Executor, IntoAsync, IoSourceExt};
use crate::{AsyncResult, Error, Executor, IntoAsync, IoSourceExt};
#[cfg(test)]
use crate::{FdExecutor, URingExecutor};
@ -36,6 +36,15 @@ impl TimerAsync {
self.io_source.read_u64().await
}
/// Async sleep for the given duration
pub async fn sleep(ex: &Executor, dur: Duration) -> std::result::Result<(), Error> {
let tfd = TimerFd::new().map_err(Error::TimerFd)?;
tfd.reset(dur, None).map_err(Error::TimerFd)?;
let t = TimerAsync::new(tfd, ex).map_err(Error::TimerAsync)?;
t.next_val().await.map_err(Error::TimerAsync)?;
Ok(())
}
/// Sets the timer to expire after `dur`. If `interval` is not `None` it represents
/// the period for repeated expirations after the initial expiration. Otherwise
/// the timer will expire just once. Cancels any existing duration and repeating interval.
@ -96,4 +105,17 @@ mod tests {
let ex = FdExecutor::new().unwrap();
ex.run_until(this_test(&ex)).unwrap();
}
#[test]
fn timer() {
async fn this_test(ex: &Executor) -> () {
let dur = Duration::from_millis(200);
let now = Instant::now();
TimerAsync::sleep(ex, dur).await.expect("unable to sleep");
assert!(now.elapsed() >= dur);
}
let ex = Executor::new().expect("creating an executor failed");
ex.run_until(this_test(&ex)).unwrap();
}
}