use core::marker::PhantomData;
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> {
phantom: PhantomData<*mut u8>,
counter: 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 {
phantom: PhantomData,
counter: 1,
data,
}
}
fn decrement(&self) -> usize {
unsafe {
*(&self.counter as *const usize as *mut usize) -= 1;
}
self.counter
}
fn increment(&self) -> usize {
#[cfg(not(feature = "no-asserts"))]
assert!(self.counter < core::usize::MAX, "Incrementing the reference count of an `RcStruct` past `core::usize::MAX` is unsafe and results in undefined behavior");
unsafe {
*(&self.counter as *const usize as *mut usize) += 1;
}
self.counter
}
fn counter(&self) -> usize {
self.counter
}
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 = "no-asserts"))]
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 {}