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