Skip to content

Commit e65783d

Browse files
committed
add generic Atomic<T> type alias
1 parent df7f778 commit e65783d

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

library/core/src/sync/atomic.rs

+94
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,100 @@ use crate::cell::UnsafeCell;
227227
use crate::hint::spin_loop;
228228
use crate::{fmt, intrinsics};
229229

230+
trait Sealed {}
231+
232+
/// A marker trait for primitive types which can be modified atomically.
233+
///
234+
/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
235+
///
236+
/// # Safety
237+
///
238+
/// Types implementing this trait must be primitives that can be modified atomically.
239+
///
240+
/// The associated `Self::AtomicInner` type must have the same size and bit validity as `Self`,
241+
/// but may have a higher alignment requirement, so the following `transmute`s are sound:
242+
///
243+
/// - `&mut Self::AtomicInner` as `&mut Self`
244+
/// - `Self` as `Self::AtomicInner` or the reverse
245+
#[unstable(
246+
feature = "atomic_internals",
247+
reason = "implementation detail which may disappear or be replaced at any time",
248+
issue = "none"
249+
)]
250+
#[allow(private_bounds)]
251+
pub unsafe trait AtomicPrimitive: Sized + Copy + Sealed {
252+
#[doc(hidden)]
253+
type AtomicInner: Sized;
254+
}
255+
256+
macro impl_atomic_primitive(
257+
$Atom:ident $(<$T:ident>)? ($Primitive:ty),
258+
size($size:literal),
259+
align($align:literal) $(,)?
260+
) {
261+
impl $(<$T>)? Sealed for $Primitive {}
262+
263+
#[unstable(
264+
feature = "atomic_internals",
265+
reason = "implementation detail which may disappear or be replaced at any time",
266+
issue = "none"
267+
)]
268+
#[cfg(target_has_atomic_load_store = $size)]
269+
unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
270+
type AtomicInner = $Atom $(<$T>)?;
271+
}
272+
}
273+
274+
impl_atomic_primitive!(AtomicBool(bool), size("8"), align(1));
275+
impl_atomic_primitive!(AtomicI8(i8), size("8"), align(1));
276+
impl_atomic_primitive!(AtomicU8(u8), size("8"), align(1));
277+
impl_atomic_primitive!(AtomicI16(i16), size("16"), align(2));
278+
impl_atomic_primitive!(AtomicU16(u16), size("16"), align(2));
279+
impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4));
280+
impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4));
281+
impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8));
282+
impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8));
283+
impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16));
284+
impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16));
285+
286+
#[cfg(target_pointer_width = "16")]
287+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2));
288+
#[cfg(target_pointer_width = "32")]
289+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(4));
290+
#[cfg(target_pointer_width = "64")]
291+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(8));
292+
293+
#[cfg(target_pointer_width = "16")]
294+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(2));
295+
#[cfg(target_pointer_width = "32")]
296+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(4));
297+
#[cfg(target_pointer_width = "64")]
298+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(8));
299+
300+
#[cfg(target_pointer_width = "16")]
301+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(2));
302+
#[cfg(target_pointer_width = "32")]
303+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(4));
304+
#[cfg(target_pointer_width = "64")]
305+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(8));
306+
307+
/// A memory location which can be safely modified from multiple threads.
308+
///
309+
/// This has the same size and bit validity as the underlying type `T`. However,
310+
/// the alignment of this type is always equal to its size, even on targets where
311+
/// `T` has alignment less than its size.
312+
///
313+
/// For more about the differences between atomic types and non-atomic types as
314+
/// well as information about the portability of this type, please see the
315+
/// [module-level documentation].
316+
///
317+
/// **Note:** This type is only available on platforms that support atomic loads
318+
/// and stores of `T`.
319+
///
320+
/// [module-level documentation]: crate::sync::atomic
321+
#[unstable(feature = "generic_atomic", issue = "130539")]
322+
pub type Atomic<T> = <T as AtomicPrimitive>::AtomicInner;
323+
230324
// Some architectures don't have byte-sized atomics, which results in LLVM
231325
// emulating them using a LL/SC loop. However for AtomicBool we can take
232326
// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND

0 commit comments

Comments
 (0)