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> {}