From 330b7f7359f27efee391be2edc1fa896146535f0 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 16 Aug 2016 16:58:20 +0100 Subject: [PATCH] Implement RFC 1649 --- src/libcore/sync/atomic.rs | 142 +++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 2a7a0b6232936..14ce4f56fd22c 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -90,6 +90,8 @@ use default::Default; use fmt; /// A boolean type which can be safely shared between threads. +/// +/// This type has the same in-memory representation as a `bool`. #[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicBool { @@ -110,6 +112,8 @@ impl Default for AtomicBool { unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. +/// +/// This type has the same in-memory representation as a `*mut T`. #[cfg(target_has_atomic = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicPtr { @@ -191,6 +195,48 @@ impl AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } + /// Returns a mutable reference to the underlying `bool`. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bool = AtomicBool::new(true); + /// assert_eq!(*some_bool.get_mut(), true); + /// *some_bool.get_mut() = false; + /// assert_eq!(some_bool.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[unstable(feature = "atomic_access", issue = "35603")] + pub fn get_mut(&mut self) -> &mut bool { + unsafe { &mut *(self.v.get() as *mut bool) } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::AtomicBool; + /// + /// let some_bool = AtomicBool::new(true); + /// assert_eq!(some_bool.into_inner(), true); + /// ``` + #[inline] + #[unstable(feature = "atomic_access", issue = "35603")] + pub fn into_inner(self) -> bool { + unsafe { self.v.into_inner() != 0 } + } + /// Loads a value from the bool. /// /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. @@ -528,6 +574,47 @@ impl AtomicPtr { AtomicPtr { p: UnsafeCell::new(p) } } + /// Returns a mutable reference to the underlying pointer. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut atomic_ptr = AtomicPtr::new(&mut 10); + /// *atomic_ptr.get_mut() = &mut 5; + /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5); + /// ``` + #[inline] + #[unstable(feature = "atomic_access", issue = "35603")] + pub fn get_mut(&mut self) -> &mut *mut T { + unsafe { &mut *self.p.get() } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::AtomicPtr; + /// + /// let atomic_ptr = AtomicPtr::new(&mut 5); + /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); + /// ``` + #[inline] + #[unstable(feature = "atomic_access", issue = "35603")] + pub fn into_inner(self) -> *mut T { + unsafe { self.p.into_inner() } + } + /// Loads a value from the pointer. /// /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. @@ -730,8 +817,11 @@ macro_rules! atomic_int { ($stable:meta, $stable_cxchg:meta, $stable_debug:meta, + $stable_access:meta, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. + /// + /// This type has the same in-memory representation as the underlying integer type. #[$stable] pub struct $atomic_type { v: UnsafeCell<$int_type>, @@ -777,6 +867,48 @@ macro_rules! atomic_int { $atomic_type {v: UnsafeCell::new(v)} } + /// Returns a mutable reference to the underlying integer. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::{AtomicIsize, Ordering}; + /// + /// let mut some_isize = AtomicIsize::new(10); + /// assert_eq!(*some_isize.get_mut(), 10); + /// *some_isize.get_mut() = 5; + /// assert_eq!(some_isize.load(Ordering::SeqCst), 5); + /// ``` + #[inline] + #[$stable_access] + pub fn get_mut(&mut self) -> &mut $int_type { + unsafe { &mut *self.v.get() } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_access)] + /// use std::sync::atomic::AtomicIsize; + /// + /// let some_isize = AtomicIsize::new(5); + /// assert_eq!(some_isize.into_inner(), 5); + /// ``` + #[inline] + #[$stable_access] + pub fn into_inner(self) -> $int_type { + unsafe { self.v.into_inner() } + } + /// Loads a value from the atomic integer. /// /// `load` takes an `Ordering` argument which describes the memory ordering of this @@ -1057,6 +1189,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1064,6 +1197,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1071,6 +1205,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1078,6 +1213,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1085,6 +1221,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1092,6 +1229,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1099,6 +1237,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1106,6 +1245,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + unstable(feature = "integer_atomics", issue = "32976"), u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1113,6 +1253,7 @@ atomic_int!{ stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), + unstable(feature = "atomic_access", issue = "35603"), isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1120,6 +1261,7 @@ atomic_int!{ stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), + unstable(feature = "atomic_access", issue = "35603"), usize AtomicUsize ATOMIC_USIZE_INIT }