use core::sync::atomic::Ordering;
pub(crate) mod sealed {
pub trait Sealed {}
}
pub trait AtomicOrder: sealed::Sealed + Copy {
const LOAD: Ordering;
const STORE: Ordering;
const RMW: Ordering;
const FAILURE: Ordering;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Relaxed;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct AcqRel;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct SeqCst;
impl AtomicOrder for Relaxed {
const LOAD: Ordering = Ordering::Relaxed;
const STORE: Ordering = Ordering::Relaxed;
const RMW: Ordering = Ordering::Relaxed;
const FAILURE: Ordering = Ordering::Relaxed;
}
impl AtomicOrder for AcqRel {
const LOAD: Ordering = Ordering::Acquire;
const STORE: Ordering = Ordering::Release;
const RMW: Ordering = Ordering::AcqRel;
const FAILURE: Ordering = Ordering::Acquire;
}
impl AtomicOrder for SeqCst {
const LOAD: Ordering = Ordering::SeqCst;
const STORE: Ordering = Ordering::SeqCst;
const RMW: Ordering = Ordering::SeqCst;
const FAILURE: Ordering = Ordering::SeqCst;
}
impl sealed::Sealed for Relaxed {}
impl sealed::Sealed for AcqRel {}
impl sealed::Sealed for SeqCst {}
pub(crate) trait OrderingSource: Copy {
fn load_order(self) -> Ordering;
fn store_order(self) -> Ordering;
fn rmw_order(self) -> Ordering;
fn failure_order(self) -> Ordering;
}
impl OrderingSource for Ordering {
#[inline]
fn load_order(self) -> Ordering {
self
}
#[inline]
fn store_order(self) -> Ordering {
self
}
#[inline]
fn rmw_order(self) -> Ordering {
self
}
#[inline]
fn failure_order(self) -> Ordering {
self
}
}
impl<O: AtomicOrder> OrderingSource for O {
#[inline]
fn load_order(self) -> Ordering {
O::LOAD
}
#[inline]
fn store_order(self) -> Ordering {
O::STORE
}
#[inline]
fn rmw_order(self) -> Ordering {
O::RMW
}
#[inline]
fn failure_order(self) -> Ordering {
O::FAILURE
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ordering_sources_preserve_runtime_and_policy_roles() {
assert_eq!(Ordering::Relaxed.load_order(), Ordering::Relaxed);
assert_eq!(Ordering::Acquire.store_order(), Ordering::Acquire);
assert_eq!(Ordering::Release.rmw_order(), Ordering::Release);
assert_eq!(Ordering::AcqRel.failure_order(), Ordering::AcqRel);
assert_eq!(Relaxed.load_order(), Ordering::Relaxed);
assert_eq!(AcqRel.store_order(), Ordering::Release);
assert_eq!(AcqRel.rmw_order(), Ordering::AcqRel);
assert_eq!(AcqRel.failure_order(), Ordering::Acquire);
assert_eq!(SeqCst.failure_order(), Ordering::SeqCst);
}
}