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