Skip to content

Commit

Permalink
Auto merge of rust-lang#35719 - Amanieu:atomic_access, r=alexcrichton
Browse files Browse the repository at this point in the history
  • Loading branch information
bors authored Aug 19, 2016
2 parents 499484f + ee1fc38 commit 413ada3
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
142 changes: 142 additions & 0 deletions src/libcore/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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<T> {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -528,6 +574,47 @@ impl<T> AtomicPtr<T> {
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.
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1057,69 +1189,79 @@ 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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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
}

Expand Down
31 changes: 31 additions & 0 deletions src/test/run-pass/atomic-access-bool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(atomic_access)]
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
use std::sync::atomic::Ordering::*;

static mut ATOMIC: AtomicBool = ATOMIC_BOOL_INIT;

fn main() {
unsafe {
assert_eq!(*ATOMIC.get_mut(), false);
ATOMIC.store(true, SeqCst);
assert_eq!(*ATOMIC.get_mut(), true);
ATOMIC.fetch_or(false, SeqCst);
assert_eq!(*ATOMIC.get_mut(), true);
ATOMIC.fetch_and(false, SeqCst);
assert_eq!(*ATOMIC.get_mut(), false);
ATOMIC.fetch_nand(true, SeqCst);
assert_eq!(*ATOMIC.get_mut(), true);
ATOMIC.fetch_xor(true, SeqCst);
assert_eq!(*ATOMIC.get_mut(), false);
}
}

0 comments on commit 413ada3

Please sign in to comment.