Skip to content

Commit d3d2a27

Browse files
committed
Add Atomic*::from_mut_slice
1 parent d981633 commit d3d2a27

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

library/core/src/sync/atomic.rs

+94
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,32 @@ impl AtomicBool {
340340
unsafe { &mut *(v as *mut bool as *mut Self) }
341341
}
342342

343+
/// Get atomic access to a `&mut [bool]` slice.
344+
///
345+
/// # Examples
346+
///
347+
/// ```
348+
/// #![feature(atomic_from_mut, scoped_threads)]
349+
/// use std::sync::atomic::{AtomicBool, Ordering};
350+
///
351+
/// let mut some_bools = [false; 10];
352+
/// let a = &*AtomicBool::from_mut_slice(&mut some_bools);
353+
/// std::thread::scope(|s| {
354+
/// for i in 0..a.len() {
355+
/// s.spawn(move |_| a[i].store(true, Ordering::Relaxed));
356+
/// }
357+
/// });
358+
/// assert_eq!(some_bools, [true; 10]);
359+
/// ```
360+
#[inline]
361+
#[cfg(target_has_atomic_equal_alignment = "8")]
362+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
363+
pub fn from_mut_slice(v: &mut [bool]) -> &mut [Self] {
364+
// SAFETY: the mutable reference guarantees unique ownership, and
365+
// alignment of both `bool` and `Self` is 1.
366+
unsafe { &mut *(v as *mut [bool] as *mut [Self]) }
367+
}
368+
343369
/// Consumes the atomic and returns the contained value.
344370
///
345371
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -945,6 +971,42 @@ impl<T> AtomicPtr<T> {
945971
unsafe { &mut *(v as *mut *mut T as *mut Self) }
946972
}
947973

974+
/// Get atomic access to a slice of pointers.
975+
///
976+
/// # Examples
977+
///
978+
/// ```
979+
/// #![feature(atomic_from_mut, scoped_threads)]
980+
/// use std::ptr::null_mut;
981+
/// use std::sync::atomic::{AtomicPtr, Ordering};
982+
///
983+
/// let mut some_ptrs = [null_mut::<String>(); 10];
984+
/// let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs);
985+
/// std::thread::scope(|s| {
986+
/// for i in 0..a.len() {
987+
/// s.spawn(move |_| {
988+
/// let name = Box::new(format!("thread{i}"));
989+
/// a[i].store(Box::into_raw(name), Ordering::Relaxed);
990+
/// });
991+
/// }
992+
/// });
993+
/// for p in some_ptrs {
994+
/// assert!(!p.is_null());
995+
/// let name = unsafe { Box::from_raw(p) };
996+
/// println!("Hello, {name}!");
997+
/// }
998+
/// ```
999+
#[inline]
1000+
#[cfg(target_has_atomic_equal_alignment = "ptr")]
1001+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
1002+
pub fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] {
1003+
// SAFETY:
1004+
// - the mutable reference guarantees unique ownership.
1005+
// - the alignment of `*mut T` and `Self` is the same on all platforms
1006+
// supported by rust, as verified above.
1007+
unsafe { &mut *(v as *mut [*mut T] as *mut [Self]) }
1008+
}
1009+
9481010
/// Consumes the atomic and returns the contained value.
9491011
///
9501012
/// This is safe because passing `self` by value guarantees that no other threads are
@@ -1459,6 +1521,38 @@ macro_rules! atomic_int {
14591521
unsafe { &mut *(v as *mut $int_type as *mut Self) }
14601522
}
14611523

1524+
#[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")]
1525+
///
1526+
/// # Examples
1527+
///
1528+
/// ```
1529+
/// #![feature(atomic_from_mut, scoped_threads)]
1530+
#[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
1531+
///
1532+
/// let mut some_ints = [0; 10];
1533+
#[doc = concat!("let a = &*", stringify!($atomic_type), "::from_mut_slice(&mut some_ints);")]
1534+
/// std::thread::scope(|s| {
1535+
/// for i in 0..a.len() {
1536+
/// s.spawn(move |_| a[i].store(i as _, Ordering::Relaxed));
1537+
/// }
1538+
/// });
1539+
/// for (i, n) in some_ints.into_iter().enumerate() {
1540+
/// assert_eq!(i, n as usize);
1541+
/// }
1542+
/// ```
1543+
#[inline]
1544+
#[$cfg_align]
1545+
#[unstable(feature = "atomic_from_mut", issue = "76314")]
1546+
pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] {
1547+
use crate::mem::align_of;
1548+
let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
1549+
// SAFETY:
1550+
// - the mutable reference guarantees unique ownership.
1551+
// - the alignment of `$int_type` and `Self` is the
1552+
// same, as promised by $cfg_align and verified above.
1553+
unsafe { &mut *(v as *mut [$int_type] as *mut [Self]) }
1554+
}
1555+
14621556
/// Consumes the atomic and returns the contained value.
14631557
///
14641558
/// This is safe because passing `self` by value guarantees that no other threads are

0 commit comments

Comments
 (0)