Skip to content

Commit

Permalink
add generic Atomic<T> type alias
Browse files Browse the repository at this point in the history
  • Loading branch information
CAD97 committed Sep 19, 2024
1 parent df7f778 commit e65783d
Showing 1 changed file with 94 additions and 0 deletions.
94 changes: 94 additions & 0 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,100 @@ use crate::cell::UnsafeCell;
use crate::hint::spin_loop;
use crate::{fmt, intrinsics};

trait Sealed {}

/// A marker trait for primitive types which can be modified atomically.
///
/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
///
/// # Safety
///
/// Types implementing this trait must be primitives that can be modified atomically.
///
/// The associated `Self::AtomicInner` type must have the same size and bit validity as `Self`,
/// but may have a higher alignment requirement, so the following `transmute`s are sound:
///
/// - `&mut Self::AtomicInner` as `&mut Self`
/// - `Self` as `Self::AtomicInner` or the reverse
#[unstable(
feature = "atomic_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
#[allow(private_bounds)]
pub unsafe trait AtomicPrimitive: Sized + Copy + Sealed {
#[doc(hidden)]
type AtomicInner: Sized;
}

macro impl_atomic_primitive(
$Atom:ident $(<$T:ident>)? ($Primitive:ty),
size($size:literal),
align($align:literal) $(,)?
) {
impl $(<$T>)? Sealed for $Primitive {}

#[unstable(
feature = "atomic_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
#[cfg(target_has_atomic_load_store = $size)]
unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
type AtomicInner = $Atom $(<$T>)?;
}
}

impl_atomic_primitive!(AtomicBool(bool), size("8"), align(1));
impl_atomic_primitive!(AtomicI8(i8), size("8"), align(1));
impl_atomic_primitive!(AtomicU8(u8), size("8"), align(1));
impl_atomic_primitive!(AtomicI16(i16), size("16"), align(2));
impl_atomic_primitive!(AtomicU16(u16), size("16"), align(2));
impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4));
impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4));
impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8));
impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8));
impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16));
impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16));

#[cfg(target_pointer_width = "16")]
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2));
#[cfg(target_pointer_width = "32")]
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(4));
#[cfg(target_pointer_width = "64")]
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(8));

#[cfg(target_pointer_width = "16")]
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(2));
#[cfg(target_pointer_width = "32")]
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(4));
#[cfg(target_pointer_width = "64")]
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(8));

#[cfg(target_pointer_width = "16")]
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(2));
#[cfg(target_pointer_width = "32")]
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(4));
#[cfg(target_pointer_width = "64")]
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(8));

/// A memory location which can be safely modified from multiple threads.
///
/// This has the same size and bit validity as the underlying type `T`. However,
/// the alignment of this type is always equal to its size, even on targets where
/// `T` has alignment less than its size.
///
/// For more about the differences between atomic types and non-atomic types as
/// well as information about the portability of this type, please see the
/// [module-level documentation].
///
/// **Note:** This type is only available on platforms that support atomic loads
/// and stores of `T`.
///
/// [module-level documentation]: crate::sync::atomic
#[unstable(feature = "generic_atomic", issue = "130539")]
pub type Atomic<T> = <T as AtomicPrimitive>::AtomicInner;

// Some architectures don't have byte-sized atomics, which results in LLVM
// emulating them using a LL/SC loop. However for AtomicBool we can take
// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
Expand Down

0 comments on commit e65783d

Please sign in to comment.