use portable_atomic::{AtomicUsize, Ordering};
const REF_COUNT_MAX: usize = usize::MAX;
#[derive(Debug)]
pub struct Refs {
refs: AtomicUsize,
}
impl Refs {
pub const fn one() -> Self {
Self { refs: AtomicUsize::new(1) }
}
pub fn count(&self) -> usize {
self.refs.load(Ordering::Relaxed)
}
pub fn take_ref(&self) {
let r = self.refs.fetch_add(1, Ordering::Relaxed);
if r == REF_COUNT_MAX {
panic_ref_count_overflow();
}
}
pub unsafe fn release_ref(&self) -> bool {
let r = self.refs.fetch_sub(1, Ordering::Release);
if r == 1 {
let _ = self.refs.load(Ordering::Acquire);
true
} else if r == 0 {
panic_ref_count_overflow()
} else {
false
}
}
}
#[cold]
#[inline(never)]
fn panic_ref_count_overflow() -> ! {
panic!("ref count overflowed")
}