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