@@ -110,6 +110,7 @@ use self::Ordering::*;
110110use crate :: cell:: UnsafeCell ;
111111use crate :: fmt;
112112use crate :: intrinsics;
113+ use crate :: mem:: align_of;
113114
114115use crate :: hint:: spin_loop;
115116
@@ -327,6 +328,27 @@ impl AtomicBool {
327328 unsafe { & mut * ( self . v . get ( ) as * mut bool ) }
328329 }
329330
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+
330352 /// Consumes the atomic and returns the contained value.
331353 ///
332354 /// This is safe because passing `self` by value guarantees that no other threads are
@@ -820,6 +842,30 @@ impl<T> AtomicPtr<T> {
820842 unsafe { & mut * self . p . get ( ) }
821843 }
822844
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+
823869 /// Consumes the atomic and returns the contained value.
824870 ///
825871 /// 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> {
11041150 }
11051151}
11061152
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+
11071160#[ cfg( target_has_atomic_load_store = "8" ) ]
11081161macro_rules! atomic_int {
11091162 ( $cfg_cas: meta,
@@ -1115,7 +1168,8 @@ macro_rules! atomic_int {
11151168 $stable_nand: meta,
11161169 $const_stable: meta,
11171170 $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,
11191173 $extra_feature: expr,
11201174 $min_fn: ident, $max_fn: ident,
11211175 $align: expr,
@@ -1226,6 +1280,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
12261280 }
12271281 }
12281282
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+
12291322 doc_comment! {
12301323 concat!( "Consumes the atomic and returns the contained value.
12311324
@@ -1984,6 +2077,7 @@ atomic_int! {
19842077 stable( feature = "integer_atomics_stable" , since = "1.34.0" ) ,
19852078 rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
19862079 unstable( feature = "integer_atomics" , issue = "32976" ) ,
2080+ from_mut: cfg( not( target_arch = "x86" ) ) ,
19872081 "i64" , "../../../std/primitive.i64.html" ,
19882082 "" ,
19892083 atomic_min, atomic_max,
@@ -2002,6 +2096,7 @@ atomic_int! {
20022096 stable( feature = "integer_atomics_stable" , since = "1.34.0" ) ,
20032097 rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
20042098 unstable( feature = "integer_atomics" , issue = "32976" ) ,
2099+ from_mut: cfg( not( target_arch = "x86" ) ) ,
20052100 "u64" , "../../../std/primitive.u64.html" ,
20062101 "" ,
20072102 atomic_umin, atomic_umax,
@@ -2020,6 +2115,7 @@ atomic_int! {
20202115 unstable( feature = "integer_atomics" , issue = "32976" ) ,
20212116 rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
20222117 unstable( feature = "integer_atomics" , issue = "32976" ) ,
2118+ from_mut: cfg( not( target_arch = "x86_64" ) ) ,
20232119 "i128" , "../../../std/primitive.i128.html" ,
20242120 "#![feature(integer_atomics)]\n \n " ,
20252121 atomic_min, atomic_max,
@@ -2038,6 +2134,7 @@ atomic_int! {
20382134 unstable( feature = "integer_atomics" , issue = "32976" ) ,
20392135 rustc_const_stable( feature = "const_integer_atomics" , since = "1.34.0" ) ,
20402136 unstable( feature = "integer_atomics" , issue = "32976" ) ,
2137+ from_mut: cfg( not( target_arch = "x86_64" ) ) ,
20412138 "u128" , "../../../std/primitive.u128.html" ,
20422139 "#![feature(integer_atomics)]\n \n " ,
20432140 atomic_umin, atomic_umax,
0 commit comments