Skip to content

Commit

Permalink
Add Atomic*::from_ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
WaffleLapkin committed Feb 27, 2023
1 parent 58136ff commit 4a2c555
Showing 1 changed file with 135 additions and 0 deletions.
135 changes: 135 additions & 0 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,50 @@ impl AtomicBool {
AtomicBool { v: UnsafeCell::new(v as u8) }
}

/// Creates a new `AtomicBool` from a pointer.
///
/// # Examples
///
/// ```
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
/// use std::sync::atomic::{self, AtomicBool};
/// use std::mem::align_of;
///
/// // Get a pointer to an allocated value
/// let ptr: *mut bool = Box::into_raw(Box::new(false));
///
/// assert!(ptr.is_aligned_to(align_of::<AtomicBool>()));
///
/// {
/// // Create an atomic view of the allocated value
/// let atomic = unsafe { AtomicBool::from_ptr(ptr) };
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(true, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, true);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
///
/// [valid]: crate::ptr#safety
#[unstable(feature = "atomic_from_ptr", issue = "none")]
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "none")]
pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
}

/// Returns a mutable reference to the underlying [`bool`].
///
/// This is safe because the mutable reference guarantees that no other threads are
Expand Down Expand Up @@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> {
AtomicPtr { p: UnsafeCell::new(p) }
}

/// Creates a new `AtomicPtr` from a pointer.
///
/// # Examples
///
/// ```
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
/// use std::sync::atomic::{self, AtomicPtr};
/// use std::mem::align_of;
///
/// // Get a pointer to an allocated value
/// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
///
/// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>()));
///
/// {
/// // Create an atomic view of the allocated value
/// let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert!(!unsafe { *ptr }.is_null());
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
///
/// [valid]: crate::ptr#safety
#[unstable(feature = "atomic_from_ptr", issue = "none")]
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "none")]
pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
}

/// Returns a mutable reference to the underlying pointer.
///
/// This is safe because the mutable reference guarantees that no other threads are
Expand Down Expand Up @@ -1958,6 +2046,53 @@ macro_rules! atomic_int {
Self {v: UnsafeCell::new(v)}
}

/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
/// ```
/// #![feature(atomic_from_ptr, pointer_is_aligned)]
#[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
/// use std::mem::align_of;
///
/// // Get a pointer to an allocated value
#[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
///
#[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")]
///
/// {
/// // Create an atomic view of the allocated value
// SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
#[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
#[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
///
/// [valid]: crate::ptr#safety
#[unstable(feature = "atomic_from_ptr", issue = "none")]
#[rustc_const_unstable(feature = "atomic_from_ptr", issue = "none")]
pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
}


/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
Expand Down

0 comments on commit 4a2c555

Please # to comment.