]> git.lizzy.rs Git - rust.git/blob - src/libcore/atomic.rs
Merge pull request #20510 from tshepang/patch-6
[rust.git] / src / libcore / atomic.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Atomic types
12 //!
13 //! Atomic types provide primitive shared-memory communication between
14 //! threads, and are the building blocks of other concurrent
15 //! types.
16 //!
17 //! This module defines atomic versions of a select number of primitive
18 //! types, including `AtomicBool`, `AtomicInt`, `AtomicUint`, and `AtomicOption`.
19 //! Atomic types present operations that, when used correctly, synchronize
20 //! updates between threads.
21 //!
22 //! Each method takes an `Ordering` which represents the strength of
23 //! the memory barrier for that operation. These orderings are the
24 //! same as [C++11 atomic orderings][1].
25 //!
26 //! [1]: http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
27 //!
28 //! Atomic variables are safe to share between threads (they implement `Sync`)
29 //! but they do not themselves provide the mechanism for sharing. The most
30 //! common way to share an atomic variable is to put it into an `Arc` (an
31 //! atomically-reference-counted shared pointer).
32 //!
33 //! Most atomic types may be stored in static variables, initialized using
34 //! the provided static initializers like `INIT_ATOMIC_BOOL`. Atomic statics
35 //! are often used for lazy global initialization.
36 //!
37 //!
38 //! # Examples
39 //!
40 //! A simple spinlock:
41 //!
42 //! ```
43 //! use std::sync::Arc;
44 //! use std::sync::atomic::{AtomicUint, Ordering};
45 //! use std::thread::Thread;
46 //!
47 //! fn main() {
48 //!     let spinlock = Arc::new(AtomicUint::new(1));
49 //!
50 //!     let spinlock_clone = spinlock.clone();
51 //!     Thread::spawn(move|| {
52 //!         spinlock_clone.store(0, Ordering::SeqCst);
53 //!     }).detach();
54 //!
55 //!     // Wait for the other task to release the lock
56 //!     while spinlock.load(Ordering::SeqCst) != 0 {}
57 //! }
58 //! ```
59 //!
60 //! Keep a global count of live tasks:
61 //!
62 //! ```
63 //! use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
64 //!
65 //! static GLOBAL_TASK_COUNT: AtomicUint = ATOMIC_UINT_INIT;
66 //!
67 //! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, Ordering::SeqCst);
68 //! println!("live tasks: {}", old_task_count + 1);
69 //! ```
70
71 #![stable]
72
73 use self::Ordering::*;
74
75 use kinds::Sync;
76
77 use intrinsics;
78 use cell::UnsafeCell;
79
80 /// A boolean type which can be safely shared between threads.
81 #[stable]
82 pub struct AtomicBool {
83     v: UnsafeCell<uint>,
84 }
85
86 unsafe impl Sync for AtomicBool {}
87
88 /// A signed integer type which can be safely shared between threads.
89 #[stable]
90 pub struct AtomicInt {
91     v: UnsafeCell<int>,
92 }
93
94 unsafe impl Sync for AtomicInt {}
95
96 /// An unsigned integer type which can be safely shared between threads.
97 #[stable]
98 pub struct AtomicUint {
99     v: UnsafeCell<uint>,
100 }
101
102 unsafe impl Sync for AtomicUint {}
103
104 /// A raw pointer type which can be safely shared between threads.
105 #[stable]
106 pub struct AtomicPtr<T> {
107     p: UnsafeCell<uint>,
108 }
109
110 unsafe impl<T> Sync for AtomicPtr<T> {}
111
112 /// Atomic memory orderings
113 ///
114 /// Memory orderings limit the ways that both the compiler and CPU may reorder
115 /// instructions around atomic operations. At its most restrictive,
116 /// "sequentially consistent" atomics allow neither reads nor writes
117 /// to be moved either before or after the atomic operation; on the other end
118 /// "relaxed" atomics allow all reorderings.
119 ///
120 /// Rust's memory orderings are [the same as
121 /// C++'s](http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync).
122 #[stable]
123 #[derive(Copy)]
124 pub enum Ordering {
125     /// No ordering constraints, only atomic operations.
126     #[stable]
127     Relaxed,
128     /// When coupled with a store, all previous writes become visible
129     /// to another thread that performs a load with `Acquire` ordering
130     /// on the same value.
131     #[stable]
132     Release,
133     /// When coupled with a load, all subsequent loads will see data
134     /// written before a store with `Release` ordering on the same value
135     /// in another thread.
136     #[stable]
137     Acquire,
138     /// When coupled with a load, uses `Acquire` ordering, and with a store
139     /// `Release` ordering.
140     #[stable]
141     AcqRel,
142     /// Like `AcqRel` with the additional guarantee that all threads see all
143     /// sequentially consistent operations in the same order.
144     #[stable]
145     SeqCst,
146 }
147
148 /// An `AtomicBool` initialized to `false`.
149 #[unstable = "may be renamed, pending conventions for static initalizers"]
150 pub const ATOMIC_BOOL_INIT: AtomicBool =
151         AtomicBool { v: UnsafeCell { value: 0 } };
152 /// An `AtomicInt` initialized to `0`.
153 #[unstable = "may be renamed, pending conventions for static initalizers"]
154 pub const ATOMIC_INT_INIT: AtomicInt =
155         AtomicInt { v: UnsafeCell { value: 0 } };
156 /// An `AtomicUint` initialized to `0`.
157 #[unstable = "may be renamed, pending conventions for static initalizers"]
158 pub const ATOMIC_UINT_INIT: AtomicUint =
159         AtomicUint { v: UnsafeCell { value: 0, } };
160
161 /// Deprecated
162 #[deprecated = "renamed to ATOMIC_BOOL_INIT"]
163 pub const INIT_ATOMIC_BOOL: AtomicBool = ATOMIC_BOOL_INIT;
164 /// Deprecated
165 #[deprecated = "renamed to ATOMIC_INT_INIT"]
166 pub const INIT_ATOMIC_INT: AtomicInt = ATOMIC_INT_INIT;
167 /// Deprecated
168 #[deprecated = "renamed to ATOMIC_UINT_INIT"]
169 pub const INIT_ATOMIC_UINT: AtomicUint = ATOMIC_UINT_INIT;
170
171 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
172 const UINT_TRUE: uint = -1;
173
174 impl AtomicBool {
175     /// Creates a new `AtomicBool`.
176     ///
177     /// # Examples
178     ///
179     /// ```
180     /// use std::sync::atomic::AtomicBool;
181     ///
182     /// let atomic_true  = AtomicBool::new(true);
183     /// let atomic_false = AtomicBool::new(false);
184     /// ```
185     #[inline]
186     #[stable]
187     pub fn new(v: bool) -> AtomicBool {
188         let val = if v { UINT_TRUE } else { 0 };
189         AtomicBool { v: UnsafeCell::new(val) }
190     }
191
192     /// Loads a value from the bool.
193     ///
194     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
195     ///
196     /// # Panics
197     ///
198     /// Panics if `order` is `Release` or `AcqRel`.
199     ///
200     /// # Examples
201     ///
202     /// ```
203     /// use std::sync::atomic::{AtomicBool, Ordering};
204     ///
205     /// let some_bool = AtomicBool::new(true);
206     ///
207     /// let value = some_bool.load(Ordering::Relaxed);
208     /// ```
209     #[inline]
210     #[stable]
211     pub fn load(&self, order: Ordering) -> bool {
212         unsafe { atomic_load(self.v.get() as *const uint, order) > 0 }
213     }
214
215     /// Stores a value into the bool.
216     ///
217     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
218     ///
219     /// # Examples
220     ///
221     /// ```
222     /// use std::sync::atomic::{AtomicBool, Ordering};
223     ///
224     /// let some_bool = AtomicBool::new(true);
225     ///
226     /// some_bool.store(false, Ordering::Relaxed);
227     /// ```
228     ///
229     /// # Panics
230     ///
231     /// Panics if `order` is `Acquire` or `AcqRel`.
232     #[inline]
233     #[stable]
234     pub fn store(&self, val: bool, order: Ordering) {
235         let val = if val { UINT_TRUE } else { 0 };
236
237         unsafe { atomic_store(self.v.get(), val, order); }
238     }
239
240     /// Stores a value into the bool, returning the old value.
241     ///
242     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
243     ///
244     /// # Examples
245     ///
246     /// ```
247     /// use std::sync::atomic::{AtomicBool, Ordering};
248     ///
249     /// let some_bool = AtomicBool::new(true);
250     ///
251     /// let value = some_bool.swap(false, Ordering::Relaxed);
252     /// ```
253     #[inline]
254     #[stable]
255     pub fn swap(&self, val: bool, order: Ordering) -> bool {
256         let val = if val { UINT_TRUE } else { 0 };
257
258         unsafe { atomic_swap(self.v.get(), val, order) > 0 }
259     }
260
261     /// Stores a value into the bool if the current value is the same as the expected value.
262     ///
263     /// If the return value is equal to `old` then the value was updated.
264     ///
265     /// `swap` also takes an `Ordering` argument which describes the memory ordering of this
266     /// operation.
267     ///
268     /// # Examples
269     ///
270     /// ```
271     /// use std::sync::atomic::{AtomicBool, Ordering};
272     ///
273     /// let some_bool = AtomicBool::new(true);
274     ///
275     /// let value = some_bool.store(false, Ordering::Relaxed);
276     /// ```
277     #[inline]
278     #[stable]
279     pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool {
280         let old = if old { UINT_TRUE } else { 0 };
281         let new = if new { UINT_TRUE } else { 0 };
282
283         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) > 0 }
284     }
285
286     /// Logical "and" with a boolean value.
287     ///
288     /// Performs a logical "and" operation on the current value and the argument `val`, and sets
289     /// the new value to the result.
290     ///
291     /// Returns the previous value.
292     ///
293     /// # Examples
294     ///
295     /// ```
296     /// use std::sync::atomic::{AtomicBool, Ordering};
297     ///
298     /// let foo = AtomicBool::new(true);
299     /// assert_eq!(true, foo.fetch_and(false, Ordering::SeqCst));
300     /// assert_eq!(false, foo.load(Ordering::SeqCst));
301     ///
302     /// let foo = AtomicBool::new(true);
303     /// assert_eq!(true, foo.fetch_and(true, Ordering::SeqCst));
304     /// assert_eq!(true, foo.load(Ordering::SeqCst));
305     ///
306     /// let foo = AtomicBool::new(false);
307     /// assert_eq!(false, foo.fetch_and(false, Ordering::SeqCst));
308     /// assert_eq!(false, foo.load(Ordering::SeqCst));
309     /// ```
310     #[inline]
311     #[stable]
312     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
313         let val = if val { UINT_TRUE } else { 0 };
314
315         unsafe { atomic_and(self.v.get(), val, order) > 0 }
316     }
317
318     /// Logical "nand" with a boolean value.
319     ///
320     /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
321     /// the new value to the result.
322     ///
323     /// Returns the previous value.
324     ///
325     /// # Examples
326     ///
327     /// ```
328     /// use std::sync::atomic::{AtomicBool, Ordering};
329     ///
330     /// let foo = AtomicBool::new(true);
331     /// assert_eq!(true, foo.fetch_nand(false, Ordering::SeqCst));
332     /// assert_eq!(true, foo.load(Ordering::SeqCst));
333     ///
334     /// let foo = AtomicBool::new(true);
335     /// assert_eq!(true, foo.fetch_nand(true, Ordering::SeqCst));
336     /// assert_eq!(0, foo.load(Ordering::SeqCst) as int);
337     /// assert_eq!(false, foo.load(Ordering::SeqCst));
338     ///
339     /// let foo = AtomicBool::new(false);
340     /// assert_eq!(false, foo.fetch_nand(false, Ordering::SeqCst));
341     /// assert_eq!(true, foo.load(Ordering::SeqCst));
342     /// ```
343     #[inline]
344     #[stable]
345     pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
346         let val = if val { UINT_TRUE } else { 0 };
347
348         unsafe { atomic_nand(self.v.get(), val, order) > 0 }
349     }
350
351     /// Logical "or" with a boolean value.
352     ///
353     /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
354     /// new value to the result.
355     ///
356     /// Returns the previous value.
357     ///
358     /// # Examples
359     ///
360     /// ```
361     /// use std::sync::atomic::{AtomicBool, Ordering};
362     ///
363     /// let foo = AtomicBool::new(true);
364     /// assert_eq!(true, foo.fetch_or(false, Ordering::SeqCst));
365     /// assert_eq!(true, foo.load(Ordering::SeqCst));
366     ///
367     /// let foo = AtomicBool::new(true);
368     /// assert_eq!(true, foo.fetch_or(true, Ordering::SeqCst));
369     /// assert_eq!(true, foo.load(Ordering::SeqCst));
370     ///
371     /// let foo = AtomicBool::new(false);
372     /// assert_eq!(false, foo.fetch_or(false, Ordering::SeqCst));
373     /// assert_eq!(false, foo.load(Ordering::SeqCst));
374     /// ```
375     #[inline]
376     #[stable]
377     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
378         let val = if val { UINT_TRUE } else { 0 };
379
380         unsafe { atomic_or(self.v.get(), val, order) > 0 }
381     }
382
383     /// Logical "xor" with a boolean value.
384     ///
385     /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
386     /// the new value to the result.
387     ///
388     /// Returns the previous value.
389     ///
390     /// # Examples
391     ///
392     /// ```
393     /// use std::sync::atomic::{AtomicBool, Ordering};
394     ///
395     /// let foo = AtomicBool::new(true);
396     /// assert_eq!(true, foo.fetch_xor(false, Ordering::SeqCst));
397     /// assert_eq!(true, foo.load(Ordering::SeqCst));
398     ///
399     /// let foo = AtomicBool::new(true);
400     /// assert_eq!(true, foo.fetch_xor(true, Ordering::SeqCst));
401     /// assert_eq!(false, foo.load(Ordering::SeqCst));
402     ///
403     /// let foo = AtomicBool::new(false);
404     /// assert_eq!(false, foo.fetch_xor(false, Ordering::SeqCst));
405     /// assert_eq!(false, foo.load(Ordering::SeqCst));
406     /// ```
407     #[inline]
408     #[stable]
409     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
410         let val = if val { UINT_TRUE } else { 0 };
411
412         unsafe { atomic_xor(self.v.get(), val, order) > 0 }
413     }
414 }
415
416 impl AtomicInt {
417     /// Creates a new `AtomicInt`.
418     ///
419     /// # Examples
420     ///
421     /// ```
422     /// use std::sync::atomic::AtomicInt;
423     ///
424     /// let atomic_forty_two  = AtomicInt::new(42);
425     /// ```
426     #[inline]
427     #[stable]
428     pub fn new(v: int) -> AtomicInt {
429         AtomicInt {v: UnsafeCell::new(v)}
430     }
431
432     /// Loads a value from the int.
433     ///
434     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
435     ///
436     /// # Panics
437     ///
438     /// Panics if `order` is `Release` or `AcqRel`.
439     ///
440     /// # Examples
441     ///
442     /// ```
443     /// use std::sync::atomic::{AtomicInt, Ordering};
444     ///
445     /// let some_int = AtomicInt::new(5);
446     ///
447     /// let value = some_int.load(Ordering::Relaxed);
448     /// ```
449     #[inline]
450     #[stable]
451     pub fn load(&self, order: Ordering) -> int {
452         unsafe { atomic_load(self.v.get() as *const int, order) }
453     }
454
455     /// Stores a value into the int.
456     ///
457     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
458     ///
459     /// # Examples
460     ///
461     /// ```
462     /// use std::sync::atomic::{AtomicInt, Ordering};
463     ///
464     /// let some_int = AtomicInt::new(5);
465     ///
466     /// some_int.store(10, Ordering::Relaxed);
467     /// ```
468     ///
469     /// # Panics
470     ///
471     /// Panics if `order` is `Acquire` or `AcqRel`.
472     #[inline]
473     #[stable]
474     pub fn store(&self, val: int, order: Ordering) {
475         unsafe { atomic_store(self.v.get(), val, order); }
476     }
477
478     /// Stores a value into the int, returning the old value.
479     ///
480     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
481     ///
482     /// # Examples
483     ///
484     /// ```
485     /// use std::sync::atomic::{AtomicInt, Ordering};
486     ///
487     /// let some_int = AtomicInt::new(5);
488     ///
489     /// let value = some_int.swap(10, Ordering::Relaxed);
490     /// ```
491     #[inline]
492     #[stable]
493     pub fn swap(&self, val: int, order: Ordering) -> int {
494         unsafe { atomic_swap(self.v.get(), val, order) }
495     }
496
497     /// Stores a value into the int if the current value is the same as the expected value.
498     ///
499     /// If the return value is equal to `old` then the value was updated.
500     ///
501     /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
502     /// this operation.
503     ///
504     /// # Examples
505     ///
506     /// ```
507     /// use std::sync::atomic::{AtomicInt, Ordering};
508     ///
509     /// let some_int = AtomicInt::new(5);
510     ///
511     /// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed);
512     /// ```
513     #[inline]
514     #[stable]
515     pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
516         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
517     }
518
519     /// Add an int to the current value, returning the previous value.
520     ///
521     /// # Examples
522     ///
523     /// ```
524     /// use std::sync::atomic::{AtomicInt, Ordering};
525     ///
526     /// let foo = AtomicInt::new(0);
527     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
528     /// assert_eq!(10, foo.load(Ordering::SeqCst));
529     /// ```
530     #[inline]
531     #[stable]
532     pub fn fetch_add(&self, val: int, order: Ordering) -> int {
533         unsafe { atomic_add(self.v.get(), val, order) }
534     }
535
536     /// Subtract an int from the current value, returning the previous value.
537     ///
538     /// # Examples
539     ///
540     /// ```
541     /// use std::sync::atomic::{AtomicInt, Ordering};
542     ///
543     /// let foo = AtomicInt::new(0);
544     /// assert_eq!(0, foo.fetch_sub(10, Ordering::SeqCst));
545     /// assert_eq!(-10, foo.load(Ordering::SeqCst));
546     /// ```
547     #[inline]
548     #[stable]
549     pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
550         unsafe { atomic_sub(self.v.get(), val, order) }
551     }
552
553     /// Bitwise and with the current int, returning the previous value.
554     ///
555     /// # Examples
556     ///
557     /// ```
558     /// use std::sync::atomic::{AtomicInt, Ordering};
559     ///
560     /// let foo = AtomicInt::new(0b101101);
561     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
562     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
563     #[inline]
564     #[stable]
565     pub fn fetch_and(&self, val: int, order: Ordering) -> int {
566         unsafe { atomic_and(self.v.get(), val, order) }
567     }
568
569     /// Bitwise or with the current int, returning the previous value.
570     ///
571     /// # Examples
572     ///
573     /// ```
574     /// use std::sync::atomic::{AtomicInt, Ordering};
575     ///
576     /// let foo = AtomicInt::new(0b101101);
577     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
578     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
579     #[inline]
580     #[stable]
581     pub fn fetch_or(&self, val: int, order: Ordering) -> int {
582         unsafe { atomic_or(self.v.get(), val, order) }
583     }
584
585     /// Bitwise xor with the current int, returning the previous value.
586     ///
587     /// # Examples
588     ///
589     /// ```
590     /// use std::sync::atomic::{AtomicInt, Ordering};
591     ///
592     /// let foo = AtomicInt::new(0b101101);
593     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
594     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
595     #[inline]
596     #[stable]
597     pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
598         unsafe { atomic_xor(self.v.get(), val, order) }
599     }
600 }
601
602 impl AtomicUint {
603     /// Creates a new `AtomicUint`.
604     ///
605     /// # Examples
606     ///
607     /// ```
608     /// use std::sync::atomic::AtomicUint;
609     ///
610     /// let atomic_forty_two = AtomicUint::new(42u);
611     /// ```
612     #[inline]
613     #[stable]
614     pub fn new(v: uint) -> AtomicUint {
615         AtomicUint { v: UnsafeCell::new(v) }
616     }
617
618     /// Loads a value from the uint.
619     ///
620     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
621     ///
622     /// # Panics
623     ///
624     /// Panics if `order` is `Release` or `AcqRel`.
625     ///
626     /// # Examples
627     ///
628     /// ```
629     /// use std::sync::atomic::{AtomicUint, Ordering};
630     ///
631     /// let some_uint = AtomicUint::new(5);
632     ///
633     /// let value = some_uint.load(Ordering::Relaxed);
634     /// ```
635     #[inline]
636     #[stable]
637     pub fn load(&self, order: Ordering) -> uint {
638         unsafe { atomic_load(self.v.get() as *const uint, order) }
639     }
640
641     /// Stores a value into the uint.
642     ///
643     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
644     ///
645     /// # Examples
646     ///
647     /// ```
648     /// use std::sync::atomic::{AtomicUint, Ordering};
649     ///
650     /// let some_uint = AtomicUint::new(5);
651     ///
652     /// some_uint.store(10, Ordering::Relaxed);
653     /// ```
654     ///
655     /// # Panics
656     ///
657     /// Panics if `order` is `Acquire` or `AcqRel`.
658     #[inline]
659     #[stable]
660     pub fn store(&self, val: uint, order: Ordering) {
661         unsafe { atomic_store(self.v.get(), val, order); }
662     }
663
664     /// Stores a value into the uint, returning the old value.
665     ///
666     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
667     ///
668     /// # Examples
669     ///
670     /// ```
671     /// use std::sync::atomic::{AtomicUint, Ordering};
672     ///
673     /// let some_uint = AtomicUint::new(5);
674     ///
675     /// let value = some_uint.swap(10, Ordering::Relaxed);
676     /// ```
677     #[inline]
678     #[stable]
679     pub fn swap(&self, val: uint, order: Ordering) -> uint {
680         unsafe { atomic_swap(self.v.get(), val, order) }
681     }
682
683     /// Stores a value into the uint if the current value is the same as the expected value.
684     ///
685     /// If the return value is equal to `old` then the value was updated.
686     ///
687     /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
688     /// this operation.
689     ///
690     /// # Examples
691     ///
692     /// ```
693     /// use std::sync::atomic::{AtomicUint, Ordering};
694     ///
695     /// let some_uint = AtomicUint::new(5);
696     ///
697     /// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed);
698     /// ```
699     #[inline]
700     #[stable]
701     pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
702         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
703     }
704
705     /// Add to the current uint, returning the previous value.
706     ///
707     /// # Examples
708     ///
709     /// ```
710     /// use std::sync::atomic::{AtomicUint, Ordering};
711     ///
712     /// let foo = AtomicUint::new(0);
713     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
714     /// assert_eq!(10, foo.load(Ordering::SeqCst));
715     /// ```
716     #[inline]
717     #[stable]
718     pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
719         unsafe { atomic_add(self.v.get(), val, order) }
720     }
721
722     /// Subtract from the current uint, returning the previous value.
723     ///
724     /// # Examples
725     ///
726     /// ```
727     /// use std::sync::atomic::{AtomicUint, Ordering};
728     ///
729     /// let foo = AtomicUint::new(10);
730     /// assert_eq!(10, foo.fetch_sub(10, Ordering::SeqCst));
731     /// assert_eq!(0, foo.load(Ordering::SeqCst));
732     /// ```
733     #[inline]
734     #[stable]
735     pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
736         unsafe { atomic_sub(self.v.get(), val, order) }
737     }
738
739     /// Bitwise and with the current uint, returning the previous value.
740     ///
741     /// # Examples
742     ///
743     /// ```
744     /// use std::sync::atomic::{AtomicUint, Ordering};
745     ///
746     /// let foo = AtomicUint::new(0b101101);
747     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
748     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
749     #[inline]
750     #[stable]
751     pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
752         unsafe { atomic_and(self.v.get(), val, order) }
753     }
754
755     /// Bitwise or with the current uint, returning the previous value.
756     ///
757     /// # Examples
758     ///
759     /// ```
760     /// use std::sync::atomic::{AtomicUint, Ordering};
761     ///
762     /// let foo = AtomicUint::new(0b101101);
763     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
764     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
765     #[inline]
766     #[stable]
767     pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
768         unsafe { atomic_or(self.v.get(), val, order) }
769     }
770
771     /// Bitwise xor with the current uint, returning the previous value.
772     ///
773     /// # Examples
774     ///
775     /// ```
776     /// use std::sync::atomic::{AtomicUint, Ordering};
777     ///
778     /// let foo = AtomicUint::new(0b101101);
779     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
780     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
781     #[inline]
782     #[stable]
783     pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
784         unsafe { atomic_xor(self.v.get(), val, order) }
785     }
786 }
787
788 impl<T> AtomicPtr<T> {
789     /// Creates a new `AtomicPtr`.
790     ///
791     /// # Examples
792     ///
793     /// ```
794     /// use std::sync::atomic::AtomicPtr;
795     ///
796     /// let ptr = &mut 5i;
797     /// let atomic_ptr  = AtomicPtr::new(ptr);
798     /// ```
799     #[inline]
800     #[stable]
801     pub fn new(p: *mut T) -> AtomicPtr<T> {
802         AtomicPtr { p: UnsafeCell::new(p as uint) }
803     }
804
805     /// Loads a value from the pointer.
806     ///
807     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
808     ///
809     /// # Panics
810     ///
811     /// Panics if `order` is `Release` or `AcqRel`.
812     ///
813     /// # Examples
814     ///
815     /// ```
816     /// use std::sync::atomic::{AtomicPtr, Ordering};
817     ///
818     /// let ptr = &mut 5i;
819     /// let some_ptr  = AtomicPtr::new(ptr);
820     ///
821     /// let value = some_ptr.load(Ordering::Relaxed);
822     /// ```
823     #[inline]
824     #[stable]
825     pub fn load(&self, order: Ordering) -> *mut T {
826         unsafe {
827             atomic_load(self.p.get() as *const *mut T, order) as *mut T
828         }
829     }
830
831     /// Stores a value into the pointer.
832     ///
833     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
834     ///
835     /// # Examples
836     ///
837     /// ```
838     /// use std::sync::atomic::{AtomicPtr, Ordering};
839     ///
840     /// let ptr = &mut 5i;
841     /// let some_ptr  = AtomicPtr::new(ptr);
842     ///
843     /// let other_ptr = &mut 10i;
844     ///
845     /// some_ptr.store(other_ptr, Ordering::Relaxed);
846     /// ```
847     ///
848     /// # Panics
849     ///
850     /// Panics if `order` is `Acquire` or `AcqRel`.
851     #[inline]
852     #[stable]
853     pub fn store(&self, ptr: *mut T, order: Ordering) {
854         unsafe { atomic_store(self.p.get(), ptr as uint, order); }
855     }
856
857     /// Stores a value into the pointer, returning the old value.
858     ///
859     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
860     ///
861     /// # Examples
862     ///
863     /// ```
864     /// use std::sync::atomic::{AtomicPtr, Ordering};
865     ///
866     /// let ptr = &mut 5i;
867     /// let some_ptr  = AtomicPtr::new(ptr);
868     ///
869     /// let other_ptr = &mut 10i;
870     ///
871     /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
872     /// ```
873     #[inline]
874     #[stable]
875     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
876         unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T }
877     }
878
879     /// Stores a value into the pointer if the current value is the same as the expected value.
880     ///
881     /// If the return value is equal to `old` then the value was updated.
882     ///
883     /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
884     /// this operation.
885     ///
886     /// # Examples
887     ///
888     /// ```
889     /// use std::sync::atomic::{AtomicPtr, Ordering};
890     ///
891     /// let ptr = &mut 5i;
892     /// let some_ptr  = AtomicPtr::new(ptr);
893     ///
894     /// let other_ptr   = &mut 10i;
895     /// let another_ptr = &mut 10i;
896     ///
897     /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
898     /// ```
899     #[inline]
900     #[stable]
901     pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
902         unsafe {
903             atomic_compare_and_swap(self.p.get(), old as uint,
904                                     new as uint, order) as *mut T
905         }
906     }
907 }
908
909 #[inline]
910 unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
911     match order {
912         Release => intrinsics::atomic_store_rel(dst, val),
913         Relaxed => intrinsics::atomic_store_relaxed(dst, val),
914         SeqCst  => intrinsics::atomic_store(dst, val),
915         Acquire => panic!("there is no such thing as an acquire store"),
916         AcqRel  => panic!("there is no such thing as an acquire/release store"),
917     }
918 }
919
920 #[inline]
921 #[stable]
922 unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
923     match order {
924         Acquire => intrinsics::atomic_load_acq(dst),
925         Relaxed => intrinsics::atomic_load_relaxed(dst),
926         SeqCst  => intrinsics::atomic_load(dst),
927         Release => panic!("there is no such thing as a release load"),
928         AcqRel  => panic!("there is no such thing as an acquire/release load"),
929     }
930 }
931
932 #[inline]
933 #[stable]
934 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
935     match order {
936         Acquire => intrinsics::atomic_xchg_acq(dst, val),
937         Release => intrinsics::atomic_xchg_rel(dst, val),
938         AcqRel  => intrinsics::atomic_xchg_acqrel(dst, val),
939         Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
940         SeqCst  => intrinsics::atomic_xchg(dst, val)
941     }
942 }
943
944 /// Returns the old value (like __sync_fetch_and_add).
945 #[inline]
946 #[stable]
947 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
948     match order {
949         Acquire => intrinsics::atomic_xadd_acq(dst, val),
950         Release => intrinsics::atomic_xadd_rel(dst, val),
951         AcqRel  => intrinsics::atomic_xadd_acqrel(dst, val),
952         Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
953         SeqCst  => intrinsics::atomic_xadd(dst, val)
954     }
955 }
956
957 /// Returns the old value (like __sync_fetch_and_sub).
958 #[inline]
959 #[stable]
960 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
961     match order {
962         Acquire => intrinsics::atomic_xsub_acq(dst, val),
963         Release => intrinsics::atomic_xsub_rel(dst, val),
964         AcqRel  => intrinsics::atomic_xsub_acqrel(dst, val),
965         Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
966         SeqCst  => intrinsics::atomic_xsub(dst, val)
967     }
968 }
969
970 #[inline]
971 #[stable]
972 unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
973     match order {
974         Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
975         Release => intrinsics::atomic_cxchg_rel(dst, old, new),
976         AcqRel  => intrinsics::atomic_cxchg_acqrel(dst, old, new),
977         Relaxed => intrinsics::atomic_cxchg_relaxed(dst, old, new),
978         SeqCst  => intrinsics::atomic_cxchg(dst, old, new),
979     }
980 }
981
982 #[inline]
983 #[stable]
984 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
985     match order {
986         Acquire => intrinsics::atomic_and_acq(dst, val),
987         Release => intrinsics::atomic_and_rel(dst, val),
988         AcqRel  => intrinsics::atomic_and_acqrel(dst, val),
989         Relaxed => intrinsics::atomic_and_relaxed(dst, val),
990         SeqCst  => intrinsics::atomic_and(dst, val)
991     }
992 }
993
994 #[inline]
995 #[stable]
996 unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
997     match order {
998         Acquire => intrinsics::atomic_nand_acq(dst, val),
999         Release => intrinsics::atomic_nand_rel(dst, val),
1000         AcqRel  => intrinsics::atomic_nand_acqrel(dst, val),
1001         Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
1002         SeqCst  => intrinsics::atomic_nand(dst, val)
1003     }
1004 }
1005
1006
1007 #[inline]
1008 #[stable]
1009 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
1010     match order {
1011         Acquire => intrinsics::atomic_or_acq(dst, val),
1012         Release => intrinsics::atomic_or_rel(dst, val),
1013         AcqRel  => intrinsics::atomic_or_acqrel(dst, val),
1014         Relaxed => intrinsics::atomic_or_relaxed(dst, val),
1015         SeqCst  => intrinsics::atomic_or(dst, val)
1016     }
1017 }
1018
1019
1020 #[inline]
1021 #[stable]
1022 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1023     match order {
1024         Acquire => intrinsics::atomic_xor_acq(dst, val),
1025         Release => intrinsics::atomic_xor_rel(dst, val),
1026         AcqRel  => intrinsics::atomic_xor_acqrel(dst, val),
1027         Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
1028         SeqCst  => intrinsics::atomic_xor(dst, val)
1029     }
1030 }
1031
1032
1033 /// An atomic fence.
1034 ///
1035 /// A fence 'A' which has `Release` ordering semantics, synchronizes with a
1036 /// fence 'B' with (at least) `Acquire` semantics, if and only if there exists
1037 /// atomic operations X and Y, both operating on some atomic object 'M' such
1038 /// that A is sequenced before X, Y is synchronized before B and Y observes
1039 /// the change to M. This provides a happens-before dependence between A and B.
1040 ///
1041 /// Atomic operations with `Release` or `Acquire` semantics can also synchronize
1042 /// with a fence.
1043 ///
1044 /// A fence which has `SeqCst` ordering, in addition to having both `Acquire`
1045 /// and `Release` semantics, participates in the global program order of the
1046 /// other `SeqCst` operations and/or fences.
1047 ///
1048 /// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
1049 ///
1050 /// # Panics
1051 ///
1052 /// Panics if `order` is `Relaxed`.
1053 #[inline]
1054 #[stable]
1055 pub fn fence(order: Ordering) {
1056     unsafe {
1057         match order {
1058             Acquire => intrinsics::atomic_fence_acq(),
1059             Release => intrinsics::atomic_fence_rel(),
1060             AcqRel  => intrinsics::atomic_fence_acqrel(),
1061             SeqCst  => intrinsics::atomic_fence(),
1062             Relaxed => panic!("there is no such thing as a relaxed fence")
1063         }
1064     }
1065 }