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