Skip to main content

atomic_primitive/
integer.rs

1use core::sync::atomic::Ordering;
2
3use crate::PrimitiveAtomic;
4
5/// Trait for all primitive atomic [integer types], extending [`PrimitiveAtomic`].
6///
7/// This adds integer-specific atomic operations: [`fetch_add`], [`fetch_sub`],
8/// [`fetch_max`], [`fetch_min`], and a [`BITS`] constant.
9///
10/// This trait is sealed to prevent downstream implementations.
11///
12/// [`fetch_add`]: PrimitiveAtomicInteger::fetch_add
13/// [`fetch_sub`]: PrimitiveAtomicInteger::fetch_sub
14/// [`fetch_max`]: PrimitiveAtomicInteger::fetch_max
15/// [`fetch_min`]: PrimitiveAtomicInteger::fetch_min
16/// [`BITS`]: PrimitiveAtomicInteger::BITS
17/// [integer types]: core::sync::atomic
18pub trait PrimitiveAtomicInteger: PrimitiveAtomic {
19    /// The size of this atomic integer type in bits.
20    const BITS: u32;
21
22    /// Adds to the current value, returning the previous value.
23    fn fetch_add(&self, val: Self::Value, order: Ordering) -> Self::Value;
24
25    /// Subtracts from the current value, returning the previous value.
26    fn fetch_sub(&self, val: Self::Value, order: Ordering) -> Self::Value;
27
28    /// Stores the maximum of the current value and `val`. Returns the previous value.
29    fn fetch_max(&self, val: Self::Value, order: Ordering) -> Self::Value;
30
31    /// Stores the minimum of the current value and `val`. Returns the previous value.
32    fn fetch_min(&self, val: Self::Value, order: Ordering) -> Self::Value;
33}
34
35macro_rules! impl_primitive_atomic_integer {
36    ($Atomic:ty, $bits:expr) => {
37        impl PrimitiveAtomicInteger for $Atomic {
38            const BITS: u32 = $bits;
39
40            forward! {
41                fn fetch_add(&self, val: Self::Value, order: Ordering) -> Self::Value;
42                fn fetch_sub(&self, val: Self::Value, order: Ordering) -> Self::Value;
43                fn fetch_max(&self, val: Self::Value, order: Ordering) -> Self::Value;
44                fn fetch_min(&self, val: Self::Value, order: Ordering) -> Self::Value;
45            }
46        }
47    };
48}
49
50use core::sync::atomic::{
51    AtomicI8, AtomicI16, AtomicI32, AtomicIsize, AtomicU8, AtomicU16, AtomicU32, AtomicUsize,
52};
53#[cfg(target_has_atomic = "64")]
54use core::sync::atomic::{AtomicI64, AtomicU64};
55
56impl_primitive_atomic_integer!(AtomicU8, 8);
57impl_primitive_atomic_integer!(AtomicU16, 16);
58impl_primitive_atomic_integer!(AtomicU32, 32);
59impl_primitive_atomic_integer!(AtomicUsize, usize::BITS);
60impl_primitive_atomic_integer!(AtomicI8, 8);
61impl_primitive_atomic_integer!(AtomicI16, 16);
62impl_primitive_atomic_integer!(AtomicI32, 32);
63impl_primitive_atomic_integer!(AtomicIsize, isize::BITS);
64#[cfg(target_has_atomic = "64")]
65impl_primitive_atomic_integer!(AtomicU64, 64);
66#[cfg(target_has_atomic = "64")]
67impl_primitive_atomic_integer!(AtomicI64, 64);