hazptr 0.1.1

hazard pointer based concurrent memory reclamation
Documentation
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);
}