Skip to content

Commit c8c60f0

Browse files
committed
auto merge of #6740 : Aatch/rust/atomic-types, r=brson
This is a follow up to #6732. Makes everything a little more sound. r? @brson
2 parents e3d0c1e + df1814b commit c8c60f0

File tree

1 file changed

+118
-68
lines changed

1 file changed

+118
-68
lines changed

src/libstd/unstable/atomics.rs

+118-68
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,60 @@
1010

1111
/*!
1212
* Atomic types
13+
*
14+
* Basic atomic types supporting atomic operations. Each method takes an `Ordering` which
15+
* represents the strength of the memory barrier for that operation. These orderings are the same
16+
* as C++11 atomic orderings [http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync]
17+
*
18+
* All atomic types are a single word in size.
1319
*/
1420

1521
use unstable::intrinsics;
1622
use cast;
1723
use option::{Option,Some,None};
24+
use libc::c_void;
25+
use ops::Drop;
1826

27+
/**
28+
* A simple atomic flag, that can be set and cleared. The most basic atomic type.
29+
*/
1930
pub struct AtomicFlag {
20-
priv v:int
31+
priv v: int
2132
}
2233

34+
/**
35+
* An atomic boolean type.
36+
*/
2337
pub struct AtomicBool {
24-
priv v:uint
38+
priv v: uint
2539
}
2640

41+
/**
42+
* A signed atomic integer type, supporting basic atomic aritmetic operations
43+
*/
2744
pub struct AtomicInt {
28-
priv v:int
45+
priv v: int
2946
}
3047

48+
/**
49+
* An unsigned atomic integer type, supporting basic atomic aritmetic operations
50+
*/
3151
pub struct AtomicUint {
32-
priv v:uint
52+
priv v: uint
3353
}
3454

55+
/**
56+
* An unsafe atomic pointer. Only supports basic atomic operations
57+
*/
3558
pub struct AtomicPtr<T> {
36-
priv p:~T
59+
priv p: *mut T
60+
}
61+
62+
/**
63+
* An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
64+
*/
65+
pub struct AtomicOption<T> {
66+
priv p: *mut c_void
3767
}
3868

