use crate::shim::atomic::Ordering;
use crate::shim::atomic::{
AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicU8, AtomicU16,
AtomicU32, AtomicU64, AtomicUsize,
};
pub trait AtomicElement: Send + Sync {
type Primitive: Copy;
fn load(&self, order: Ordering) -> Self::Primitive;
fn store(&self, val: Self::Primitive, order: Ordering);
fn swap(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive;
}
macro_rules! impl_atomic_element {
($atomic:ty, $primitive:ty) => {
impl AtomicElement for $atomic {
type Primitive = $primitive;
#[inline(always)]
fn load(&self, order: Ordering) -> Self::Primitive {
self.load(order)
}
#[inline(always)]
fn store(&self, val: Self::Primitive, order: Ordering) {
self.store(val, order);
}
#[inline(always)]
fn swap(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
self.swap(val, order)
}
}
};
}
impl_atomic_element!(AtomicU8, u8);
impl_atomic_element!(AtomicU16, u16);
impl_atomic_element!(AtomicU32, u32);
impl_atomic_element!(AtomicU64, u64);
impl_atomic_element!(AtomicUsize, usize);
impl_atomic_element!(AtomicI8, i8);
impl_atomic_element!(AtomicI16, i16);
impl_atomic_element!(AtomicI32, i32);
impl_atomic_element!(AtomicI64, i64);
impl_atomic_element!(AtomicIsize, isize);
impl_atomic_element!(AtomicBool, bool);
#[cfg(any(feature = "loom", feature = "portable-atomic"))]
macro_rules! impl_core_atomic_element {
($atomic:ty, $primitive:ty) => {
impl AtomicElement for $atomic {
type Primitive = $primitive;
#[inline(always)]
fn load(&self, order: Ordering) -> Self::Primitive {
let core_order = match order {
Ordering::Relaxed => core::sync::atomic::Ordering::Relaxed,
Ordering::Release => core::sync::atomic::Ordering::Release,
Ordering::Acquire => core::sync::atomic::Ordering::Acquire,
Ordering::AcqRel => core::sync::atomic::Ordering::AcqRel,
Ordering::SeqCst => core::sync::atomic::Ordering::SeqCst,
_ => core::sync::atomic::Ordering::SeqCst,
};
self.load(core_order)
}
#[inline(always)]
fn store(&self, val: Self::Primitive, order: Ordering) {
let core_order = match order {
Ordering::Relaxed => core::sync::atomic::Ordering::Relaxed,
Ordering::Release => core::sync::atomic::Ordering::Release,
Ordering::Acquire => core::sync::atomic::Ordering::Acquire,
Ordering::AcqRel => core::sync::atomic::Ordering::AcqRel,
Ordering::SeqCst => core::sync::atomic::Ordering::SeqCst,
_ => core::sync::atomic::Ordering::SeqCst,
};
self.store(val, core_order);
}
#[inline(always)]
fn swap(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
let core_order = match order {
Ordering::Relaxed => core::sync::atomic::Ordering::Relaxed,
Ordering::Release => core::sync::atomic::Ordering::Release,
Ordering::Acquire => core::sync::atomic::Ordering::Acquire,
Ordering::AcqRel => core::sync::atomic::Ordering::AcqRel,
Ordering::SeqCst => core::sync::atomic::Ordering::SeqCst,
_ => core::sync::atomic::Ordering::SeqCst,
};
self.swap(val, core_order)
}
}
};
}
#[cfg(any(feature = "loom", feature = "portable-atomic"))]
mod core_atomic_impls {
use super::*;
#[cfg(target_has_atomic = "8")]
impl_core_atomic_element!(core::sync::atomic::AtomicBool, bool);
#[cfg(target_has_atomic = "8")]
impl_core_atomic_element!(core::sync::atomic::AtomicU8, u8);
#[cfg(target_has_atomic = "8")]
impl_core_atomic_element!(core::sync::atomic::AtomicI8, i8);
#[cfg(target_has_atomic = "16")]
impl_core_atomic_element!(core::sync::atomic::AtomicU16, u16);
#[cfg(target_has_atomic = "16")]
impl_core_atomic_element!(core::sync::atomic::AtomicI16, i16);
#[cfg(target_has_atomic = "32")]
impl_core_atomic_element!(core::sync::atomic::AtomicU32, u32);
#[cfg(target_has_atomic = "32")]
impl_core_atomic_element!(core::sync::atomic::AtomicI32, i32);
#[cfg(target_has_atomic = "64")]
impl_core_atomic_element!(core::sync::atomic::AtomicU64, u64);
#[cfg(target_has_atomic = "64")]
impl_core_atomic_element!(core::sync::atomic::AtomicI64, i64);
#[cfg(target_has_atomic = "ptr")]
impl_core_atomic_element!(core::sync::atomic::AtomicUsize, usize);
#[cfg(target_has_atomic = "ptr")]
impl_core_atomic_element!(core::sync::atomic::AtomicIsize, isize);
}
pub trait AtomicNumeric: AtomicElement {
fn fetch_add(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive;
fn fetch_sub(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive;
}
macro_rules! impl_atomic_numeric {
($atomic:ty, $primitive:ty) => {
impl AtomicNumeric for $atomic {
#[inline]
fn fetch_add(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
self.fetch_add(val, order)
}
#[inline]
fn fetch_sub(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
self.fetch_sub(val, order)
}
}
};
}
impl_atomic_numeric!(AtomicU8, u8);
impl_atomic_numeric!(AtomicU16, u16);
impl_atomic_numeric!(AtomicU32, u32);
impl_atomic_numeric!(AtomicU64, u64);
impl_atomic_numeric!(AtomicUsize, usize);
impl_atomic_numeric!(AtomicI8, i8);
impl_atomic_numeric!(AtomicI16, i16);
impl_atomic_numeric!(AtomicI32, i32);
impl_atomic_numeric!(AtomicI64, i64);
impl_atomic_numeric!(AtomicIsize, isize);
#[cfg(any(feature = "loom", feature = "portable-atomic"))]
macro_rules! impl_core_atomic_numeric {
($atomic:ty) => {
impl AtomicNumeric for $atomic {
#[inline]
fn fetch_add(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
let core_order = match order {
Ordering::Relaxed => core::sync::atomic::Ordering::Relaxed,
Ordering::Release => core::sync::atomic::Ordering::Release,
Ordering::Acquire => core::sync::atomic::Ordering::Acquire,
Ordering::AcqRel => core::sync::atomic::Ordering::AcqRel,
Ordering::SeqCst => core::sync::atomic::Ordering::SeqCst,
_ => core::sync::atomic::Ordering::SeqCst,
};
self.fetch_add(val, core_order)
}
#[inline]
fn fetch_sub(&self, val: Self::Primitive, order: Ordering) -> Self::Primitive {
let core_order = match order {
Ordering::Relaxed => core::sync::atomic::Ordering::Relaxed,
Ordering::Release => core::sync::atomic::Ordering::Release,
Ordering::Acquire => core::sync::atomic::Ordering::Acquire,
Ordering::AcqRel => core::sync::atomic::Ordering::AcqRel,
Ordering::SeqCst => core::sync::atomic::Ordering::SeqCst,
_ => core::sync::atomic::Ordering::SeqCst,
};
self.fetch_sub(val, core_order)
}
}
};
}
#[cfg(any(feature = "loom", feature = "portable-atomic"))]
mod core_atomic_numeric_impls {
use super::*;
#[cfg(target_has_atomic = "8")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicU8);
#[cfg(target_has_atomic = "8")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicI8);
#[cfg(target_has_atomic = "16")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicU16);
#[cfg(target_has_atomic = "16")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicI16);
#[cfg(target_has_atomic = "32")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicU32);
#[cfg(target_has_atomic = "32")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicI32);
#[cfg(target_has_atomic = "64")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicU64);
#[cfg(target_has_atomic = "64")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicI64);
#[cfg(target_has_atomic = "ptr")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicUsize);
#[cfg(target_has_atomic = "ptr")]
impl_core_atomic_numeric!(core::sync::atomic::AtomicIsize);
}