Skip to content

Commit 715e934

Browse files
committed
Auto merge of #74532 - fusion-engineering-forks:atomic-from-mut, r=KodrAus
Add Atomic*::from_mut. The atomic equivalent of [`Cell::from_mut`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.from_mut).
2 parents 255ceeb + 9914c3b commit 715e934

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

library/core/src/sync/atomic.rs

+98-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ use self::Ordering::*;
110110
use crate::cell::UnsafeCell;
111111
use crate::fmt;
112112
use crate::intrinsics;
113+
use crate::mem::align_of;
113114

114115
use 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")]
11081161
macro_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

Comments
 (0)