use core::sync::atomic::Ordering;
use crate::Sealed;
#[expect(private_bounds)]
pub trait PrimitiveAtomic: Sealed + Sized + Send + Sync {
type Value: Copy + Send + Sync + crate::AtomicPrimitive<Atomic = Self>;
fn new(value: Self::Value) -> Self;
fn get_mut(&mut self) -> &mut Self::Value;
fn into_inner(self) -> Self::Value;
fn load(&self, order: Ordering) -> Self::Value;
fn store(&self, value: Self::Value, order: Ordering);
fn swap(&self, value: Self::Value, order: Ordering) -> Self::Value;
fn compare_exchange(
&self,
current: Self::Value,
new: Self::Value,
success: Ordering,
failure: Ordering,
) -> Result<Self::Value, Self::Value>;
fn compare_exchange_weak(
&self,
current: Self::Value,
new: Self::Value,
success: Ordering,
failure: Ordering,
) -> Result<Self::Value, Self::Value>;
fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F,
) -> Result<Self::Value, Self::Value>
where
F: FnMut(Self::Value) -> Option<Self::Value>;
fn fetch_and(&self, val: Self::Value, order: Ordering) -> Self::Value;
fn fetch_nand(&self, val: Self::Value, order: Ordering) -> Self::Value;
fn fetch_or(&self, val: Self::Value, order: Ordering) -> Self::Value;
fn fetch_xor(&self, val: Self::Value, order: Ordering) -> Self::Value;
fn as_ptr(&self) -> *mut Self::Value;
}
macro_rules! impl_primitive_atomic {
($Atomic:ty, $Value:ty) => {
impl Sealed for $Atomic {}
impl PrimitiveAtomic for $Atomic {
type Value = $Value;
forward! {
fn new(value: $Value) -> Self;
fn get_mut(&mut self) -> &mut $Value;
fn into_inner(self) -> $Value;
fn load(&self, order: Ordering) -> $Value;
}
#[inline]
fn store(&self, value: $Value, order: Ordering) {
<$Atomic>::store(self, value, order)
}
forward! {
fn swap(&self, value: $Value, order: Ordering) -> $Value;
fn compare_exchange(&self, current: $Value, new: $Value, success: Ordering, failure: Ordering) -> Result<$Value, $Value>;
fn compare_exchange_weak(&self, current: $Value, new: $Value, success: Ordering, failure: Ordering) -> Result<$Value, $Value>;
}
#[inline]
fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F,
) -> Result<$Value, $Value>
where
F: FnMut($Value) -> Option<$Value>,
{
<$Atomic>::fetch_update(self, set_order, fetch_order, f)
}
forward! {
fn fetch_and(&self, val: $Value, order: Ordering) -> $Value;
fn fetch_nand(&self, val: $Value, order: Ordering) -> $Value;
fn fetch_or(&self, val: $Value, order: Ordering) -> $Value;
fn fetch_xor(&self, val: $Value, order: Ordering) -> $Value;
fn as_ptr(&self) -> *mut $Value;
}
}
};
}
use core::sync::atomic::{
AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicIsize, AtomicU8, AtomicU16, AtomicU32,
AtomicUsize,
};
#[cfg(target_has_atomic = "64")]
use core::sync::atomic::{AtomicI64, AtomicU64};
impl_primitive_atomic!(AtomicBool, bool);
impl_primitive_atomic!(AtomicU8, u8);
impl_primitive_atomic!(AtomicU16, u16);
impl_primitive_atomic!(AtomicU32, u32);
impl_primitive_atomic!(AtomicUsize, usize);
impl_primitive_atomic!(AtomicI8, i8);
impl_primitive_atomic!(AtomicI16, i16);
impl_primitive_atomic!(AtomicI32, i32);
impl_primitive_atomic!(AtomicIsize, isize);
#[cfg(target_has_atomic = "64")]
impl_primitive_atomic!(AtomicU64, u64);
#[cfg(target_has_atomic = "64")]
impl_primitive_atomic!(AtomicI64, i64);