@@ -227,6 +227,100 @@ use crate::cell::UnsafeCell;
227
227
use crate :: hint:: spin_loop;
228
228
use crate :: { fmt, intrinsics} ;
229
229
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
+
230
324
// Some architectures don't have byte-sized atomics, which results in LLVM
231
325
// emulating them using a LL/SC loop. However for AtomicBool we can take
232
326
// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
@@ -388,7 +482,7 @@ pub enum Ordering {
388
482
note = "the `new` function is now preferred" ,
389
483
suggestion = "AtomicBool::new(false)"
390
484
) ]
391
- pub const ATOMIC_BOOL_INIT : AtomicBool = AtomicBool :: new ( false ) ;
485
+ pub const ATOMIC_BOOL_INIT : Atomic < bool > = AtomicBool :: new ( false ) ;
392
486
393
487
#[ cfg( target_has_atomic_load_store = "8" ) ]
394
488
impl AtomicBool {
@@ -3253,7 +3347,7 @@ macro_rules! atomic_int_ptr_sized {
3253
3347
note = "the `new` function is now preferred" ,
3254
3348
suggestion = "AtomicIsize::new(0)" ,
3255
3349
) ]
3256
- pub const ATOMIC_ISIZE_INIT : AtomicIsize = AtomicIsize :: new( 0 ) ;
3350
+ pub const ATOMIC_ISIZE_INIT : Atomic < isize > = AtomicIsize :: new( 0 ) ;
3257
3351
3258
3352
/// An [`AtomicUsize`] initialized to `0`.
3259
3353
#[ cfg( target_pointer_width = $target_pointer_width) ]
@@ -3263,7 +3357,7 @@ macro_rules! atomic_int_ptr_sized {
3263
3357
note = "the `new` function is now preferred" ,
3264
3358
suggestion = "AtomicUsize::new(0)" ,
3265
3359
) ]
3266
- pub const ATOMIC_USIZE_INIT : AtomicUsize = AtomicUsize :: new( 0 ) ;
3360
+ pub const ATOMIC_USIZE_INIT : Atomic < usize > = AtomicUsize :: new( 0 ) ;
3267
3361
) * } ;
3268
3362
}
3269
3363
0 commit comments