use std::mem; use std::sync::{ atomic::{AtomicUsize, Ordering}, Arc, }; use std::thread; mod stack; use crate::stack::Stack; #[repr(align(64))] struct ThreadCount(AtomicUsize); struct DropCount<'a>(&'a AtomicUsize); impl Drop for DropCount<'_> { fn drop(&mut self) { self.0.fetch_add(1, Ordering::Relaxed); } } fn main() { const THREADS: usize = 8; const PER_THREAD_ALLOCATIONS: usize = 10_000_000 + 1_000; static COUNTERS: [ThreadCount; THREADS] = [ ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ThreadCount(AtomicUsize::new(0)), ]; let stack = Arc::new(Stack::new()); let handles: Vec<_> = (0..THREADS) .map(|id| { let stack = Arc::clone(&stack); thread::spawn(move || { let counter = &COUNTERS[id].0; for _ in 0..1_000 { stack.push(DropCount(counter)); } for _ in 0..10_000_000 { let _res = stack.pop(); stack.push(DropCount(counter)); } println!( "thread {} reclaimed {:7} records before exiting", id, counter.load(Ordering::Relaxed) ); }) }) .collect(); for handle in handles { handle.join().unwrap(); } mem::drop(stack); let drop_sum = COUNTERS.iter().map(|local| local.0.load(Ordering::Relaxed)).sum(); assert_eq!(THREADS * PER_THREAD_ALLOCATIONS, drop_sum); println!("total dropped records: {}, no memory was leaked", drop_sum); }