diff options
Diffstat (limited to 'sys_util/src/clock.rs')
-rw-r--r-- | sys_util/src/clock.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/sys_util/src/clock.rs b/sys_util/src/clock.rs new file mode 100644 index 0000000..5f6ce0c --- /dev/null +++ b/sys_util/src/clock.rs @@ -0,0 +1,84 @@ +// Copyright 2019 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. + +// Utility file to provide a fake clock object representing current time, and a timerfd driven by +// that time. + +use std::time::{Duration, Instant}; +use std::os::unix::io::AsRawFd; +use EventFd; + +#[derive(Debug, Copy, Clone)] +pub struct Clock(Instant); +impl Clock { + pub fn new() -> Self { + Clock(Instant::now()) + } + + pub fn now(&self) -> Self { + Clock(Instant::now()) + } + + pub fn duration_since(&self, earlier: &Self) -> Duration { + self.0.duration_since(earlier.0) + } +} + +const NS_PER_SEC : u64 = 1_000_000_000; +/// A fake clock that can be used in tests to give exact control over the time. +/// For a code example, see the tests in sys_util/src/timerfd.rs. +#[derive(Debug)] +pub struct FakeClock { + ns_since_epoch: u64, + deadlines: Vec<(u64, EventFd)>, +} + +impl FakeClock { + pub fn new() -> Self { + FakeClock { + ns_since_epoch: 1547163599 * NS_PER_SEC, + deadlines: Vec::new(), + } + } + + /// Get the current time, according to this clock. + pub fn now(&self) -> Self { + FakeClock { + ns_since_epoch: self.ns_since_epoch, + deadlines: Vec::new(), + } + } + + /// Get the current time in ns, according to this clock. + pub fn nanos(&self) -> u64 { + self.ns_since_epoch + } + + /// Get the duration since |earlier|, assuming that earlier < self. + pub fn duration_since(&self, earlier: &Self) -> Duration { + let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch; + Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32) + } + + /// Register the event fd for a notification when self's time is |deadline_ns|. + /// Drop any existing events registered to the same raw fd. + pub fn add_event_fd(&mut self, deadline_ns: u64, fd: EventFd) { + self.deadlines.retain(|&(_, ref old_fd)| { + fd.as_raw_fd() != old_fd.as_raw_fd() + }); + self.deadlines.push((deadline_ns, fd)); + } + + pub fn add_ns(&mut self, ns: u64) { + self.ns_since_epoch += ns; + let time = self.ns_since_epoch; + self.deadlines.retain(|&(ns, ref fd)| { + let expired = ns <= time; + if expired { + fd.write(1).unwrap(); + } + !expired + }); + } +} |