Skip to content

Commit c1926bc

Browse files
CAD97GrigorenkoPV
authored andcommitted
add generic Atomic<T> type alias
1 parent 49e5e4e commit c1926bc

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

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

0 commit comments

Comments
 (0)