atom_box 0.3.0

A safe idiomatic Rust implementation of Atomic Box using hazard pointers
Documentation
use crate::sync::{AtomicBool, AtomicPtr, Ordering};

use super::list::LockFreeList;

#[derive(Debug)]
pub(crate) struct Node {
    pub(crate) ptr: AtomicPtr<usize>,
    pub(crate) active: AtomicBool,
}

pub(super) type HazardPointerList = LockFreeList<Node>;

impl Node {
    pub(crate) fn reset(&self) {
        self.ptr.store(core::ptr::null_mut(), Ordering::Release);
    }

    fn try_acquire(&self) -> bool {
        let active = self.active.load(Ordering::Acquire);
        !active
            && self
                .active
                .compare_exchange(active, true, Ordering::Release, Ordering::Relaxed)
                .is_ok()
    }
    pub(crate) fn release(&self) {
        self.active.store(false, Ordering::Release);
    }
    pub(crate) fn load(&self, ordering: Ordering) -> *mut usize {
        self.ptr.load(ordering)
    }
    pub(crate) fn store(&self, value: *mut usize, ordering: Ordering) {
        self.ptr.store(value, ordering)
    }
}

impl HazardPointerList {
    pub(crate) fn get_available(&self) -> Option<&Node> {
        self.iter()
            .find(|node| !node.ptr.load(Ordering::Acquire).is_null() && node.try_acquire())
    }

    pub(crate) fn set_node_available(&self, node: &Node) {
        node.reset();
        node.release();
    }

    pub(crate) fn push_in_use(&self, ptr: AtomicPtr<usize>) -> &Node {
        &unsafe {
            &*self.push(Node {
                ptr,
                active: AtomicBool::new(true),
            })
        }
        .value
    }
}