use core::sync::atomic::{AtomicUsize, Ordering};
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub struct Epoch {
data: usize,
}
impl Epoch {
#[inline]
pub fn starting() -> Self {
Self::default()
}
pub fn wrapping_sub(self, rhs: Self) -> isize {
self.data.wrapping_sub(rhs.data & !1) as isize >> 1
}
#[inline]
pub fn is_pinned(self) -> bool {
(self.data & 1) == 1
}
#[inline]
pub fn pinned(self) -> Epoch {
Epoch { data: self.data | 1 }
}
#[inline]
pub fn unpinned(self) -> Epoch {
Epoch { data: self.data & !1 }
}
#[inline]
pub fn successor(self) -> Epoch {
Epoch { data: self.data.wrapping_add(2) }
}
}
#[derive(Default, Debug)]
pub struct AtomicEpoch {
data: AtomicUsize,
}
impl AtomicEpoch {
#[inline]
pub fn new(epoch: Epoch) -> Self {
let data = AtomicUsize::new(epoch.data);
AtomicEpoch { data }
}
#[inline]
pub fn load(&self, ord: Ordering) -> Epoch {
Epoch { data: self.data.load(ord) }
}
#[inline]
pub fn store(&self, epoch: Epoch, ord: Ordering) {
self.data.store(epoch.data, ord);
}
#[inline]
pub fn compare_and_swap(&self, current: Epoch, new: Epoch, ord: Ordering) -> Epoch {
let data = self.data.compare_and_swap(current.data, new.data, ord);
Epoch { data }
}
}