Skip to content

Commit 413ada3

Browse files
authored
Auto merge of rust-lang#35719 - Amanieu:atomic_access, r=alexcrichton
Implement RFC 1649 cc rust-lang#35603 rust-lang/rfcs#1649 r? @alexcrichton
2 parents 499484f + ee1fc38 commit 413ada3

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

src/libcore/sync/atomic.rs

+142
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ use default::Default;
9090
use fmt;
9191

9292
/// A boolean type which can be safely shared between threads.
93+
///
94+
/// This type has the same in-memory representation as a `bool`.
9395
#[cfg(target_has_atomic = "8")]
9496
#[stable(feature = "rust1", since = "1.0.0")]
9597
pub struct AtomicBool {
@@ -110,6 +112,8 @@ impl Default for AtomicBool {
110112
unsafe impl Sync for AtomicBool {}
111113

112114
/// A raw pointer type which can be safely shared between threads.
115+
///
116+
/// This type has the same in-memory representation as a `*mut T`.
113117
#[cfg(target_has_atomic = "ptr")]
114118
#[stable(feature = "rust1", since = "1.0.0")]
115119
pub struct AtomicPtr<T> {
@@ -191,6 +195,48 @@ impl AtomicBool {
191195
AtomicBool { v: UnsafeCell::new(v as u8) }
192196
}
193197

198+
/// Returns a mutable reference to the underlying `bool`.
199+
///
200+
/// This is safe because the mutable reference guarantees that no other threads are
201+
/// concurrently accessing the atomic data.
202+
///
203+
/// # Examples
204+
///
205+
/// ```
206+
/// #![feature(atomic_access)]
207+
/// use std::sync::atomic::{AtomicBool, Ordering};
208+
///
209+
/// let mut some_bool = AtomicBool::new(true);
210+
/// assert_eq!(*some_bool.get_mut(), true);
211+
/// *some_bool.get_mut() = false;
212+
/// assert_eq!(some_bool.load(Ordering::SeqCst), false);
213+
/// ```
214+
#[inline]
215+
#[unstable(feature = "atomic_access", issue = "35603")]
216+
pub fn get_mut(&mut self) -> &mut bool {
217+
unsafe { &mut *(self.v.get() as *mut bool) }
218+
}
219+
220+
/// Consumes the atomic and returns the contained value.
221+
///
222+
/// This is safe because passing `self` by value guarantees that no other threads are
223+
/// concurrently accessing the atomic data.
224+
///
225+
/// # Examples
226+
///
227+
/// ```
228+
/// #![feature(atomic_access)]
229+
/// use std::sync::atomic::AtomicBool;
230+
///
231+
/// let some_bool = AtomicBool::new(true);
232+
/// assert_eq!(some_bool.into_inner(), true);
233+
/// ```
234+
#[inline]
235+
#[unstable(feature = "atomic_access", issue = "35603")]
236+
pub fn into_inner(self) -> bool {
237+
unsafe { self.v.into_inner() != 0 }
238+
}
239+
194240
/// Loads a value from the bool.
195241
///
196242
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
@@ -528,6 +574,47 @@ impl<T> AtomicPtr<T> {
528574
AtomicPtr { p: UnsafeCell::new(p) }
529575
}
530576

577+
/// Returns a mutable reference to the underlying pointer.
578+
///
579+
/// This is safe because the mutable reference guarantees that no other threads are
580+
/// concurrently accessing the atomic data.
581+
///
582+
/// # Examples
583+
///
584+
/// ```
585+
/// #![feature(atomic_access)]
586+
/// use std::sync::atomic::{AtomicPtr, Ordering};
587+
///
588+
/// let mut atomic_ptr = AtomicPtr::new(&mut 10);
589+
/// *atomic_ptr.get_mut() = &mut 5;
590+
/// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
591+
/// ```
592+
#[inline]
593+
#[unstable(feature = "atomic_access", issue = "35603")]
594+
pub fn get_mut(&mut self) -> &mut *mut T {
595+
unsafe { &mut *self.p.get() }
596+
}
597+
598+
/// Consumes the atomic and returns the contained value.
599+
///
600+
/// This is safe because passing `self` by value guarantees that no other threads are
601+
/// concurrently accessing the atomic data.
602+
///
603+
/// # Examples
604+
///
605+
/// ```
606+
/// #![feature(atomic_access)]
607+
/// use std::sync::atomic::AtomicPtr;
608+
///
609+
/// let atomic_ptr = AtomicPtr::new(&mut 5);
610+
/// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
611+
/// ```
612+
#[inline]
613+
#[unstable(feature = "atomic_access", issue = "35603")]
614+
pub fn into_inner(self) -> *mut T {
615+
unsafe { self.p.into_inner() }
616+
}
617+
531618
/// Loads a value from the pointer.
532619
///
533620
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
@@ -730,8 +817,11 @@ macro_rules! atomic_int {
730817
($stable:meta,
731818
$stable_cxchg:meta,
732819
$stable_debug:meta,
820+
$stable_access:meta,
733821
$int_type:ident $atomic_type:ident $atomic_init:ident) => {
734822
/// An integer type which can be safely shared between threads.
823+
///
824+
/// This type has the same in-memory representation as the underlying integer type.
735825
#[$stable]
736826
pub struct $atomic_type {
737827
v: UnsafeCell<$int_type>,
@@ -777,6 +867,48 @@ macro_rules! atomic_int {
777867
$atomic_type {v: UnsafeCell::new(v)}
778868
}
779869

870+
/// Returns a mutable reference to the underlying integer.
871+
///
872+
/// This is safe because the mutable reference guarantees that no other threads are
873+
/// concurrently accessing the atomic data.
874+
///
875+
/// # Examples
876+
///
877+
/// ```
878+
/// #![feature(atomic_access)]
879+
/// use std::sync::atomic::{AtomicIsize, Ordering};
880+
///
881+
/// let mut some_isize = AtomicIsize::new(10);
882+
/// assert_eq!(*some_isize.get_mut(), 10);
883+
/// *some_isize.get_mut() = 5;
884+
/// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
885+
/// ```
886+
#[inline]
887+
#[$stable_access]
888+
pub fn get_mut(&mut self) -> &mut $int_type {
889+
unsafe { &mut *self.v.get() }
890+
}
891+
892+
/// Consumes the atomic and returns the contained value.
893+
///
894+
/// This is safe because passing `self` by value guarantees that no other threads are
895+
/// concurrently accessing the atomic data.
896+
///
897+
/// # Examples
898+
///
899+
/// ```
900+
/// #![feature(atomic_access)]
901+
/// use std::sync::atomic::AtomicIsize;
902+
///
903+
/// let some_isize = AtomicIsize::new(5);
904+
/// assert_eq!(some_isize.into_inner(), 5);
905+
/// ```
906+
#[inline]
907+
#[$stable_access]
908+
pub fn into_inner(self) -> $int_type {
909+
unsafe { self.v.into_inner() }
910+
}
911+
780912
/// Loads a value from the atomic integer.
781913
///
782914
/// `load` takes an `Ordering` argument which describes the memory ordering of this
@@ -1057,69 +1189,79 @@ atomic_int! {
10571189
unstable(feature = "integer_atomics", issue = "32976"),
10581190
unstable(feature = "integer_atomics", issue = "32976"),
10591191
unstable(feature = "integer_atomics", issue = "32976"),
1192+
unstable(feature = "integer_atomics", issue = "32976"),
10601193
i8 AtomicI8 ATOMIC_I8_INIT
10611194
}
10621195
#[cfg(target_has_atomic = "8")]
10631196
atomic_int! {
10641197
unstable(feature = "integer_atomics", issue = "32976"),
10651198
unstable(feature = "integer_atomics", issue = "32976"),
10661199
unstable(feature = "integer_atomics", issue = "32976"),
1200+
unstable(feature = "integer_atomics", issue = "32976"),
10671201
u8 AtomicU8 ATOMIC_U8_INIT
10681202
}
10691203
#[cfg(target_has_atomic = "16")]
10701204
atomic_int! {
10711205
unstable(feature = "integer_atomics", issue = "32976"),
10721206
unstable(feature = "integer_atomics", issue = "32976"),
10731207
unstable(feature = "integer_atomics", issue = "32976"),
1208+
unstable(feature = "integer_atomics", issue = "32976"),
10741209
i16 AtomicI16 ATOMIC_I16_INIT
10751210
}
10761211
#[cfg(target_has_atomic = "16")]
10771212
atomic_int! {
10781213
unstable(feature = "integer_atomics", issue = "32976"),
10791214
unstable(feature = "integer_atomics", issue = "32976"),
10801215
unstable(feature = "integer_atomics", issue = "32976"),
1216+
unstable(feature = "integer_atomics", issue = "32976"),
10811217
u16 AtomicU16 ATOMIC_U16_INIT
10821218
}
10831219
#[cfg(target_has_atomic = "32")]
10841220
atomic_int! {
10851221
unstable(feature = "integer_atomics", issue = "32976"),
10861222
unstable(feature = "integer_atomics", issue = "32976"),
10871223
unstable(feature = "integer_atomics", issue = "32976"),
1224+
unstable(feature = "integer_atomics", issue = "32976"),
10881225
i32 AtomicI32 ATOMIC_I32_INIT
10891226
}
10901227
#[cfg(target_has_atomic = "32")]
10911228
atomic_int! {
10921229
unstable(feature = "integer_atomics", issue = "32976"),
10931230
unstable(feature = "integer_atomics", issue = "32976"),
10941231
unstable(feature = "integer_atomics", issue = "32976"),
1232+
unstable(feature = "integer_atomics", issue = "32976"),
10951233
u32 AtomicU32 ATOMIC_U32_INIT
10961234
}
10971235
#[cfg(target_has_atomic = "64")]
10981236
atomic_int! {
10991237
unstable(feature = "integer_atomics", issue = "32976"),
11001238
unstable(feature = "integer_atomics", issue = "32976"),
11011239
unstable(feature = "integer_atomics", issue = "32976"),
1240+
unstable(feature = "integer_atomics", issue = "32976"),
11021241
i64 AtomicI64 ATOMIC_I64_INIT
11031242
}
11041243
#[cfg(target_has_atomic = "64")]
11051244
atomic_int! {
11061245
unstable(feature = "integer_atomics", issue = "32976"),
11071246
unstable(feature = "integer_atomics", issue = "32976"),
11081247
unstable(feature = "integer_atomics", issue = "32976"),
1248+
unstable(feature = "integer_atomics", issue = "32976"),
11091249
u64 AtomicU64 ATOMIC_U64_INIT
11101250
}
11111251
#[cfg(target_has_atomic = "ptr")]
11121252
atomic_int!{
11131253
stable(feature = "rust1", since = "1.0.0"),
11141254
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
11151255
stable(feature = "atomic_debug", since = "1.3.0"),
1256+
unstable(feature = "atomic_access", issue = "35603"),
11161257
isize AtomicIsize ATOMIC_ISIZE_INIT
11171258
}
11181259
#[cfg(target_has_atomic = "ptr")]
11191260
atomic_int!{
11201261
stable(feature = "rust1", since = "1.0.0"),
11211262
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
11221263
stable(feature = "atomic_debug", since = "1.3.0"),
1264+
unstable(feature = "atomic_access", issue = "35603"),
11231265
usize AtomicUsize ATOMIC_USIZE_INIT
11241266
}
11251267

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(atomic_access)]
12+
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
13+
use std::sync::atomic::Ordering::*;
14+
15+
static mut ATOMIC: AtomicBool = ATOMIC_BOOL_INIT;
16+
17+
fn main() {
18+
unsafe {
19+
assert_eq!(*ATOMIC.get_mut(), false);
20+
ATOMIC.store(true, SeqCst);
21+
assert_eq!(*ATOMIC.get_mut(), true);
22+
ATOMIC.fetch_or(false, SeqCst);
23+
assert_eq!(*ATOMIC.get_mut(), true);
24+
ATOMIC.fetch_and(false, SeqCst);
25+
assert_eq!(*ATOMIC.get_mut(), false);
26+
ATOMIC.fetch_nand(true, SeqCst);
27+
assert_eq!(*ATOMIC.get_mut(), true);
28+
ATOMIC.fetch_xor(true, SeqCst);
29+
assert_eq!(*ATOMIC.get_mut(), false);
30+
}
31+
}

0 commit comments

Comments
 (0)