use core::cell::Cell;
use core::sync::atomic::{AtomicUsize, Ordering};
pub trait RefCounter<T> {
fn new(data: T) -> Self;
fn decrement(&self) -> usize;
fn increment(&self) -> usize;
fn counter(&self) -> usize;
fn get_data(&self) -> &T;
fn get_data_mut(&mut self) -> &mut T;
}
pub struct RcStruct<T> {
counter: Cell<usize>,
pub data: T,
}
impl<T> Clone for RcStruct<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self::new(self.data.clone())
}
}
impl<T> RefCounter<T> for RcStruct<T> {
fn new(data: T) -> Self {
Self {
counter: Cell::new(1),
data,
}
}
fn decrement(&self) -> usize {
self.counter.set(self.counter.get() - 1);
self.counter.get()
}
fn increment(&self) -> usize {
#[cfg(not(feature = "ref-counter-skip-overflow-check"))]
assert!(
self.counter.get() < core::usize::MAX,
"Incrementing the reference count of an `RcStruct`\
past `core::usize::MAX` is unsafe and results in undefined behavior"
);
self.counter.set(self.counter.get() + 1);
self.counter.get()
}
fn counter(&self) -> usize {
self.counter.get()
}
fn get_data(&self) -> &T {
&self.data
}
fn get_data_mut(&mut self) -> &mut T {
&mut self.data
}
}
pub struct ArcStruct<T> {
counter: AtomicUsize,
pub data: T,
}
impl<T> Clone for ArcStruct<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self::new(self.data.clone())
}
}
impl<T> RefCounter<T> for ArcStruct<T> {
fn new(data: T) -> Self {
Self {
counter: AtomicUsize::new(1),
data,
}
}
fn decrement(&self) -> usize {
self.counter.fetch_sub(1, Ordering::AcqRel) - 1
}
fn increment(&self) -> usize {
#[cfg(not(feature = "ref-counter-skip-overflow-check"))]
assert!(
self.counter.load(Ordering::Acquire) < core::usize::MAX,
"Incrementing the reference count of an `ArcStruct`\
past `core::usize::MAX` is unsafe and results in undefined behavior"
);
self.counter.fetch_add(1, Ordering::Relaxed) + 1
}
fn counter(&self) -> usize {
self.counter.load(Ordering::Acquire)
}
fn get_data(&self) -> &T {
&self.data
}
fn get_data_mut(&mut self) -> &mut T {
&mut self.data
}
}
unsafe impl<T> Send for ArcStruct<T> where T: Send {}
unsafe impl<T> Sync for ArcStruct<T> where T: Sync {}