use arc_swap::ArcSwap;
use std::fmt;
use std::sync::Arc;
use crate::atomic::traits::Atomic;
pub struct AtomicRef<T> {
inner: ArcSwap<T>,
}
impl<T> AtomicRef<T> {
#[inline]
pub fn new(value: Arc<T>) -> Self {
Self {
inner: ArcSwap::from(value),
}
}
#[inline]
pub fn load(&self) -> Arc<T> {
self.inner.load_full()
}
#[inline]
pub fn store(&self, value: Arc<T>) {
self.inner.store(value);
}
#[inline]
pub fn swap(&self, value: Arc<T>) -> Arc<T> {
self.inner.swap(value)
}
#[inline]
pub fn compare_set(&self, current: &Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
let prev = Arc::clone(&*self.inner.compare_and_swap(current, new));
if Arc::ptr_eq(&prev, current) {
Ok(())
} else {
Err(prev)
}
}
#[inline]
pub fn compare_set_weak(&self, current: &Arc<T>, new: Arc<T>) -> Result<(), Arc<T>> {
self.compare_set(current, new)
}
#[inline]
pub fn compare_and_exchange(&self, current: &Arc<T>, new: Arc<T>) -> Arc<T> {
Arc::clone(&*self.inner.compare_and_swap(current, new))
}
#[inline]
pub fn compare_and_exchange_weak(&self, current: &Arc<T>, new: Arc<T>) -> Arc<T> {
self.compare_and_exchange(current, new)
}
#[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) -> &ArcSwap<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> {
self.compare_and_exchange(¤t, new)
}
#[inline]
fn compare_exchange_weak(&self, current: Arc<T>, new: Arc<T>) -> Arc<T> {
self.compare_and_exchange_weak(¤t, new)
}
#[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> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.load())
}
}
impl<T: fmt::Debug> fmt::Debug for AtomicRef<T> {
#[inline]
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> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.load())
}
}