This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / knot2 / crates / knot-runtime / src / clock.rs
2.3 kB 84 lines
1use std::sync::Arc; 2use std::sync::atomic::{AtomicU64, Ordering}; 3use std::time::{Duration, SystemTime, UNIX_EPOCH}; 4 5pub use knot_types::UnixMicros; 6 7pub trait Clock: Send + Sync + 'static { 8 fn now_unix_micros(&self) -> UnixMicros; 9} 10 11impl<T: Clock + ?Sized> Clock for Arc<T> { 12 fn now_unix_micros(&self) -> UnixMicros { 13 (**self).now_unix_micros() 14 } 15} 16 17pub struct SystemClock; 18 19impl Clock for SystemClock { 20 fn now_unix_micros(&self) -> UnixMicros { 21 let micros = SystemTime::now() 22 .duration_since(UNIX_EPOCH) 23 .map(|elapsed| elapsed.as_micros() as u64) 24 .unwrap_or(0); 25 UnixMicros::new(micros) 26 } 27} 28 29pub struct ManualClock { 30 micros: AtomicU64, 31} 32 33impl ManualClock { 34 pub fn new(start: UnixMicros) -> Self { 35 Self { 36 micros: AtomicU64::new(start.get()), 37 } 38 } 39 40 pub fn advance(&self, delta: Duration) { 41 self.micros 42 .fetch_add(delta.as_micros() as u64, Ordering::SeqCst); 43 } 44} 45 46impl Clock for ManualClock { 47 fn now_unix_micros(&self) -> UnixMicros { 48 UnixMicros::new(self.micros.load(Ordering::SeqCst)) 49 } 50} 51 52#[cfg(test)] 53mod tests { 54 use super::*; 55 56 #[test] 57 fn manual_clock_advances() { 58 let clock = ManualClock::new(UnixMicros::new(1_000)); 59 assert_eq!(clock.now_unix_micros().get(), 1_000); 60 clock.advance(Duration::from_micros(500)); 61 assert_eq!(clock.now_unix_micros().get(), 1_500); 62 } 63 64 #[test] 65 fn manual_clock_same_start_same_sequence() { 66 let one = ManualClock::new(UnixMicros::new(1_000)); 67 let two = ManualClock::new(UnixMicros::new(1_000)); 68 let advances = [10, 250, 7, 1_000]; 69 advances.iter().for_each(|&step| { 70 one.advance(Duration::from_micros(step)); 71 two.advance(Duration::from_micros(step)); 72 assert_eq!(one.now_unix_micros(), two.now_unix_micros()); 73 }); 74 } 75 76 #[test] 77 fn a_shared_clock_advances_through_the_trait_object() { 78 let shared = Arc::new(ManualClock::new(UnixMicros::new(1_000))); 79 let view: Arc<dyn Clock> = Arc::clone(&shared) as Arc<dyn Clock>; 80 assert_eq!(view.now_unix_micros().get(), 1_000); 81 shared.advance(Duration::from_micros(250)); 82 assert_eq!(view.now_unix_micros().get(), 1_250); 83 } 84}