use std::marker::PhantomData;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::Arc;
use crate::collections::boxed::reference::Ref;
use crate::rcu::default::RcuDefaultFlavor;
use crate::rcu::flavor::RcuFlavor;
use crate::rcu::guard::RcuGuard;
use crate::utility::{PhantomUnsend, PhantomUnsync};
pub struct RcuBox<T, F = RcuDefaultFlavor> {
ptr: AtomicPtr<T>,
_unsend: PhantomUnsend<F>,
_unsync: PhantomUnsync<F>,
}
impl<T, F> RcuBox<T, F>
where
F: RcuFlavor,
{
pub fn new(data: T) -> Arc<Self> {
Arc::new(Self {
ptr: AtomicPtr::new(Box::into_raw(Box::new(data))),
_unsend: PhantomData,
_unsync: PhantomData,
})
}
pub fn get<'me, 'guard, G>(&'me self, guard: &'guard G) -> &'guard T
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
let _ = guard;
unsafe { self.ptr.load(Ordering::Acquire).as_ref_unchecked() }
}
pub fn replace(&self, data: T) -> Ref<T, F>
where
T: Send,
{
let new_ptr = Box::into_raw(Box::new(data));
let old_ptr = self.ptr.swap(new_ptr, Ordering::Release);
Ref::new(old_ptr)
}
}
unsafe impl<T, F> Send for RcuBox<T, F> where T: Send {}
unsafe impl<T, F> Sync for RcuBox<T, F> where T: Sync {}
impl<T, F> Drop for RcuBox<T, F> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.ptr.load(Ordering::Relaxed));
}
}
}