use std::fmt;
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use crate::atomic::traits::Atomic;
pub struct AtomicRef<T> {
inner: AtomicPtr<T>,
}
impl<T> AtomicRef<T> {
#[inline]
pub fn new(value: Arc<T>) -> Self {
let ptr = Arc::into_raw(value) as *mut T;
Self {
inner: AtomicPtr::new(ptr),
}
}
#[inline]
pub fn load(&self) -> Arc<T> {
let ptr = self.inner.load(Ordering::Acquire);
unsafe {
let arc = Arc::from_raw(ptr);
let cloned = arc.clone();
let _ = Arc::into_raw(arc); cloned
}
}
#[inline]
pub fn store(&self, value: Arc<T>) {
let new_ptr = Arc::into_raw(value) as *mut T;
let old_ptr = self.inner.swap(new_ptr, Ordering::AcqRel);
unsafe {
if !old_ptr.is_null() {
Arc::from_raw(old_ptr);
}
}
}
#[inline]
pub fn swap(&self, value: Arc<T>) -> Arc<T> {
let new_ptr = Arc::into_raw(value) as *mut T;
let old_ptr = self.inner.swap(new_ptr, Ordering::AcqRel);
unsafe { Arc::from_raw(old_ptr) }
}
#[inline]
pub fn compare_set(&self, current: &Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
let current_ptr = Arc::as_ptr(current) as *mut T;
let new_ptr = Arc::into_raw(new) as *mut T;
match self
.inner
.compare_exchange(current_ptr, new_ptr, Ordering::AcqRel, Ordering::Acquire)
{
Ok(_) => Ok(()),
Err(actual_ptr) => unsafe {
let _new_arc = Arc::from_raw(new_ptr);
let actual_arc = Arc::from_raw(actual_ptr);
let cloned = actual_arc.clone();
let _ = Arc::into_raw(actual_arc); Err(cloned)
},
}
}
#[inline]
pub fn compare_set_weak(&self, current: &Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
let current_ptr = Arc::as_ptr(current) as *mut T;
let new_ptr = Arc::into_raw(new) as *mut T;
match self.inner.compare_exchange_weak(
current_ptr,
new_ptr,
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(_) => Ok(()),
Err(actual_ptr) => unsafe {
let _new_arc = Arc::from_raw(new_ptr);
let actual_arc = Arc::from_raw(actual_ptr);
let cloned = actual_arc.clone();
let _ = Arc::into_raw(actual_arc); Err(cloned)
},
}
}
#[inline]
pub fn compare_and_exchange(&self, current: &Arc<T>, new: Arc<T>) -> Arc<T> {
let current_ptr = Arc::as_ptr(current) as *mut T;
let new_ptr = Arc::into_raw(new) as *mut T;
match self
.inner
.compare_exchange(current_ptr, new_ptr, Ordering::AcqRel, Ordering::Acquire)
{
Ok(prev_ptr) => unsafe { Arc::from_raw(prev_ptr) },
Err(actual_ptr) => unsafe {
let _ = Arc::from_raw(new_ptr);
let actual_arc = Arc::from_raw(actual_ptr);
let cloned = actual_arc.clone();
let _ = Arc::into_raw(actual_arc); cloned
},
}
}
#[inline]
pub fn compare_and_exchange_weak(&self, current: &Arc<T>, new: Arc<T>) -> Arc<T> {
let current_ptr = Arc::as_ptr(current) as *mut T;
let new_ptr = Arc::into_raw(new) as *mut T;
match self.inner.compare_exchange_weak(
current_ptr,
new_ptr,
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(prev_ptr) => unsafe { Arc::from_raw(prev_ptr) },
Err(actual_ptr) => unsafe {
let _ = Arc::from_raw(new_ptr);
let actual_arc = Arc::from_raw(actual_ptr);
let cloned = actual_arc.clone();
let _ = Arc::into_raw(actual_arc); cloned
},
}
}
#[inline]
pub fn fetch_update<F>(&self, f: F) -> Arc<T>
where
F: Fn(&Arc<T>) -> Arc<T>,
{
let mut current = self.load();
loop {
let new = f(¤t);
match self.compare_set_weak(¤t, new) {
Ok(_) => return current,
Err(actual) => current = actual,
}
}
}
#[inline]
pub fn inner(&self) -> &AtomicPtr<T> {
&self.inner
}
}
impl<T> Atomic for AtomicRef<T> {
type Value = Arc<T>;
#[inline]
fn load(&self) -> Arc<T> {
self.load()
}
#[inline]
fn store(&self, value: Arc<T>) {
self.store(value);
}
#[inline]
fn swap(&self, value: Arc<T>) -> Arc<T> {
self.swap(value)
}
#[inline]
fn compare_set(&self, current: Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
self.compare_set(¤t, new)
}
#[inline]
fn compare_set_weak(&self, current: Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
self.compare_set_weak(¤t, new)
}
#[inline]
fn compare_exchange(&self, current: Arc<T>, new: Arc<T>) -> Arc<T> {
match self.compare_set(¤t, new.clone()) {
Ok(_) => current,
Err(_) => self.load(),
}
}
#[inline]
fn compare_exchange_weak(&self, current: Arc<T>, new: Arc<T>) -> Arc<T> {
match self.compare_set_weak(¤t, new.clone()) {
Ok(_) => current,
Err(_) => self.load(),
}
}
#[inline]
fn fetch_update<F>(&self, f: F) -> Arc<T>
where
F: Fn(Arc<T>) -> Arc<T>,
{
self.fetch_update(|x| f(x.clone()))
}
}
impl<T> Clone for AtomicRef<T> {
fn clone(&self) -> Self {
Self::new(self.load())
}
}
impl<T> Drop for AtomicRef<T> {
fn drop(&mut self) {
let ptr = self.inner.load(Ordering::Acquire);
unsafe {
if !ptr.is_null() {
Arc::from_raw(ptr);
}
}
}
}
unsafe impl<T: Send + Sync> Send for AtomicRef<T> {}
unsafe impl<T: Send + Sync> Sync for AtomicRef<T> {}
impl<T: fmt::Debug> fmt::Debug for AtomicRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AtomicRef")
.field("value", &self.load())
.finish()
}
}
impl<T: fmt::Display> fmt::Display for AtomicRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.load())
}
}