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