use core::fmt;
use core::marker::PhantomData;
use core::sync::atomic::Ordering;
use super::order::AtomicOrder;
use super::traits::{Atomic, AtomicInt};
use crate::token::{InvariantLifetime, ReadPermit, WritePermit};
#[repr(transparent)]
pub struct BrandedAtomic<'brand, A: Atomic> {
inner: A,
_brand: InvariantLifetime<'brand>,
}
impl<'brand, A: Atomic> BrandedAtomic<'brand, A> {
#[inline]
pub fn new(value: A::Value) -> Self {
Self {
inner: A::new_atomic(value),
_brand: PhantomData,
}
}
#[inline]
#[must_use]
pub fn from_mut(atomic: &mut A) -> &mut Self {
unsafe { &mut *(atomic as *mut A as *mut Self) }
}
#[inline]
#[must_use]
pub fn as_atomic<'a, P>(&'a self, _permit: P) -> &'a A
where
P: ReadPermit<'brand> + 'a,
{
&self.inner
}
#[inline]
#[must_use]
pub fn as_atomic_mut(&mut self) -> &mut A {
&mut self.inner
}
#[inline]
#[must_use]
pub fn into_atomic(self) -> A {
self.inner
}
#[inline]
pub fn with_exclusive<P, R>(&self, _permit: P, f: impl FnOnce(&mut A::Value) -> R) -> R
where
P: WritePermit<'brand>,
{
f(unsafe { &mut *self.inner.value_ptr() })
}
#[inline]
pub fn load_exclusive<P>(&self, permit: P) -> A::Value
where
P: WritePermit<'brand>,
{
self.with_exclusive(permit, |v| *v)
}
#[inline]
pub fn store_exclusive<P>(&self, value: A::Value, permit: P)
where
P: WritePermit<'brand>,
{
self.with_exclusive(permit, |v| *v = value);
}
#[inline]
pub fn get_mut(&mut self) -> &mut A::Value {
self.inner.atomic_get_mut()
}
#[inline]
pub fn into_inner(self) -> A::Value {
self.inner.atomic_into_inner()
}
#[inline]
pub fn load<P>(&self, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_load(order)
}
#[inline]
pub fn load_with<P, O>(&self, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_load(O::LOAD)
}
#[inline]
pub fn store<P>(&self, value: A::Value, _permit: P, order: Ordering)
where
P: ReadPermit<'brand>,
{
self.inner.atomic_store(value, order);
}
#[inline]
pub fn store_with<P, O>(&self, value: A::Value, _permit: P, _order: O)
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_store(value, O::STORE);
}
#[inline]
pub fn swap<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_swap(value, order)
}
#[inline]
pub fn swap_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_swap(value, O::RMW)
}
#[inline]
pub fn compare_exchange<P>(
&self,
current: A::Value,
new: A::Value,
success: Ordering,
failure: Ordering,
_permit: P,
) -> Result<A::Value, A::Value>
where
P: ReadPermit<'brand>,
{
self.inner
.atomic_compare_exchange(current, new, success, failure)
}
#[inline]
pub fn compare_exchange_with<P, O>(
&self,
current: A::Value,
new: A::Value,
_permit: P,
_order: O,
) -> Result<A::Value, A::Value>
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner
.atomic_compare_exchange(current, new, O::RMW, O::FAILURE)
}
#[inline]
pub fn fetch_update<P, F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
_permit: P,
f: F,
) -> Result<A::Value, A::Value>
where
P: ReadPermit<'brand>,
F: FnMut(A::Value) -> Option<A::Value>,
{
self.inner.atomic_fetch_update(set_order, fetch_order, f)
}
#[inline]
pub fn fetch_update_with<P, O, F>(
&self,
_permit: P,
_order: O,
f: F,
) -> Result<A::Value, A::Value>
where
P: ReadPermit<'brand>,
O: AtomicOrder,
F: FnMut(A::Value) -> Option<A::Value>,
{
self.inner.atomic_fetch_update(O::RMW, O::FAILURE, f)
}
}
impl<'brand, A: AtomicInt> BrandedAtomic<'brand, A> {
#[inline]
pub fn fetch_add<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_add(value, order)
}
#[inline]
pub fn fetch_add_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_add(value, O::RMW)
}
#[inline]
pub fn fetch_sub<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_sub(value, order)
}
#[inline]
pub fn fetch_sub_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_sub(value, O::RMW)
}
#[inline]
pub fn fetch_and<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_and(value, order)
}
#[inline]
pub fn fetch_and_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_and(value, O::RMW)
}
#[inline]
pub fn fetch_or<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_or(value, order)
}
#[inline]
pub fn fetch_or_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_or(value, O::RMW)
}
#[inline]
pub fn fetch_xor<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_xor(value, order)
}
#[inline]
pub fn fetch_xor_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_xor(value, O::RMW)
}
#[inline]
pub fn fetch_nand<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_nand(value, order)
}
#[inline]
pub fn fetch_nand_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_nand(value, O::RMW)
}
#[inline]
pub fn fetch_max<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_max(value, order)
}
#[inline]
pub fn fetch_max_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_max(value, O::RMW)
}
#[inline]
pub fn fetch_min<P>(&self, value: A::Value, _permit: P, order: Ordering) -> A::Value
where
P: ReadPermit<'brand>,
{
self.inner.atomic_fetch_min(value, order)
}
#[inline]
pub fn fetch_min_with<P, O>(&self, value: A::Value, _permit: P, _order: O) -> A::Value
where
P: ReadPermit<'brand>,
O: AtomicOrder,
{
self.inner.atomic_fetch_min(value, O::RMW)
}
}
impl<'brand, A: Atomic + fmt::Debug> fmt::Debug for BrandedAtomic<'brand, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("BrandedAtomic").field(&self.inner).finish()
}
}