mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
cros_async: Add TimerAsync
Add an asynchronous timer that is similar to EventAsync. This will allow the timer to be used from async contexts such as the new block device. Change-Id: I858f44e2165459c388a83735aba3ed23755a534b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2545128 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Noah Gold <nkgold@google.com> Reviewed-by: Chirantan Ekbote <chirantan@chromium.org> Commit-Queue: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
977c67e2a6
commit
6c40ddbdf4
3 changed files with 108 additions and 1 deletions
|
@ -14,7 +14,7 @@ use sys_util::{FakeTimerFd, TimerFd};
|
||||||
|
|
||||||
/// See [TimerFd](sys_util::TimerFd) for struct- and method-level
|
/// See [TimerFd](sys_util::TimerFd) for struct- and method-level
|
||||||
/// documentation.
|
/// documentation.
|
||||||
pub struct Timer(TimerFd);
|
pub struct Timer(pub TimerFd);
|
||||||
impl Timer {
|
impl Timer {
|
||||||
pub fn new() -> Result<Timer> {
|
pub fn new() -> Result<Timer> {
|
||||||
TimerFd::new().map(|timerfd| Timer(timerfd))
|
TimerFd::new().map(|timerfd| Timer(timerfd))
|
||||||
|
|
|
@ -66,6 +66,7 @@ mod io_ext;
|
||||||
mod io_source;
|
mod io_source;
|
||||||
mod poll_source;
|
mod poll_source;
|
||||||
mod select;
|
mod select;
|
||||||
|
mod timer;
|
||||||
mod uring_executor;
|
mod uring_executor;
|
||||||
mod uring_futures;
|
mod uring_futures;
|
||||||
pub mod uring_mem;
|
pub mod uring_mem;
|
||||||
|
@ -79,6 +80,7 @@ pub use io_ext::{
|
||||||
};
|
};
|
||||||
pub use poll_source::PollSource;
|
pub use poll_source::PollSource;
|
||||||
pub use select::SelectResult;
|
pub use select::SelectResult;
|
||||||
|
pub use timer::TimerAsync;
|
||||||
pub use uring_futures::UringSource;
|
pub use uring_futures::UringSource;
|
||||||
pub use uring_mem::{BackingMemory, MemRegion};
|
pub use uring_mem::{BackingMemory, MemRegion};
|
||||||
|
|
||||||
|
|
105
cros_async/src/timer.rs
Normal file
105
cros_async/src/timer.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
use crate::io_ext::async_from;
|
||||||
|
use crate::{AsyncError, AsyncResult, IntoAsync, IoSourceExt};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use sys_util::TimerFd;
|
||||||
|
|
||||||
|
/// An async version of sys_util::TimerFd.
|
||||||
|
pub struct TimerAsync {
|
||||||
|
io_source: Box<dyn IoSourceExt<TimerFd>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimerAsync {
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) fn new_poll(timer: TimerFd) -> AsyncResult<TimerAsync> {
|
||||||
|
Ok(TimerAsync {
|
||||||
|
io_source: crate::io_ext::async_poll_from(timer)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) fn new_uring(timer: TimerFd) -> AsyncResult<TimerAsync> {
|
||||||
|
Ok(TimerAsync {
|
||||||
|
io_source: crate::io_ext::async_uring_from(timer)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the next value from the timer.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn next_val(&self) -> AsyncResult<u64> {
|
||||||
|
self.io_source.read_u64().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<TimerFd> for TimerAsync {
|
||||||
|
type Error = AsyncError;
|
||||||
|
|
||||||
|
/// Creates a new TimerAsync wrapper around the provided timer.
|
||||||
|
fn try_from(timer: TimerFd) -> AsyncResult<Self> {
|
||||||
|
Ok(TimerAsync {
|
||||||
|
io_source: async_from(timer)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoAsync for TimerFd {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use futures::pin_mut;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_shot() {
|
||||||
|
async fn this_test() -> () {
|
||||||
|
let tfd = TimerFd::new().expect("failed to create timerfd");
|
||||||
|
assert_eq!(tfd.is_armed().unwrap(), false);
|
||||||
|
|
||||||
|
let dur = Duration::from_millis(200);
|
||||||
|
let now = Instant::now();
|
||||||
|
tfd.reset(dur, None).expect("failed to arm timer");
|
||||||
|
|
||||||
|
assert_eq!(tfd.is_armed().unwrap(), true);
|
||||||
|
|
||||||
|
let t = TimerAsync::try_from(tfd).unwrap();
|
||||||
|
let count = t.next_val().await.expect("unable to wait for timer");
|
||||||
|
|
||||||
|
assert_eq!(count, 1);
|
||||||
|
assert!(now.elapsed() >= dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fut = this_test();
|
||||||
|
pin_mut!(fut);
|
||||||
|
crate::run_executor(crate::RunOne::new(fut)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_shot_fd() {
|
||||||
|
async fn this_test() -> () {
|
||||||
|
let tfd = TimerFd::new().expect("failed to create timerfd");
|
||||||
|
assert_eq!(tfd.is_armed().unwrap(), false);
|
||||||
|
|
||||||
|
let dur = Duration::from_millis(200);
|
||||||
|
let now = Instant::now();
|
||||||
|
tfd.reset(dur, None).expect("failed to arm timer");
|
||||||
|
|
||||||
|
assert_eq!(tfd.is_armed().unwrap(), true);
|
||||||
|
|
||||||
|
let t = TimerAsync::new_poll(tfd).unwrap();
|
||||||
|
let count = t.next_val().await.expect("unable to wait for timer");
|
||||||
|
|
||||||
|
assert_eq!(count, 1);
|
||||||
|
assert!(now.elapsed() >= dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fut = this_test();
|
||||||
|
pin_mut!(fut);
|
||||||
|
crate::run_one_poll(fut).unwrap();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue