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