use crossbeam::epoch::{self, Atomic, Owned, Shared};
use std::sync::atomic::Ordering;
#[derive(Debug)]
pub struct AtomicRef<T> {
inner: Atomic<T>,
}
impl<T> AtomicRef<T> {
pub fn new(value: T) -> Self {
Self {
inner: Atomic::new(value),
}
}
pub fn load<'g>(&self, guard: &'g epoch::Guard) -> Shared<'g, T> {
self.inner.load(Ordering::SeqCst, guard)
}
pub fn store(&self, value: T) {
let guard = &epoch::pin();
let new = Owned::new(value);
let old = self.inner.swap(new, Ordering::SeqCst, guard);
unsafe {
guard.defer_destroy(old);
}
}
pub fn compare_and_swap(&self, current: Shared<'_, T>, new: T) -> std::result::Result<T, T>
where
T: Clone,
{
let guard = epoch::pin();
let new_owned = Owned::new(new.clone());
match self.inner.compare_exchange(current, new_owned, Ordering::SeqCst, Ordering::SeqCst, &guard) {
Ok(_) => unsafe { Ok((*current.as_raw()).clone()) },
Err(_) => Err(new),
}
}
}