use std::sync::atomic::{AtomicUsize, Ordering}; /// A thread-safe counter backed by an atomic integer. #[derive(Debug, Default)] pub struct Counter { value: AtomicUsize, } impl Counter { /// Creates a counter with the given initial value. pub const fn new(initial: usize) -> Self { Self { value: AtomicUsize::new(initial), } } /// Increments the counter and returns the new value. pub fn increment(&self) -> usize { self.value.fetch_add(1, Ordering::Relaxed) + 1 } /// Returns the current value. pub fn get(&self) -> usize { self.value.load(Ordering::Relaxed) } /// Resets the counter to zero. pub fn reset(&self) { self.value.store(0, Ordering::Relaxed); } } fn main() {} #[cfg(test)] mod tests { use super::Counter; use std::sync::Arc; use std::thread; #[test] fn increments_and_resets() { let counter = Counter::new(3); assert_eq!(counter.increment(), 4); assert_eq!(counter.get(), 4); counter.reset(); assert_eq!(counter.get(), 0); } #[test] fn increments_safely_across_threads() { let counter = Arc::new(Counter::default()); let mut handles = Vec::new(); for _ in 0..8 { let counter = Arc::clone(&counter); handles.push(thread::spawn(move || { for _ in 0..1_000 { counter.increment(); } })); } for handle in handles { handle.join().unwrap(); } assert_eq!(counter.get(), 8_000); } }