xref: /aosp_15_r20/external/crosvm/base/src/clock.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker // Utility file to provide a fake clock object representing current time, and a timer driven by
6*bb4ee6a4SAndroid Build Coastguard Worker // that time.
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Instant;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::Event;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Default, Copy, Clone)]
15*bb4ee6a4SAndroid Build Coastguard Worker pub struct Clock {}
16*bb4ee6a4SAndroid Build Coastguard Worker impl Clock {
new() -> Self17*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Self {
18*bb4ee6a4SAndroid Build Coastguard Worker         Clock {}
19*bb4ee6a4SAndroid Build Coastguard Worker     }
20*bb4ee6a4SAndroid Build Coastguard Worker 
now(&self) -> Instant21*bb4ee6a4SAndroid Build Coastguard Worker     pub fn now(&self) -> Instant {
22*bb4ee6a4SAndroid Build Coastguard Worker         Instant::now()
23*bb4ee6a4SAndroid Build Coastguard Worker     }
24*bb4ee6a4SAndroid Build Coastguard Worker }
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker /// A fake clock that can be used in tests to give exact control over the time.
27*bb4ee6a4SAndroid Build Coastguard Worker /// For a code example, see the tests in base/src/timer.rs.
28*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
29*bb4ee6a4SAndroid Build Coastguard Worker pub struct FakeClock {
30*bb4ee6a4SAndroid Build Coastguard Worker     epoch: Instant,
31*bb4ee6a4SAndroid Build Coastguard Worker     ns_since_epoch: u64,
32*bb4ee6a4SAndroid Build Coastguard Worker     deadlines: Vec<(u64, Event)>,
33*bb4ee6a4SAndroid Build Coastguard Worker }
34*bb4ee6a4SAndroid Build Coastguard Worker 
35*bb4ee6a4SAndroid Build Coastguard Worker impl FakeClock {
new() -> Self36*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Self {
37*bb4ee6a4SAndroid Build Coastguard Worker         FakeClock {
38*bb4ee6a4SAndroid Build Coastguard Worker             epoch: Instant::now(),
39*bb4ee6a4SAndroid Build Coastguard Worker             ns_since_epoch: 0,
40*bb4ee6a4SAndroid Build Coastguard Worker             deadlines: Vec::new(),
41*bb4ee6a4SAndroid Build Coastguard Worker         }
42*bb4ee6a4SAndroid Build Coastguard Worker     }
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the current time, according to this clock.
now(&self) -> Instant45*bb4ee6a4SAndroid Build Coastguard Worker     pub fn now(&self) -> Instant {
46*bb4ee6a4SAndroid Build Coastguard Worker         self.epoch + Duration::from_nanos(self.ns_since_epoch)
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker     ///  Get the current time in ns, according to this clock.
nanos(&self) -> u6450*bb4ee6a4SAndroid Build Coastguard Worker     pub fn nanos(&self) -> u64 {
51*bb4ee6a4SAndroid Build Coastguard Worker         self.ns_since_epoch
52*bb4ee6a4SAndroid Build Coastguard Worker     }
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker     /// Register the event descriptor for a notification when self's time is |deadline_ns|.
55*bb4ee6a4SAndroid Build Coastguard Worker     /// Drop any existing events registered to the same raw descriptor.
add_event(&mut self, deadline_ns: u64, descriptor: Event)56*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_event(&mut self, deadline_ns: u64, descriptor: Event) {
57*bb4ee6a4SAndroid Build Coastguard Worker         self.deadlines.retain(|(_, old_descriptor)| {
58*bb4ee6a4SAndroid Build Coastguard Worker             descriptor.as_raw_descriptor() != old_descriptor.as_raw_descriptor()
59*bb4ee6a4SAndroid Build Coastguard Worker         });
60*bb4ee6a4SAndroid Build Coastguard Worker         self.deadlines.push((deadline_ns, descriptor));
61*bb4ee6a4SAndroid Build Coastguard Worker     }
62*bb4ee6a4SAndroid Build Coastguard Worker 
add_ns(&mut self, ns: u64)63*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_ns(&mut self, ns: u64) {
64*bb4ee6a4SAndroid Build Coastguard Worker         self.ns_since_epoch += ns;
65*bb4ee6a4SAndroid Build Coastguard Worker         let time = self.ns_since_epoch;
66*bb4ee6a4SAndroid Build Coastguard Worker         self.deadlines.retain(|(ns, descriptor)| {
67*bb4ee6a4SAndroid Build Coastguard Worker             let expired = *ns <= time;
68*bb4ee6a4SAndroid Build Coastguard Worker             if expired {
69*bb4ee6a4SAndroid Build Coastguard Worker                 descriptor.signal().unwrap();
70*bb4ee6a4SAndroid Build Coastguard Worker             }
71*bb4ee6a4SAndroid Build Coastguard Worker             !expired
72*bb4ee6a4SAndroid Build Coastguard Worker         });
73*bb4ee6a4SAndroid Build Coastguard Worker     }
74*bb4ee6a4SAndroid Build Coastguard Worker }
75*bb4ee6a4SAndroid Build Coastguard Worker 
76*bb4ee6a4SAndroid Build Coastguard Worker impl Default for FakeClock {
default() -> Self77*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
78*bb4ee6a4SAndroid Build Coastguard Worker         Self::new()
79*bb4ee6a4SAndroid Build Coastguard Worker     }
80*bb4ee6a4SAndroid Build Coastguard Worker }
81