3969
pub enum Ordering {
@@ -53,46 +83,46 @@ impl AtomicFlag {
5383
* Clears the atomic flag
5484
*/
5585
#[inline(always)]
56-
fn clear(&mut self, order:Ordering) {
86+
fn clear(&mut self, order: Ordering) {
5787
unsafe {atomic_store(&mut self.v, 0, order)}
5888
}
5989

60-
#[inline(always)]
6190
/**
6291
* Sets the flag if it was previously unset, returns the previous value of the
6392
* flag.
6493
*/
65-
fn test_and_set(&mut self, order:Ordering) -> bool {
94+
#[inline(always)]
95+
fn test_and_set(&mut self, order: Ordering) -> bool {
6696
unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0}
6797
}
6898
}
6999

70100
impl AtomicBool {
71-
fn new(v:bool) -> AtomicBool {
101+
fn new(v: bool) -> AtomicBool {
72102
AtomicBool { v: if v { 1 } else { 0 } }
73103
}
74104

75105
#[inline(always)]
76-
fn load(&self, order:Ordering) -> bool {
106+
fn load(&self, order: Ordering) -> bool {
77107
unsafe { atomic_load(&self.v, order) > 0 }
78108
}
79109

80110
#[inline(always)]
81-
fn store(&mut self, val:bool, order:Ordering) {
111+
fn store(&mut self, val: bool, order: Ordering) {
82112
let val = if val { 1 } else { 0 };
83113

84114
unsafe { atomic_store(&mut self.v, val, order); }
85115
}
86116

87117
#[inline(always)]
88-
fn swap(&mut self, val:bool, order:Ordering) -> bool {
118+
fn swap(&mut self, val: bool, order: Ordering) -> bool {
89119
let val = if val { 1 } else { 0 };
90120

91121
unsafe { atomic_swap(&mut self.v, val, order) > 0}
92122
}
93123

94124
#[inline(always)]
95-
fn compare_and_swap(&mut self, old: bool, new: bool, order:Ordering) -> bool {
125+
fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool {
96126
let old = if old { 1 } else { 0 };
97127
let new = if new { 1 } else { 0 };
98128

@@ -101,131 +131,152 @@ impl AtomicBool {
101131
}
102132

103133
impl AtomicInt {
104-
fn new(v:int) -> AtomicInt {
134+
fn new(v: int) -> AtomicInt {
105135
AtomicInt { v:v }
106136
}
107137

108138
#[inline(always)]
109-
fn load(&self, order:Ordering) -> int {
139+
fn load(&self, order: Ordering) -> int {
110140
unsafe { atomic_load(&self.v, order) }
111141
}
112142

113143
#[inline(always)]
114-
fn store(&mut self, val:int, order:Ordering) {
144+
fn store(&mut self, val: int, order: Ordering) {
115145
unsafe { atomic_store(&mut self.v, val, order); }
116146
}
117147

118148
#[inline(always)]
119-
fn swap(&mut self, val:int, order:Ordering) -> int {
149+
fn swap(&mut self, val: int, order: Ordering) -> int {
120150
unsafe { atomic_swap(&mut self.v, val, order) }
121151
}
122152

123153
#[inline(always)]
124-
fn compare_and_swap(&mut self, old: int, new: int, order:Ordering) -> int {
154+
fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int {
125155
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
126156
}
127157

128158
#[inline(always)]
129-
fn fetch_add(&mut self, val:int, order:Ordering) -> int {
159+
fn fetch_add(&mut self, val: int, order: Ordering) -> int {
130160
unsafe { atomic_add(&mut self.v, val, order) }
131161
}
132162

133163
#[inline(always)]
134-
fn fetch_sub(&mut self, val:int, order:Ordering) -> int {
164+
fn fetch_sub(&mut self, val: int, order: Ordering) -> int {
135165
unsafe { atomic_sub(&mut self.v, val, order) }
136166
}
137167
}
138168

139169
impl AtomicUint {
140-
fn new(v:uint) -> AtomicUint {
170+
fn new(v: uint) -> AtomicUint {
141171
AtomicUint { v:v }
142172
}
143173

144174
#[inline(always)]
145-
fn load(&self, order:Ordering) -> uint {
175+
fn load(&self, order: Ordering) -> uint {
146176
unsafe { atomic_load(&self.v, order) }
147177
}
148178

149179
#[inline(always)]
150-
fn store(&mut self, val:uint, order:Ordering) {
180+
fn store(&mut self, val: uint, order: Ordering) {
151181
unsafe { atomic_store(&mut self.v, val, order); }
152182
}
153183

154184
#[inline(always)]
155-
fn swap(&mut self, val:uint, order:Ordering) -> uint {
185+
fn swap(&mut self, val: uint, order: Ordering) -> uint {
156186
unsafe { atomic_swap(&mut self.v, val, order) }
157187
}
158188

159189
#[inline(always)]
160-
fn compare_and_swap(&mut self, old: uint, new: uint, order:Ordering) -> uint {
190+
fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint {
161191
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
162192
}
163193

164194
#[inline(always)]
165-
fn fetch_add(&mut self, val:uint, order:Ordering) -> uint {
195+
fn fetch_add(&mut self, val: uint, order: Ordering) -> uint {
166196
unsafe { atomic_add(&mut self.v, val, order) }
167197
}
168198

169199
#[inline(always)]
170-
fn fetch_sub(&mut self, val:uint, order:Ordering) -> uint {
200+
fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint {
171201
unsafe { atomic_sub(&mut self.v, val, order) }
172202
}
173203
}
174204

175205
impl<T> AtomicPtr<T> {
176-
fn new(p:~T) -> AtomicPtr<T> {
206+
fn new(p: *mut T) -> AtomicPtr<T> {
177207
AtomicPtr { p:p }
178208
}
179209

180-
/**
181-
* Atomically swaps the stored pointer with the one given.
182-
*
183-
* Returns None if the pointer stored has been taken
184-
*/
185210
#[inline(always)]
186-
fn swap(&mut self, ptr:~T, order:Ordering) -> Option<~T> {
211+
fn load(&self, order: Ordering) -> *mut T {
212+
unsafe { atomic_load(&self.p, order) }
213+
}
214+
215+
#[inline(always)]
216+
fn store(&mut self, ptr: *mut T, order: Ordering) {
217+
unsafe { atomic_store(&mut self.p, ptr, order); }
218+
}
219+
220+
#[inline(always)]
221+
fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T {
222+
unsafe { atomic_swap(&mut self.p, ptr, order) }
223+
}
224+
225+
#[inline(always)]
226+
fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
227+
unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) }
228+
}
229+
}
230+
231+
impl<T> AtomicOption<T> {
232+
fn new(p: ~T) -> AtomicOption<T> {
187233
unsafe {
188-
let p = atomic_swap(&mut self.p, ptr, order);
234+
AtomicOption {
235+
p: cast::transmute(p)
236+
}
237+
}
238+
}
239+
240+
fn empty() -> AtomicOption<T> {
241+
unsafe {
242+
AtomicOption {
243+
p: cast::transmute(0)
244+
}
245+
}
246+
}
247+
248+
#[inline(always)]
249+
fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> {
250+
unsafe {
251+
let val = cast::transmute(val);
252+
253+
let p = atomic_swap(&mut self.p, val, order);
189254
let pv : &uint = cast::transmute(&p);
190255

191256
if *pv == 0 {
192257
None
193258
} else {
194-
Some(p)
259+
Some(cast::transmute(p))
195260
}
196261
}
197262
}
198263

199-
/**
200-
* Atomically takes the stored pointer out.
201-
*
202-
* Returns None if it was already taken.
203-
*/
204264
#[inline(always)]
205-
fn take(&mut self, order:Ordering) -> Option<~T> {
206-
unsafe { self.swap(cast::transmute(0), order) }
207-
}
208-
209-
/**
210-
* Atomically stores the given pointer, this will overwrite
211-
* and previous value stored.
212-
*/
213-
#[inline(always)]
214-
fn give(&mut self, ptr:~T, order:Ordering) {
215-
let _ = self.swap(ptr, order);
265+
fn take(&mut self, order: Ordering) -> Option<~T> {
266+
unsafe {
267+
self.swap(cast::transmute(0), order)
268+
}
216269
}
270+
}
217271

218-
/**
219-
* Checks to see if the stored pointer has been taken.
220-
*/
221-
fn taken(&self, order:Ordering) -> bool {
272+
#[unsafe_destructor]
273+
impl<T> Drop for AtomicOption<T> {
274+
fn finalize(&self) {
275+
// This will ensure that the contained data is
276+
// destroyed, unless it's null.
222277
unsafe {
223-
let p : ~T = atomic_load(&self.p, order);
224-
225-
let pv : &uint = cast::transmute(&p);
226-
227-
cast::forget(p);
228-
*pv == 0
278+
let this : &mut AtomicOption<T> = cast::transmute(self);
279+
let _ = this.take(SeqCst);
229280
}
230281
}
231282
}
@@ -316,8 +367,8 @@ mod test {
316367
}
317368

318369
#[test]
319-
fn pointer_swap() {
320-
let mut p = AtomicPtr::new(~1);
370+
fn option_swap() {
371+
let mut p = AtomicOption::new(~1);
321372
let a = ~2;
322373

323374
let b = p.swap(a, SeqCst);
@@ -327,15 +378,14 @@ mod test {
327378
}
328379

329380
#[test]
330-
fn pointer_take() {
331-
let mut p = AtomicPtr::new(~1);
381+
fn option_take() {
382+
let mut p = AtomicOption::new(~1);
332383

333384
assert_eq!(p.take(SeqCst), Some(~1));
334385
assert_eq!(p.take(SeqCst), None);
335-
assert!(p.taken(SeqCst));
336386

337387
let p2 = ~2;
338-
p.give(p2, SeqCst);
388+
p.swap(p2, SeqCst);
339389

340390
assert_eq!(p.take(SeqCst), Some(~2));
341391
}

0 commit comments

Comments
 (0)