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