@@ -110,6 +110,7 @@ use self::Ordering::*;
110
110
use crate :: cell:: UnsafeCell ;
111
111
use crate :: fmt;
112
112
use crate :: intrinsics;
113
+ use crate :: mem:: align_of;
113
114
114
115
use crate :: hint:: spin_loop;
115
116
@@ -327,6 +328,27 @@ impl AtomicBool {
327
328
unsafe { & mut * ( self . v . get ( ) as * mut bool ) }
328
329
}
329
330
331
+ /// Get atomic access to a `&mut bool`.
332
+ ///
333
+ /// # Examples
334
+ ///
335
+ /// ```
336
+ /// #![feature(atomic_from_mut)]
337
+ /// use std::sync::atomic::{AtomicBool, Ordering};
338
+ ///
339
+ /// let mut some_bool = true;
340
+ /// let a = AtomicBool::from_mut(&mut some_bool);
341
+ /// a.store(false, Ordering::Relaxed);
342
+ /// assert_eq!(some_bool, false);
343
+ /// ```
344
+ #[ inline]
345
+ #[ unstable( feature = "atomic_from_mut" , issue = "76314" ) ]
346
+ pub fn from_mut ( v : & mut bool ) -> & Self {
347
+ // SAFETY: the mutable reference guarantees unique ownership, and
348
+ // alignment of both `bool` and `Self` is 1.
349
+ unsafe { & * ( v as * mut bool as * mut Self ) }
350
+ }
351
+
330
352
/// Consumes the atomic and returns the contained value.
331
353
///
332
354
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -820,6 +842,30 @@ impl<T> AtomicPtr<T> {
820
842
unsafe { & mut * self . p . get ( ) }
821
843
}
822
844
845
+ /// Get atomic access to a pointer.
846
+ ///
847
+ /// # Examples
848
+ ///
849
+ /// ```
850
+ /// #![feature(atomic_from_mut)]
851
+ /// use std::sync::atomic::{AtomicPtr, Ordering};
852
+ ///
853
+ /// let mut some_ptr = &mut 123 as *mut i32;
854
+ /// let a = AtomicPtr::from_mut(&mut some_ptr);
855
+ /// a.store(&mut 456, Ordering::Relaxed);
856
+ /// assert_eq!(unsafe { *some_ptr }, 456);
857
+ /// ```
858
+ #[ inline]
859
+ #[ unstable( feature = "atomic_from_mut" , issue = "76314" ) ]
860
+ pub fn from_mut ( v : & mut * mut T ) -> & Self {
861
+ let [ ] = [ ( ) ; align_of :: < AtomicPtr < ( ) > > ( ) - align_of :: < * mut ( ) > ( ) ] ;
862
+ // SAFETY:
863
+ // - the mutable reference guarantees unique ownership.
864
+ // - the alignment of `*mut T` and `Self` is the same on all platforms
865
+ // supported by rust, as verified above.
866
+ unsafe { & * ( v as * mut * mut T as * mut Self ) }
867
+ }
868
+
823
869
/// Consumes the atomic and returns the contained value.
824
870
///
825
871
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -1104,6 +1150,13 @@ impl<T> From<*mut T> for AtomicPtr<T> {
1104
1150
}
1105
1151
}
1106
1152
1153
+ #[ allow( unused_macros) ] // This macro ends up being unused on some architectures.
1154
+ macro_rules! if_not_8_bit {
1155
+ ( u8 , $( $tt: tt) * ) => { "" } ;
1156
+ ( i8 , $( $tt: tt) * ) => { "" } ;
1157
+ ( $_: ident, $( $tt: tt) * ) => { $( $tt) * } ;
1158
+ }
1159
+
1107
1160
#[ cfg( target_has_atomic_load_store = "8" ) ]
1108
1161
macro_rules! atomic_int {
1109
1162
( $cfg_cas: meta,
@@ -1115,7 +1168,8 @@ macro_rules! atomic_int {
1115
1168
$stable_nand: meta,
1116
1169
$const_stable: meta,
1117
1170
$stable_init_const: meta,
1118
- $s_int_type: expr, $int_ref: expr,
1171
+ $( from_mut: cfg( $from_mut_cfg: meta) , ) ?
1172
+ $s_int_type: literal, $int_ref: expr,
1119
1173
$extra_feature: expr,
1120
1174
$min_fn: ident, $max_fn: ident,
1121
1175
$align: expr,
@@ -1226,6 +1280,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
1226
1280
}
1227
1281
}
1228
1282
1283
+ doc_comment! {
1284
+ concat!( "Get atomic access to a `&mut " , stringify!( $int_type) , "`.
1285
+
1286
+ " ,
1287
+ if_not_8_bit! {
1288
+ $int_type,
1289
+ concat!(
1290
+ "**Note:** This function is only available on targets where `" ,
1291
+ stringify!( $int_type) , "` has an alignment of " , $align, " bytes."
1292
+ )
1293
+ } ,
1294
+ "
1295
+
1296
+ # Examples
1297
+
1298
+ ```
1299
+ #![feature(atomic_from_mut)]
1300
+ " , $extra_feature, "use std::sync::atomic::{" , stringify!( $atomic_type) , ", Ordering};
1301
+
1302
+ let mut some_int = 123;
1303
+ let a = " , stringify!( $atomic_type) , "::from_mut(&mut some_int);
1304
+ a.store(100, Ordering::Relaxed);
1305
+ assert_eq!(some_int, 100);
1306
+ ```
1307
+ " ) ,
1308
+ #[ inline]
1309
+ $( #[ cfg( $from_mut_cfg) ] ) ?
1310
+ #[ unstable( feature = "atomic_from_mut" , issue = "76314" ) ]
1311
+ pub fn from_mut( v: & mut $int_type) -> & Self {
1312
+ let [ ] = [ ( ) ; align_of:: <Self >( ) - align_of:: <$int_type>( ) ] ;
1313
+ // SAFETY:
1314
+ // - the mutable reference guarantees unique ownership.
1315
+ // - the alignment of `$int_type` and `Self` is the
1316
+ // same on all platforms enabled by `$from_mut_cfg`
1317
+ // as verified above.
1318
+ unsafe { & * ( v as * mut $int_type as * mut Self ) }
1319
+ }
1320
+ }
1321
+
1229
1322
doc_comment! {
1230
1323
concat!( "Consumes the atomic and returns the contained value.
1231
1324
@@ -1984,6 +2077,7 @@ atomic_int! {
1984
2077
stable( feature = "integer_atomics_stable" , since = "1.34.0" ) ,
1985
2078
rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
1986
2079
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2080
+ from_mut: cfg( not( target_arch = "x86" ) ) ,
1987
2081
"i64" , "../../../std/primitive.i64.html" ,
1988
2082
"" ,
1989
2083
atomic_min, atomic_max,
@@ -2002,6 +2096,7 @@ atomic_int! {
2002
2096
stable( feature = "integer_atomics_stable" , since = "1.34.0" ) ,
2003
2097
rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
2004
2098
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2099
+ from_mut: cfg( not( target_arch = "x86" ) ) ,
2005
2100
"u64" , "../../../std/primitive.u64.html" ,
2006
2101
"" ,
2007
2102
atomic_umin, atomic_umax,
@@ -2020,6 +2115,7 @@ atomic_int! {
2020
2115
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2021
2116
rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
2022
2117
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2118
+ from_mut: cfg( not( target_arch = "x86_64" ) ) ,
2023
2119
"i128" , "../../../std/primitive.i128.html" ,
2024
2120
"#![feature(integer_atomics)]\n \n " ,
2025
2121
atomic_min, atomic_max,
@@ -2038,6 +2134,7 @@ atomic_int! {
2038
2134
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2039
2135
rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
2040
2136
unstable( feature = "integer_atomics" , issue = "32976" ) ,
2137
+ from_mut: cfg( not( target_arch = "x86_64" ) ) ,
2041
2138
"u128" , "../../../std/primitive.u128.html" ,
2042
2139
"#![feature(integer_atomics)]\n \n " ,
2043
2140
atomic_umin, atomic_umax,
0 commit comments