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