pub use core::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
};
use Ordering::*;
use crate::cell::generic::{StorageMarker, UnderlyingMarker};
use crate::utils::maybe_const;
#[cfg(feature = "const")]
#[macro_use]
mod const_impl;
#[cfg(not(feature = "const"))]
#[macro_use]
mod non_const_impl;
#[cfg(feature = "const")]
pub use const_impl::*;
#[cfg(not(feature = "const"))]
pub use non_const_impl::*;
pub struct AtomicUnit {
v: (),
}
maybe_const! {
impl const From<()> for AtomicUnit {
fn from(v: ()) -> Self {
Self { v }
}
}
}
impl AtomicUnit {
pub const fn new(v: ()) -> Self {
AtomicUnit { v }
}
pub const fn into_inner(self) -> () {
self.v
}
maybe_const! {
pub const fn get_mut(&mut self) -> &mut () {
&mut self.v
}
}
pub const fn load(&self, order: Ordering) -> () {
match order {
Release => panic!("there is no such thing as a release load"),
AcqRel => panic!("there is no such thing as an acquire/release load"),
_ => self.v,
}
self.v
}
pub const fn store(&self, _val: (), order: Ordering) {
match order {
Acquire => panic!("there is no such thing as a release store"),
AcqRel => panic!("there is no such thing as an acquire/release store"),
_ => self.v,
}
}
pub const fn swap(&self, _val: (), _order: Ordering) -> () {}
pub const fn compare_exchange(
&self,
_current: (),
_new: (),
success: Ordering,
failure: Ordering,
) -> Result<(), ()> {
match (success, failure) {
(_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
(Relaxed, Relaxed)
| (Acquire, Relaxed)
| (Acquire, Acquire)
| (Release, Relaxed)
| (AcqRel, Relaxed)
| (AcqRel, Acquire)
| (SeqCst, _) => Ok(()),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
}
}
pub const fn compare_exchange_weak(
&self,
_current: (),
_new: (),
success: Ordering,
failure: Ordering,
) -> Result<(), ()> {
match (success, failure) {
(_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
(Relaxed, Relaxed)
| (Acquire, Relaxed)
| (Acquire, Acquire)
| (Release, Relaxed)
| (AcqRel, Relaxed)
| (AcqRel, Acquire)
| (SeqCst, _) => Ok(()),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
}
}
}
pub trait FromInner<A> {
fn from_inner(a: A) -> Self;
}
pub trait AtomicStorage: Sized + Send + Sync + AtomicStorageBase {
const ZERO: Self::Underlying;
fn forgettable() -> Self {
Self::new(Self::ZERO)
}
fn new(v: Self::Underlying) -> Self;
fn into_inner(self) -> Self::Underlying;
fn get_mut(&mut self) -> &mut Self::Underlying;
fn load(&self, _order: Ordering) -> Self::Underlying;
fn store(&self, val: Self::Underlying, order: Ordering);
fn swap(&self, val: Self::Underlying, order: Ordering) -> Self::Underlying;
fn compare_exchange(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying>;
fn compare_exchange_weak(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying>;
}
pub fn compare_exchange<A: AtomicStorage, const WEAK: bool>(
a: &A,
current: A::Underlying,
new: A::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<A::Underlying, A::Underlying> {
if WEAK {
a.compare_exchange_weak(current, new, success, failure)
} else {
a.compare_exchange(current, new, success, failure)
}
}
macro_rules! impl_storage {
(<$($g:ident)?> $t1:ty, $t2:ty, $z:expr) => {
impl $(<$g>)? AtomicStorageBase for $t1 {
type Underlying = $t2;
}
impl $(<$g>)? AtomicStorage for $t1 {
const ZERO: Self::Underlying = $z as $t2;
fn new(val: Self::Underlying) -> Self {
<$t1>::new(val)
}
fn into_inner(self) -> Self::Underlying {
<$t1>::into_inner(self)
}
fn get_mut(&mut self) -> &mut Self::Underlying {
<$t1>::get_mut(self)
}
fn load(&self, order: Ordering) -> Self::Underlying {
<$t1>::load(self, order)
}
fn store(&self, val: Self::Underlying, order: Ordering) {
<$t1>::store(self, val, order)
}
fn swap(&self, val: Self::Underlying, order: Ordering) -> Self::Underlying {
<$t1>::swap(self, val, order)
}
fn compare_exchange(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying> {
<$t1>::compare_exchange(self, current, new, success, failure)
}
fn compare_exchange_weak(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying> {
<$t1>::compare_exchange_weak(self, current, new, success, failure)
}
}
impl_storage_inner!{<$($g)?> $t1, $t2, $z}
};
(<$($g:ident)?> $t1:ty, $t2:ty) => { impl_storage!{<$($g)?> $t1, $t2, 0} };
($t1:ty, $t2:ty, $z:expr) => { impl_storage!{<> $t1, $t2, $z} };
($t1:ty, $t2:ty) => { impl_storage!{<> $t1, $t2, 0} };
}
impl_storage! {<T> AtomicPtr<T>, *mut T, core::ptr::null_mut::<T>()}
impl_storage! {AtomicUsize, usize}
impl_storage! {AtomicIsize, isize}
impl_storage! {AtomicU64, u64}
impl_storage! {AtomicI64, i64}
impl_storage! {AtomicU32, u32}
impl_storage! {AtomicI32, i32}
impl_storage! {AtomicU16, u16}
impl_storage! {AtomicI16, i16}
impl_storage! {AtomicU8, u8}
impl_storage! {AtomicI8, i8}
impl_storage! {AtomicBool, bool, false}
impl_storage! {AtomicUnit, (), ()}
impl<A: AtomicStorageBase> AtomicStorageBase for StorageMarker<A> {
type Underlying = UnderlyingMarker<A::Underlying>;
}
impl<A: AtomicStorage> AtomicStorage for StorageMarker<A> {
const ZERO: Self::Underlying = UnderlyingMarker::new(A::ZERO);
fn new(val: Self::Underlying) -> Self {
StorageMarker::new(A::new(val.into_inner()))
}
fn into_inner(self) -> Self::Underlying {
UnderlyingMarker::new(StorageMarker::into_inner(self).into_inner())
}
fn get_mut(&mut self) -> &mut Self::Underlying {
UnderlyingMarker::as_mut((self as &mut A).get_mut())
}
fn load(&self, order: Ordering) -> Self::Underlying {
UnderlyingMarker::new((self as &A).load(order))
}
fn store(&self, val: Self::Underlying, order: Ordering) {
(self as &A).store(val.into_inner(), order)
}
fn swap(&self, val: Self::Underlying, order: Ordering) -> Self::Underlying {
UnderlyingMarker::new((self as &A).swap(val.into_inner(), order))
}
fn compare_exchange(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying> {
(self as &A)
.compare_exchange(current.into_inner(), new.into_inner(), success, failure)
.map(UnderlyingMarker::new)
.map_err(UnderlyingMarker::new)
}
fn compare_exchange_weak(
&self,
current: Self::Underlying,
new: Self::Underlying,
success: Ordering,
failure: Ordering,
) -> Result<Self::Underlying, Self::Underlying> {
(self as &A)
.compare_exchange_weak(current.into_inner(), new.into_inner(), success, failure)
.map(UnderlyingMarker::new)
.map_err(UnderlyingMarker::new)
}
}