use std::sync::atomic::{AtomicI64, Ordering};
use crate::common::time_compat::{SystemTime, UNIX_EPOCH};
static LAST_TIMESTAMP: AtomicI64 = AtomicI64::new(0);
pub fn get_fast_timestamp() -> i64 {
let now_nano = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos() as i64)
.unwrap_or(1);
loop {
let last_ts = LAST_TIMESTAMP.load(Ordering::Acquire);
let next_ts = if now_nano > last_ts {
now_nano
} else {
last_ts + 1
};
if LAST_TIMESTAMP
.compare_exchange(last_ts, next_ts, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
{
return next_ts;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rustc_hash::FxHashSet;
use std::thread;
#[test]
fn test_timestamp_monotonic() {
let mut prev = get_fast_timestamp();
for _ in 0..1000 {
let ts = get_fast_timestamp();
assert!(
ts > prev,
"Timestamp not strictly increasing: {} <= {}",
ts,
prev
);
prev = ts;
}
}
#[test]
fn test_timestamp_unique() {
let mut timestamps = FxHashSet::default();
for _ in 0..10000 {
let ts = get_fast_timestamp();
assert!(
timestamps.insert(ts),
"Duplicate timestamp detected: {}",
ts
);
}
}
#[test]
fn test_timestamp_concurrent() {
let handles: Vec<_> = (0..4)
.map(|_| {
thread::spawn(|| {
let mut timestamps = Vec::with_capacity(1000);
for _ in 0..1000 {
timestamps.push(get_fast_timestamp());
}
timestamps
})
})
.collect();
let mut all_timestamps: FxHashSet<i64> = FxHashSet::default();
for handle in handles {
let timestamps = handle.join().unwrap();
for ts in timestamps {
all_timestamps.insert(ts);
}
}
assert_eq!(
all_timestamps.len(),
4000,
"Expected all 4000 timestamps to be unique, got {}",
all_timestamps.len()
);
}
#[test]
fn test_timestamp_positive() {
for _ in 0..100 {
let ts = get_fast_timestamp();
assert!(ts > 0, "Timestamp should be positive: {}", ts);
}
}
}