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