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
1521use unstable:: intrinsics;
1622use cast;
1723use 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+ */
1930pub struct AtomicFlag {
20- priv v: int
31+ priv v: int
2132}
2233
34+ /**
35+ * An atomic boolean type.
36+ */
2337pub 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+ */
2744pub 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+ */
3151pub struct AtomicUint {
32- priv v: uint
52+ priv v: uint
3353}
3454
55+ /**
56+ * An unsafe atomic pointer. Only supports basic atomic operations
57+ */
3558pub 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
3969pub 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
70100impl 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
103133impl 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
139169impl 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
175205impl < 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