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 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> 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 {
unsafe {
*(&self.counter as *const usize as *mut usize) += 1;
}
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> 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::Relaxed) - 1
}
fn increment(&self) -> usize {
self.counter.fetch_add(1, Ordering::Relaxed) + 1
}
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 {}