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