@@ -247,6 +247,100 @@ use crate::cell::UnsafeCell;
247
247
use crate :: hint:: spin_loop;
248
248
use crate :: { fmt, intrinsics} ;
249
249
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
+ #[ expect( private_bounds) ]
271
+ pub unsafe trait AtomicPrimitive : Sized + Copy + Sealed {
272
+ /// Temporary implementation detail.
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
+
250
344
// Some architectures don't have byte-sized atomics, which results in LLVM
251
345
// emulating them using a LL/SC loop. However for AtomicBool we can take
252
346
// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
0 commit comments