wrc 2.1.0

A thread-safe weighted reference counting smart-pointer for Rust.
Documentation
use std::mem::ManuallyDrop;
use std::sync::atomic::{self, AtomicUsize};

pub struct Inner<T: ?Sized> {
    strong_weight: AtomicUsize,
    weak_weight: AtomicUsize,
    pub(crate) data: ManuallyDrop<T>,
}

impl<T> Inner<T> {
    #[inline]
    pub fn new(data: T, starting_strong_weight: usize, starting_weak_weight: usize) -> Inner<T> {
        Inner {
            strong_weight: AtomicUsize::new(starting_strong_weight),
            weak_weight: AtomicUsize::new(starting_weak_weight),
            data: ManuallyDrop::new(data),
        }
    }
}

impl<T: ?Sized> Inner<T> {
    #[inline]
    pub fn add_weak_weight(&self, weight: usize) -> usize {
        let old = self
            .weak_weight
            .fetch_add(weight, atomic::Ordering::Relaxed);
        debug_assert!(old.checked_add(weight).is_some(), "weak weight overflow");
        old + weight
    }

    #[inline]
    pub fn drop_weak_weight(&self, weight: usize) -> usize {
        let old = self
            .weak_weight
            .fetch_sub(weight, atomic::Ordering::Release);
        debug_assert!(old >= weight, "weak weight underflow");
        old - weight
    }

    #[inline]
    pub fn strong_weight(&self) -> usize {
        self.strong_weight.load(atomic::Ordering::Relaxed)
    }

    #[inline]
    pub fn weak_weight(&self) -> usize {
        self.weak_weight.load(atomic::Ordering::Relaxed)
    }

    #[inline]
    pub fn add_strong_weight(&self, weight: usize) -> usize {
        let old = self
            .strong_weight
            .fetch_add(weight, atomic::Ordering::Relaxed);
        debug_assert!(old.checked_add(weight).is_some(), "strong weight overflow");
        old + weight
    }

    #[inline]
    pub fn drop_strong_weight(&self, weight: usize) -> usize {
        let old = self
            .strong_weight
            .fetch_sub(weight, atomic::Ordering::Release);
        debug_assert!(old >= weight, "strong weight underflow");
        old - weight
    }

    #[inline]
    pub fn try_add_strong_weight(&self, weight: usize) -> bool {
        let mut current = self.strong_weight.load(atomic::Ordering::Relaxed);
        loop {
            if current == 0 {
                return false;
            }
            match self.strong_weight.compare_exchange_weak(
                current,
                current + weight,
                atomic::Ordering::Relaxed,
                atomic::Ordering::Relaxed,
            ) {
                Ok(_) => return true,
                Err(found) => current = found,
            }
        }
    }
}

unsafe impl<T: ?Sized + Sync + Send> Send for Inner<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Inner<T> {}