Skip to content

Commit ece3636

Browse files
CAD97GrigorenkoPV
authored andcommitted
add generic Atomic<T> type alias
1 parent a6434ef commit ece3636

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
@@ -246,6 +246,100 @@ use crate::cell::UnsafeCell;
246246
use crate::hint::spin_loop;
247247
use crate::{fmt, intrinsics};
248248

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

0 commit comments

Comments
 (0)