15
15
use unstable:: intrinsics;
16
16
use cast;
17
17
use option:: { Option , Some , None } ;
18
+ use libc:: c_void;
19
+ use ops:: Drop ;
18
20
19
21
pub struct AtomicFlag {
20
22
priv v: int
@@ -36,6 +38,10 @@ pub struct AtomicPtr<T> {
36
38
priv p: * mut T
37
39
}
38
40
41
+ pub struct AtomicOption < T > {
42
+ priv p: * mut c_void
43
+ }
44
+
39
45
pub enum Ordering {
40
46
Release ,
41
47
Acquire ,
@@ -53,7 +59,7 @@ impl AtomicFlag {
53
59
* Clears the atomic flag
54
60
*/
55
61
#[ inline( always) ]
56
- fn clear ( & mut self , order : Ordering ) {
62
+ fn clear ( & mut self , order : Ordering ) {
57
63
unsafe { atomic_store ( & mut self . v , 0 , order) }
58
64
}
59
65
@@ -62,37 +68,37 @@ impl AtomicFlag {
62
68
* Sets the flag if it was previously unset, returns the previous value of the
63
69
* flag.
64
70
*/
65
- fn test_and_set ( & mut self , order : Ordering ) -> bool {
71
+ fn test_and_set ( & mut self , order : Ordering ) -> bool {
66
72
unsafe { atomic_compare_and_swap ( & mut self . v , 0 , 1 , order) > 0 }
67
73
}
68
74
}
69
75
70
76
impl AtomicBool {
71
- fn new ( v : bool ) -> AtomicBool {
77
+ fn new ( v : bool ) -> AtomicBool {
72
78
AtomicBool { v : if v { 1 } else { 0 } }
73
79
}
74
80
75
81
#[ inline( always) ]
76
- fn load ( & self , order : Ordering ) -> bool {
82
+ fn load ( & self , order : Ordering ) -> bool {
77
83
unsafe { atomic_load ( & self . v , order) > 0 }
78
84
}
79
85
80
86
#[ inline( always) ]
81
- fn store ( & mut self , val : bool , order : Ordering ) {
87
+ fn store ( & mut self , val : bool , order : Ordering ) {
82
88
let val = if val { 1 } else { 0 } ;
83
89
84
90
unsafe { atomic_store ( & mut self . v , val, order) ; }
85
91
}
86
92
87
93
#[ inline( always) ]
88
- fn swap ( & mut self , val : bool , order : Ordering ) -> bool {
94
+ fn swap ( & mut self , val : bool , order : Ordering ) -> bool {
89
95
let val = if val { 1 } else { 0 } ;
90
96
91
97
unsafe { atomic_swap ( & mut self . v , val, order) > 0 }
92
98
}
93
99
94
100
#[ 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 {
96
102
let old = if old { 1 } else { 0 } ;
97
103
let new = if new { 1 } else { 0 } ;
98
104
@@ -101,100 +107,153 @@ impl AtomicBool {
101
107
}
102
108
103
109
impl AtomicInt {
104
- fn new ( v : int ) -> AtomicInt {
110
+ fn new ( v : int ) -> AtomicInt {
105
111
AtomicInt { v : v }
106
112
}
107
113
108
114
#[ inline( always) ]
109
- fn load ( & self , order : Ordering ) -> int {
115
+ fn load ( & self , order : Ordering ) -> int {
110
116
unsafe { atomic_load ( & self . v , order) }
111
117
}
112
118
113
119
#[ inline( always) ]
114
- fn store ( & mut self , val : int , order : Ordering ) {
120
+ fn store ( & mut self , val : int , order : Ordering ) {
115
121
unsafe { atomic_store ( & mut self . v , val, order) ; }
116
122
}
117
123
118
124
#[ inline( always) ]
119
- fn swap ( & mut self , val : int , order : Ordering ) -> int {
125
+ fn swap ( & mut self , val : int , order : Ordering ) -> int {
120
126
unsafe { atomic_swap ( & mut self . v , val, order) }
121
127
}
122
128
123
129
#[ 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 {
125
131
unsafe { atomic_compare_and_swap ( & mut self . v , old, new, order) }
126
132
}
127
133
128
134
#[ inline( always) ]
129
- fn fetch_add ( & mut self , val : int , order : Ordering ) -> int {
135
+ fn fetch_add ( & mut self , val : int , order : Ordering ) -> int {
130
136
unsafe { atomic_add ( & mut self . v , val, order) }
131
137
}
132
138
133
139
#[ inline( always) ]
134
- fn fetch_sub ( & mut self , val : int , order : Ordering ) -> int {
140
+ fn fetch_sub ( & mut self , val : int , order : Ordering ) -> int {
135
141
unsafe { atomic_sub ( & mut self . v , val, order) }
136
142
}
137
143
}
138
144
139
145
impl AtomicUint {
140
- fn new ( v : uint ) -> AtomicUint {
146
+ fn new ( v : uint ) -> AtomicUint {
141
147
AtomicUint { v : v }
142
148
}
143
149
144
150
#[ inline( always) ]
145
- fn load ( & self , order : Ordering ) -> uint {
151
+ fn load ( & self , order : Ordering ) -> uint {
146
152
unsafe { atomic_load ( & self . v , order) }
147
153
}
148
154
149
155
#[ inline( always) ]
150
- fn store ( & mut self , val : uint , order : Ordering ) {
156
+ fn store ( & mut self , val : uint , order : Ordering ) {
151
157
unsafe { atomic_store ( & mut self . v , val, order) ; }
152
158
}
153
159
154
160
#[ inline( always) ]
155
- fn swap ( & mut self , val : uint , order : Ordering ) -> uint {
161
+ fn swap ( & mut self , val : uint , order : Ordering ) -> uint {
156
162
unsafe { atomic_swap ( & mut self . v , val, order) }
157
163
}
158
164
159
165
#[ 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 {
161
167
unsafe { atomic_compare_and_swap ( & mut self . v , old, new, order) }
162
168
}
163
169
164
170
#[ inline( always) ]
165
- fn fetch_add ( & mut self , val : uint , order : Ordering ) -> uint {
171
+ fn fetch_add ( & mut self , val : uint , order : Ordering ) -> uint {
166
172
unsafe { atomic_add ( & mut self . v , val, order) }
167
173
}
168
174
169
175
#[ inline( always) ]
170
- fn fetch_sub ( & mut self , val : uint , order : Ordering ) -> uint {
176
+ fn fetch_sub ( & mut self , val : uint , order : Ordering ) -> uint {
171
177
unsafe { atomic_sub ( & mut self . v , val, order) }
172
178
}
173
179
}
174
180
175
181
impl < T > AtomicPtr < T > {
176
- fn new ( p : * mut T ) -> AtomicPtr < T > {
182
+ fn new ( p : * mut T ) -> AtomicPtr < T > {
177
183
AtomicPtr { p : p }
178
184
}
179
185
180
186
#[ inline( always) ]
181
- fn load ( & self , order : Ordering ) -> * mut T {
187
+ fn load ( & self , order : Ordering ) -> * mut T {
182
188
unsafe { atomic_load ( & self . p , order) }
183
189
}
184
190
185
191
#[ inline( always) ]
186
- fn store ( & mut self , ptr : * mut T , order : Ordering ) {
192
+ fn store ( & mut self , ptr : * mut T , order : Ordering ) {
187
193
unsafe { atomic_store ( & mut self . p , ptr, order) ; }
188
194
}
189
195
190
196
#[ 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 {
192
198
unsafe { atomic_swap ( & mut self . p , ptr, order) }
193
199
}
194
200
195
201
#[ 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
+ }
198
257
}
199
258
}
200
259
@@ -284,8 +343,8 @@ mod test {
284
343
}
285
344
286
345
#[ test]
287
- fn pointer_swap ( ) {
288
- let mut p = AtomicPtr :: new ( ~1 ) ;
346
+ fn option_swap ( ) {
347
+ let mut p = AtomicOption :: new ( ~1 ) ;
289
348
let a = ~2 ;
290
349
291
350
let b = p. swap ( a, SeqCst ) ;
@@ -295,15 +354,14 @@ mod test {
295
354
}
296
355
297
356
#[ test]
298
- fn pointer_take ( ) {
299
- let mut p = AtomicPtr :: new ( ~1 ) ;
357
+ fn option_take ( ) {
358
+ let mut p = AtomicOption :: new ( ~1 ) ;
300
359
301
360
assert_eq ! ( p. take( SeqCst ) , Some ( ~1 ) ) ;
302
361
assert_eq ! ( p. take( SeqCst ) , None ) ;
303
- assert ! ( p. taken( SeqCst ) ) ;
304
362
305
363
let p2 = ~2 ;
306
- p. give ( p2, SeqCst ) ;
364
+ p. swap ( p2, SeqCst ) ;
307
365
308
366
assert_eq ! ( p. take( SeqCst ) , Some ( ~2 ) ) ;
309
367
}
0 commit comments