Something went wrong. Try again.
A downstream fork of Tranquil PDS for use in margin.cafe
Something went wrong. Try again.
3.4 kB · 124 lines
Rust
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125use std::sync::OnceLock;use std::time::{Duration, Instant};
use crate::blockstore::WallClockMs;use crate::eventlog::TimestampMicros;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]#[repr(transparent)]pub struct LogicalNanos(u64);
impl LogicalNanos { pub const fn new(nanos: u64) -> Self { Self(nanos) }
pub fn raw(self) -> u64 { self.0 }
pub fn from_millis(ms: u64) -> Self { Self(ms.saturating_mul(1_000_000)) }
pub fn saturating_sub(self, other: Self) -> Self { Self(self.0.saturating_sub(other.0)) }}
pub trait Clock: Clone + Send + Sync + 'static { fn unix_micros(&self) -> TimestampMicros; fn wall_millis(&self) -> WallClockMs; fn monotonic(&self) -> LogicalNanos; fn advance(&self, by: Duration);}
#[derive(Debug, Clone, Copy, Default)]pub struct SystemClock;
static PROCESS_ORIGIN: OnceLock<Instant> = OnceLock::new();
impl Clock for SystemClock { fn unix_micros(&self) -> TimestampMicros { TimestampMicros::now() }
fn wall_millis(&self) -> WallClockMs { WallClockMs::now() }
fn monotonic(&self) -> LogicalNanos { let origin = PROCESS_ORIGIN.get_or_init(Instant::now); LogicalNanos::new(u64::try_from(origin.elapsed().as_nanos()).unwrap_or(u64::MAX)) }
fn advance(&self, _by: Duration) {}}
#[cfg(any(test, feature = "test-harness"))]pub use sim_clock::SimClock;
#[cfg(any(test, feature = "test-harness"))]mod sim_clock { use std::sync::Arc; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::Duration;
use super::{Clock, LogicalNanos}; use crate::blockstore::WallClockMs; use crate::eventlog::TimestampMicros; use crate::sim::splitmix64;
const EPOCH_BASE_MICROS: u64 = 1_700_000_000_000_000; const ORIGIN_SPREAD_MICROS: u64 = 86_400 * 1_000_000;
#[derive(Debug)] struct SimClockState { logical_nanos: AtomicU64, unix_origin_micros: u64, }
#[derive(Debug, Clone)] pub struct SimClock { state: Arc<SimClockState>, }
impl SimClock { pub fn new(seed: u64) -> Self { Self { state: Arc::new(SimClockState { logical_nanos: AtomicU64::new(0), unix_origin_micros: EPOCH_BASE_MICROS + (splitmix64(seed) % ORIGIN_SPREAD_MICROS), }), } } }
impl Clock for SimClock { fn unix_micros(&self) -> TimestampMicros { let logical = self.state.logical_nanos.load(Ordering::Acquire); TimestampMicros::new( self.state .unix_origin_micros .saturating_add(logical / 1_000), ) }
fn wall_millis(&self) -> WallClockMs { let logical = self.state.logical_nanos.load(Ordering::Acquire); WallClockMs::new( (self.state.unix_origin_micros / 1_000).saturating_add(logical / 1_000_000), ) }
fn monotonic(&self) -> LogicalNanos { LogicalNanos::new(self.state.logical_nanos.load(Ordering::Acquire)) }
fn advance(&self, by: Duration) { let nanos = u64::try_from(by.as_nanos()).unwrap_or(u64::MAX); self.state.logical_nanos.fetch_add(nanos, Ordering::AcqRel); } }}