Skip to content

Commit 30b471b

Browse files
author
James Miller
committed
Add AtomicOption type
1 parent 008e6e5 commit 30b471b

File tree

1 file changed

+91
-33
lines changed

1 file changed

+91
-33
lines changed

src/libstd/unstable/atomics.rs

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use unstable::intrinsics;
1616
use cast;
1717
use option::{Option,Some,None};
18+
use libc::c_void;
19+
use ops::Drop;
1820

1921
pub struct AtomicFlag {
2022
priv v: int
@@ -36,6 +38,10 @@ pub struct AtomicPtr<T> {
3638
priv p: *mut T
3739
}
3840

41+
pub struct AtomicOption<T> {
42+
priv p: *mut c_void
43+
}
44+
3945
pub enum Ordering {
4046
Release,
4147
Acquire,
@@ -53,7 +59,7 @@ impl AtomicFlag {
5359
* Clears the atomic flag
5460
*/
5561
#[inline(always)]
56-
fn clear(&mut self, order:Ordering) {
62+
fn clear(&mut self, order: Ordering) {
5763
unsafe {atomic_store(&mut self.v, 0, order)}
5864
}
5965

@@ -62,37 +68,37 @@ impl AtomicFlag {
6268
* Sets the flag if it was previously unset, returns the previous value of the
6369
* flag.
6470
*/
65-
fn test_and_set(&mut self, order:Ordering) -> bool {
71+
fn test_and_set(&mut self, order: Ordering) -> bool {
6672
unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0}
6773
}
6874
}
6975

7076
impl AtomicBool {
71-
fn new(v:bool) -> AtomicBool {
77+
fn new(v: bool) -> AtomicBool {
7278
AtomicBool { v: if v { 1 } else { 0 } }
7379
}
7480

7581
#[inline(always)]
76-
fn load(&self, order:Ordering) -> bool {
82+
fn load(&self, order: Ordering) -> bool {
7783
unsafe { atomic_load(&self.v, order) > 0 }
7884
}
7985

8086
#[inline(always)]
81-
fn store(&mut self, val:bool, order:Ordering) {
87+
fn store(&mut self, val: bool, order: Ordering) {
8288
let val = if val { 1 } else { 0 };
8389

8490
unsafe { atomic_store(&mut self.v, val, order); }
8591
}
8692

8793
#[inline(always)]
88-
fn swap(&mut self, val:bool, order:Ordering) -> bool {
94+
fn swap(&mut self, val: bool, order: Ordering) -> bool {
8995
let val = if val { 1 } else { 0 };
9096

9197
unsafe { atomic_swap(&mut self.v, val, order) > 0}
9298
}
9399

94100
#[inline(always)]
95-
fn compare_and_swap(&mut self, old: bool, new: bool, order:Ordering) -> bool {
101+
fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool {
96102
let old = if old { 1 } else { 0 };
97103
let new = if new { 1 } else { 0 };
98104

@@ -101,100 +107,153 @@ impl AtomicBool {
101107
}
102108

103109
impl AtomicInt {
104-
fn new(v:int) -> AtomicInt {
110+
fn new(v: int) -> AtomicInt {
105111
AtomicInt { v:v }
106112
}
107113

108114
#[inline(always)]
109-
fn load(&self, order:Ordering) -> int {
115+
fn load(&self, order: Ordering) -> int {
110116
unsafe { atomic_load(&self.v, order) }
111117
}
112118

113119
#[inline(always)]
114-
fn store(&mut self, val:int, order:Ordering) {
120+
fn store(&mut self, val: int, order: Ordering) {
115121
unsafe { atomic_store(&mut self.v, val, order); }
116122
}
117123

118124
#[inline(always)]
119-
fn swap(&mut self, val:int, order:Ordering) -> int {
125+
fn swap(&mut self, val: int, order: Ordering) -> int {
120126
unsafe { atomic_swap(&mut self.v, val, order) }
121127
}
122128

123129
#[inline(always)]
124-
fn compare_and_swap(&mut self, old: int, new: int, order:Ordering) -> int {
130+
fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int {
125131
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
126132
}
127133

128134
#[inline(always)]
129-
fn fetch_add(&mut self, val:int, order:Ordering) -> int {
135+
fn fetch_add(&mut self, val: int, order: Ordering) -> int {
130136
unsafe { atomic_add(&mut self.v, val, order) }
131137
}
132138

133139
#[inline(always)]
134-
fn fetch_sub(&mut self, val:int, order:Ordering) -> int {
140+
fn fetch_sub(&mut self, val: int, order: Ordering) -> int {
135141
unsafe { atomic_sub(&mut self.v, val, order) }
136142
}
137143
}
138144

139145
impl AtomicUint {
140-
fn new(v:uint) -> AtomicUint {
146+
fn new(v: uint) -> AtomicUint {
141147
AtomicUint { v:v }
142148
}
143149

144150
#[inline(always)]
145-
fn load(&self, order:Ordering) -> uint {
151+
fn load(&self, order: Ordering) -> uint {
146152
unsafe { atomic_load(&self.v, order) }
147153
}
148154

149155
#[inline(always)]
150-
fn store(&mut self, val:uint, order:Ordering) {
156+
fn store(&mut self, val: uint, order: Ordering) {
151157
unsafe { atomic_store(&mut self.v, val, order); }
152158
}
153159

154160
#[inline(always)]
155-
fn swap(&mut self, val:uint, order:Ordering) -> uint {
161+
fn swap(&mut self, val: uint, order: Ordering) -> uint {
156162
unsafe { atomic_swap(&mut self.v, val, order) }
157163
}
158164

159165
#[inline(always)]
160-
fn compare_and_swap(&mut self, old: uint, new: uint, order:Ordering) -> uint {
166+
fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint {
161167
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
162168
}
163169

164170
#[inline(always)]
165-
fn fetch_add(&mut self, val:uint, order:Ordering) -> uint {
171+
fn fetch_add(&mut self, val: uint, order: Ordering) -> uint {
166172
unsafe { atomic_add(&mut self.v, val, order) }
167173
}
168174

169175
#[inline(always)]
170-
fn fetch_sub(&mut self, val:uint, order:Ordering) -> uint {
176+
fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint {
171177
unsafe { atomic_sub(&mut self.v, val, order) }
172178
}
173179
}
174180

175181
impl<T> AtomicPtr<T> {
176-
fn new(p:*mut T) -> AtomicPtr<T> {
182+
fn new(p: *mut T) -> AtomicPtr<T> {
177183
AtomicPtr { p:p }
178184
}
179185

180186
#[inline(always)]
181-
fn load(&self, order:Ordering) -> *mut T {
187+
fn load(&self, order: Ordering) -> *mut T {
182188
unsafe { atomic_load(&self.p, order) }
183189
}
184190

185191
#[inline(always)]
186-
fn store(&mut self, ptr:*mut T, order:Ordering) {
192+
fn store(&mut self, ptr: *mut T, order: Ordering) {
187193
unsafe { atomic_store(&mut self.p, ptr, order); }
188194
}
189195

190196
#[inline(always)]
191-
fn swap(&mut self, ptr:*mut T, order:Ordering) -> *mut T {
197+
fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T {
192198
unsafe { atomic_swap(&mut self.p, ptr, order) }
193199
}
194200

195201
#[inline(always)]
196-
fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order:Ordering) -> *mut T {
197-
unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
202+
fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
203+
unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) }
204+
}
205+
}
206+
207+
impl<T> AtomicOption<T> {
208+
fn new(p: ~T) -> AtomicOption<T> {
209+
unsafe {
210+
AtomicOption {
211+
p: cast::transmute(p)
212+
}
213+
}
214+
}
215+
216+
fn empty() -> AtomicOption<T> {
217+
unsafe {
218+
AtomicOption {
219+
p: cast::transmute(0)
220+
}
221+
}
222+
}
223+
224+
#[inline(always)]
225+
fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> {
226+
unsafe {
227+
let val = cast::transmute(val);
228+
229+
let p = atomic_swap(&mut self.p, val, order);
230+
let pv : &uint = cast::transmute(&p);
231+
232+
if *pv == 0 {
233+
None
234+
} else {
235+
Some(cast::transmute(p))
236+
}
237+
}
238+
}
239+
240+
#[inline(always)]
241+
fn take(&mut self, order: Ordering) -> Option<~T> {
242+
unsafe {
243+
self.swap(cast::transmute(0), order)
244+
}
245+
}
246+
}
247+
248+
#[unsafe_destructor]
249+
impl<T> Drop for AtomicOption<T> {
250+
fn finalize(&self) {
251+
// This will ensure that the contained data is
252+
// destroyed, unless it's null.
253+
unsafe {
254+
let this : &mut AtomicOption<T> = cast::transmute(self);
255+
let _ = this.take(SeqCst);
256+
}
198257
}
199258
}
200259

@@ -284,8 +343,8 @@ mod test {
284343
}
285344

286345
#[test]
287-
fn pointer_swap() {
288-
let mut p = AtomicPtr::new(~1);
346+
fn option_swap() {
347+
let mut p = AtomicOption::new(~1);
289348
let a = ~2;
290349

291350
let b = p.swap(a, SeqCst);
@@ -295,15 +354,14 @@ mod test {
295354
}
296355

297356
#[test]
298-
fn pointer_take() {
299-
let mut p = AtomicPtr::new(~1);
357+
fn option_take() {
358+
let mut p = AtomicOption::new(~1);
300359

301360
assert_eq!(p.take(SeqCst), Some(~1));
302361
assert_eq!(p.take(SeqCst), None);
303-
assert!(p.taken(SeqCst));
304362

305363
let p2 = ~2;
306-
p.give(p2, SeqCst);
364+
p.swap(p2, SeqCst);
307365

308366
assert_eq!(p.take(SeqCst), Some(~2));
309367
}

0 commit comments

Comments
 (0)