base/
clock.rs

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
8use std::time::Duration;
9use std::time::Instant;
10
11use crate::descriptor::AsRawDescriptor;
12use crate::Event;
13
14#[derive(Debug, Default, Copy, Clone)]
15pub struct Clock {}
16impl Clock {
17    pub fn new() -> Self {
18        Clock {}
19    }
20
21    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)]
29pub struct FakeClock {
30    epoch: Instant,
31    ns_since_epoch: u64,
32    deadlines: Vec<(u64, Event)>,
33}
34
35impl FakeClock {
36    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.
45    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.
50    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.
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
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
76impl Default for FakeClock {
77    fn default() -> Self {
78        Self::new()
79    }
80}