10
10
11
11
/*!
12
12
* 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.
13
19
*/
14
20
15
21
use unstable:: intrinsics;
16
22
use cast;
17
23
use option:: { Option , Some , None } ;
24
+ use libc:: c_void;
25
+ use ops:: Drop ;
18
26
27
+ /**
28
+ * A simple atomic flag, that can be set and cleared. The most basic atomic type.
29
+ */
19
30
pub struct AtomicFlag {
20
- priv v: int
31
+ priv v: int
21
32
}
22
33
34
+ /**
35
+ * An atomic boolean type.
36
+ */
23
37
pub struct AtomicBool {
24
- priv v: uint
38
+ priv v: uint
25
39
}
26
40
41
+ /**
42
+ * A signed atomic integer type, supporting basic atomic aritmetic operations
43
+ */
27
44
pub struct AtomicInt {
28
- priv v: int
45
+ priv v: int
29
46
}
30
47
48
+ /**
49
+ * An unsigned atomic integer type, supporting basic atomic aritmetic operations
50
+ */
31
51
pub struct AtomicUint {
32
- priv v: uint
52
+ priv v: uint
33
53
}
34
54
55
+ /**
56
+ * An unsafe atomic pointer. Only supports basic atomic operations
57
+ */
35
58
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
37
67
}
38
68
39
69
pub enum Ordering {
@@ -53,46 +83,46 @@ impl AtomicFlag {
53
83
* Clears the atomic flag
54
84
*/
55
85
#[ inline( always) ]
56
- fn clear ( & mut self , order : Ordering ) {
86
+ fn clear ( & mut self , order : Ordering ) {
57
87
unsafe { atomic_store ( & mut self . v , 0 , order) }
58
88
}
59
89
60
- #[ inline( always) ]
61
90
/**
62
91
* Sets the flag if it was previously unset, returns the previous value of the
63
92
* flag.
64
93
*/
65
- fn test_and_set ( & mut self , order : Ordering ) -> bool {
94
+ #[ inline( always) ]
95
+ fn test_and_set ( & mut self , order : Ordering ) -> bool {
66
96
unsafe { atomic_compare_and_swap ( & mut self . v , 0 , 1 , order) > 0 }
67
97
}
68
98
}
69
99
70
100
impl AtomicBool {
71
- fn new ( v : bool ) -> AtomicBool {
101
+ fn new ( v : bool ) -> AtomicBool {
72
102
AtomicBool { v : if v { 1 } else { 0 } }
73
103
}
74
104
75
105
#[ inline( always) ]
76
- fn load ( & self , order : Ordering ) -> bool {
106
+ fn load ( & self , order : Ordering ) -> bool {
77
107
unsafe { atomic_load ( & self . v , order) > 0 }
78
108
}
79
109
80
110
#[ inline( always) ]
81
- fn store ( & mut self , val : bool , order : Ordering ) {
111
+ fn store ( & mut self , val : bool , order : Ordering ) {
82
112
let val = if val { 1 } else { 0 } ;
83
113
84
114
unsafe { atomic_store ( & mut self . v , val, order) ; }
85
115
}
86
116
87
117
#[ inline( always) ]
88
- fn swap ( & mut self , val : bool , order : Ordering ) -> bool {
118
+ fn swap ( & mut self , val : bool , order : Ordering ) -> bool {
89
119
let val = if val { 1 } else { 0 } ;
90
120
91
121
unsafe { atomic_swap ( & mut self . v , val, order) > 0 }
92
122
}
93
123
94
124
#[ 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 {
96
126
let old = if old { 1 } else { 0 } ;
97
127
let new = if new { 1 } else { 0 } ;
98
128
@@ -101,131 +131,152 @@ impl AtomicBool {
101
131
}
102
132
103
133
impl AtomicInt {
104
- fn new ( v : int ) -> AtomicInt {
134
+ fn new ( v : int ) -> AtomicInt {
105
135
AtomicInt { v : v }
106
136
}
107
137
108
138
#[ inline( always) ]
109
- fn load ( & self , order : Ordering ) -> int {
139
+ fn load ( & self , order : Ordering ) -> int {
110
140
unsafe { atomic_load ( & self . v , order) }
111
141
}
112
142
113
143
#[ inline( always) ]
114
- fn store ( & mut self , val : int , order : Ordering ) {
144
+ fn store ( & mut self , val : int , order : Ordering ) {
115
145
unsafe { atomic_store ( & mut self . v , val, order) ; }
116
146
}
117
147
118
148
#[ inline( always) ]
119
- fn swap ( & mut self , val : int , order : Ordering ) -> int {
149
+ fn swap ( & mut self , val : int , order : Ordering ) -> int {
120
150
unsafe { atomic_swap ( & mut self . v , val, order) }
121
151
}
122
152
123
153
#[ 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 {
125
155
unsafe { atomic_compare_and_swap ( & mut self . v , old, new, order) }
126
156
}
127
157
128
158
#[ inline( always) ]
129
- fn fetch_add ( & mut self , val : int , order : Ordering ) -> int {
159
+ fn fetch_add ( & mut self , val : int , order : Ordering ) -> int {
130
160
unsafe { atomic_add ( & mut self . v , val, order) }
131
161
}
132
162
133
163
#[ inline( always) ]
134
- fn fetch_sub ( & mut self , val : int , order : Ordering ) -> int {
164
+ fn fetch_sub ( & mut self , val : int , order : Ordering ) -> int {
135
165
unsafe { atomic_sub ( & mut self . v , val, order) }
136
166
}
137
167
}
138
168
139
169
impl AtomicUint {
140
- fn new ( v : uint ) -> AtomicUint {
170
+ fn new ( v : uint ) -> AtomicUint {
141
171
AtomicUint { v : v }
142
172
}
143
173
144
174
#[ inline( always) ]
145
- fn load ( & self , order : Ordering ) -> uint {
175
+ fn load ( & self , order : Ordering ) -> uint {
146
176
unsafe { atomic_load ( & self . v , order) }
147
177
}
148
178
149
179
#[ inline( always) ]
150
- fn store ( & mut self , val : uint , order : Ordering ) {
180
+ fn store ( & mut self , val : uint , order : Ordering ) {
151
181
unsafe { atomic_store ( & mut self . v , val, order) ; }
152
182
}
153
183
154
184
#[ inline( always) ]
155
- fn swap ( & mut self , val : uint , order : Ordering ) -> uint {
185
+ fn swap ( & mut self , val : uint , order : Ordering ) -> uint {
156
186
unsafe { atomic_swap ( & mut self . v , val, order) }
157
187
}
158
188
159
189
#[ 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 {
161
191
unsafe { atomic_compare_and_swap ( & mut self . v , old, new, order) }
162
192
}
163
193
164
194
#[ inline( always) ]
165
- fn fetch_add ( & mut self , val : uint , order : Ordering ) -> uint {
195
+ fn fetch_add ( & mut self , val : uint , order : Ordering ) -> uint {
166
196
unsafe { atomic_add ( & mut self . v , val, order) }
167
197
}
168
198
169
199
#[ inline( always) ]
170
- fn fetch_sub ( & mut self , val : uint , order : Ordering ) -> uint {
200
+ fn fetch_sub ( & mut self , val : uint , order : Ordering ) -> uint {
171
201
unsafe { atomic_sub ( & mut self . v , val, order) }
172
202
}
173
203
}
174
204
175
205
impl < T > AtomicPtr < T > {
176
- fn new ( p : ~ T ) -> AtomicPtr < T > {
206
+ fn new ( p : * mut T ) -> AtomicPtr < T > {
177
207
AtomicPtr { p : p }
178
208
}
179
209
180
- /**
181
- * Atomically swaps the stored pointer with the one given.
182
- *
183
- * Returns None if the pointer stored has been taken
184
- */
185
210
#[ 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 > {
187
233
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) ;
189
254
let pv : & uint = cast:: transmute ( & p) ;
190
255
191
256
if * pv == 0 {
192
257
None
193
258
} else {
194
- Some ( p )
259
+ Some ( cast :: transmute ( p ) )
195
260
}
196
261
}
197
262
}
198
263
199
- /**
200
- * Atomically takes the stored pointer out.
201
- *
202
- * Returns None if it was already taken.
203
- */
204
264
#[ 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
+ }
216
269
}
270
+ }
217
271
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.
222
277
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 ) ;
229
280
}
230
281
}
231
282
}
@@ -316,8 +367,8 @@ mod test {
316
367
}
317
368
318
369
#[ test]
319
- fn pointer_swap ( ) {
320
- let mut p = AtomicPtr :: new ( ~1 ) ;
370
+ fn option_swap ( ) {
371
+ let mut p = AtomicOption :: new ( ~1 ) ;
321
372
let a = ~2 ;
322
373
323
374
let b = p. swap ( a, SeqCst ) ;
@@ -327,15 +378,14 @@ mod test {
327
378
}
328
379
329
380
#[ test]
330
- fn pointer_take ( ) {
331
- let mut p = AtomicPtr :: new ( ~1 ) ;
381
+ fn option_take ( ) {
382
+ let mut p = AtomicOption :: new ( ~1 ) ;
332
383
333
384
assert_eq ! ( p. take( SeqCst ) , Some ( ~1 ) ) ;
334
385
assert_eq ! ( p. take( SeqCst ) , None ) ;
335
- assert ! ( p. taken( SeqCst ) ) ;
336
386
337
387
let p2 = ~2 ;
338
- p. give ( p2, SeqCst ) ;
388
+ p. swap ( p2, SeqCst ) ;
339
389
340
390
assert_eq ! ( p. take( SeqCst ) , Some ( ~2 ) ) ;
341
391
}
0 commit comments