use crate::guard::Guard;
use core::marker::PhantomData as marker;
use core::ptr;
use core::sync::atomic::{AtomicUsize, Ordering};
pub struct Atomic<T> {
data: AtomicUsize,
marker: marker<*mut T>,
}
unsafe impl<T: Send + Sync> Send for Atomic<T> {}
unsafe impl<T: Send + Sync> Sync for Atomic<T> {}
impl<T> Atomic<T> {
#[inline]
pub fn new(ptr: *mut T) -> Self {
Self {
data: AtomicUsize::new(ptr as usize),
marker,
}
}
#[inline]
pub fn null() -> Self {
Self::new(ptr::null_mut())
}
#[inline]
pub(crate) fn load_raw(&self) -> *mut T {
self.data.load(Ordering::Relaxed) as *mut T
}
#[inline]
pub fn load<'g>(&self, order: Ordering, _guard: &'g Guard) -> Shared<'g, T> {
let raw = crate::guard::protect_load(&self.data, order);
Shared {
data: raw as *mut T,
marker,
}
}
#[inline]
pub fn store(&self, ptr: Shared<T>, order: Ordering) {
self.data.store(ptr.data as usize, order);
}
#[inline]
pub fn compare_exchange<'g>(
&self,
current: Shared<T>,
new: Shared<T>,
success: Ordering,
failure: Ordering,
_guard: &'g Guard,
) -> Result<Shared<'g, T>, Shared<'g, T>> {
match self
.data
.compare_exchange(current.data as usize, new.data as usize, success, failure)
{
Ok(prev) => Ok(Shared {
data: prev as *mut T,
marker,
}),
Err(prev) => Err(Shared {
data: prev as *mut T,
marker,
}),
}
}
#[inline]
pub fn compare_exchange_weak<'g>(
&self,
current: Shared<T>,
new: Shared<T>,
success: Ordering,
failure: Ordering,
_guard: &'g Guard,
) -> Result<Shared<'g, T>, Shared<'g, T>> {
match self.data.compare_exchange_weak(
current.data as usize,
new.data as usize,
success,
failure,
) {
Ok(prev) => Ok(Shared {
data: prev as *mut T,
marker,
}),
Err(prev) => Err(Shared {
data: prev as *mut T,
marker,
}),
}
}
#[inline]
pub fn swap<'g>(&self, new: Shared<T>, order: Ordering, _guard: &'g Guard) -> Shared<'g, T> {
let prev = self.data.swap(new.data as usize, order);
Shared {
data: prev as *mut T,
marker,
}
}
}
impl<T> Default for Atomic<T> {
fn default() -> Self {
Self::null()
}
}
pub struct Shared<'g, T> {
data: *mut T,
marker: marker<(&'g Guard, *mut T)>,
}
impl<'g, T> Shared<'g, T> {
#[inline]
pub unsafe fn from_raw(ptr: *mut T) -> Self {
Self { data: ptr, marker }
}
#[inline]
pub fn as_raw(&self) -> *mut T {
self.data
}
#[inline]
pub fn is_null(&self) -> bool {
self.data.is_null()
}
#[inline]
pub unsafe fn as_ref(&self) -> Option<&'g T> {
if self.is_null() {
None
} else {
unsafe { Some(&*self.data) }
}
}
#[inline]
pub unsafe fn deref(&self) -> &'g T {
unsafe { &*self.data }
}
#[inline]
pub unsafe fn as_mut(&mut self) -> Option<&'g mut T> {
if self.is_null() {
None
} else {
unsafe { Some(&mut *self.data) }
}
}
}
impl<'g, T> Clone for Shared<'g, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'g, T> Copy for Shared<'g, T> {}
impl<'g, T> PartialEq for Shared<'g, T> {
fn eq(&self, other: &Self) -> bool {
self.data == other.data
}
}
impl<'g, T> Eq for Shared<'g, T> {}
impl<'g, T> core::fmt::Debug for Shared<'g, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Shared({:p})", self.data)
}
}