extern crate alloc;
extern crate std;
use crate::kairos::{BackoffStrategy, Clock, ClockConfig, ExponentialBackoff, TickCounter};
use alloc::vec::Vec;
use std::sync::{Arc, Barrier};
use std::thread;
#[test]
fn test_concurrency_with_backoff() {
let config = ClockConfig {
max_skew_warning_threshold: 100_000_000,
#[cfg(feature = "rand")]
backoff: BackoffStrategy::Exponential(ExponentialBackoff::new(
4, 64, Some(8), )),
#[cfg(not(feature = "rand"))]
backoff: BackoffStrategy::Exponential(ExponentialBackoff::new(4, 64, Some((123, 8)))),
};
let clock = Arc::new(Clock::new(TickCounter::new(), 123, config).unwrap());
let num_threads = if cfg!(miri) { 4 } else { 8 };
let num_timestamps_per_thread = if cfg!(miri) { 25 } else { 1000 };
let barrier = Arc::new(Barrier::new(num_threads));
let mut handles = Vec::new();
for _ in 0..num_threads {
let clock_clone = Arc::clone(&clock);
let barrier_clone = Arc::clone(&barrier);
handles.push(thread::spawn(move || {
let mut timestamps = Vec::with_capacity(num_timestamps_per_thread);
let _ = barrier_clone.wait();
for _ in 0..num_timestamps_per_thread {
timestamps.push(clock_clone.now(0u16));
}
timestamps
}));
}
let mut all_timestamps = Vec::new();
for handle in handles {
all_timestamps.extend(handle.join().expect("Thread failed to complete"));
}
assert_eq!(
all_timestamps.len(),
num_threads * num_timestamps_per_thread
);
let mut sorted_timestamps = all_timestamps.clone();
sorted_timestamps.sort();
let original_len = sorted_timestamps.len();
sorted_timestamps.dedup();
assert_eq!(
original_len,
sorted_timestamps.len(),
"All concurrent timestamps must be unique"
);
assert!(clock.stats().peak_attempts >= 1);
}