use std::{
marker::PhantomData,
ops::Deref,
ptr::NonNull,
sync::{
atomic::{self, Ordering},
Mutex,
},
};
use crate::data_holder::DataHolder;
use crate::MbarcMap;
pub struct DataReference<T> {
pub(crate) ptr: NonNull<DataHolder<T>>,
pub(crate) phantom: PhantomData<DataHolder<T>>,
}
impl<T> DataReference<T> {
pub(crate) fn raw_data(&self) -> &DataHolder<T> {
unsafe { self.ptr.as_ref() }
}
pub fn is_marked_deleted(&self) -> bool {
self.raw_data().deleted()
}
pub fn ref_count(&self) -> usize {
self.raw_data().ref_count()
}
pub(crate) fn increment_refcount(&self) {
self.raw_data().increment_refcount();
}
pub(crate) fn drop_impl(raw_ptr: NonNull<u8>) {
let inner = unsafe { raw_ptr.cast::<DataHolder<T>>().as_ref() };
if inner.ref_count.fetch_sub(1, Ordering::Release) != 1 {
return;
}
atomic::fence(Ordering::Acquire);
inner.owner.lock().unwrap().remove(&inner.owning_key);
}
}
unsafe impl<T: Sync + Send> Send for DataReference<T> {}
unsafe impl<T: Sync + Send> Sync for DataReference<T> {}
impl<T> Deref for DataReference<T> {
type Target = Mutex<T>;
fn deref(&self) -> &Self::Target {
&self.raw_data().data
}
}
impl<T> DataHolder<T> {
pub(crate) fn make_new_ref(&self) -> DataReference<T> {
self.increment_refcount();
DataReference {
ptr: NonNull::from(self),
phantom: PhantomData,
}
}
}
impl<T> Clone for DataReference<T> {
fn clone(&self) -> Self {
self.raw_data().make_new_ref()
}
}
impl<T> Drop for DataReference<T> {
fn drop(&mut self) {
DataReference::<T>::drop_impl(self.ptr.cast::<u8>());
}
}