2014-05-12 21:30:48 -07:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! Core atomic primitives
|
|
|
|
|
2014-08-04 15:42:36 -07:00
|
|
|
#![stable]
|
|
|
|
|
2014-11-06 00:05:53 -08:00
|
|
|
pub use self::Ordering::*;
|
|
|
|
|
2014-05-12 21:30:48 -07:00
|
|
|
use intrinsics;
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
use cell::UnsafeCell;
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
use kinds::Copy;
|
2014-05-12 21:30:48 -07:00
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// A boolean type which can be safely shared between threads.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub struct AtomicBool {
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
v: UnsafeCell<uint>,
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// A signed integer type which can be safely shared between threads.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub struct AtomicInt {
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
v: UnsafeCell<int>,
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// An unsigned integer type which can be safely shared between threads.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub struct AtomicUint {
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
v: UnsafeCell<uint>,
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// A raw pointer type which can be safely shared between threads.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub struct AtomicPtr<T> {
|
std: Stabilize unit, bool, ty, tuple, arc, any
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
2014-07-23 19:10:12 -07:00
|
|
|
p: UnsafeCell<uint>,
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Atomic memory orderings
|
|
|
|
///
|
|
|
|
/// Memory orderings limit the ways that both the compiler and CPU may reorder
|
|
|
|
/// instructions around atomic operations. At its most restrictive,
|
|
|
|
/// "sequentially consistent" atomics allow neither reads nor writes
|
|
|
|
/// to be moved either before or after the atomic operation; on the other end
|
|
|
|
/// "relaxed" atomics allow all reorderings.
|
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Rust's memory orderings are [the same as
|
|
|
|
/// C++'s](http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync).
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub enum Ordering {
|
2014-11-19 10:35:47 -05:00
|
|
|
/// No ordering constraints, only atomic operations.
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
Relaxed,
|
|
|
|
/// When coupled with a store, all previous writes become visible
|
|
|
|
/// to another thread that performs a load with `Acquire` ordering
|
2014-11-19 10:35:47 -05:00
|
|
|
/// on the same value.
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
Release,
|
|
|
|
/// When coupled with a load, all subsequent loads will see data
|
|
|
|
/// written before a store with `Release` ordering on the same value
|
2014-11-19 10:35:47 -05:00
|
|
|
/// in another thread.
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
Acquire,
|
|
|
|
/// When coupled with a load, uses `Acquire` ordering, and with a store
|
2014-11-19 10:35:47 -05:00
|
|
|
/// `Release` ordering.
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
AcqRel,
|
|
|
|
/// Like `AcqRel` with the additional guarantee that all threads see all
|
|
|
|
/// sequentially consistent operations in the same order.
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-11-19 10:35:47 -05:00
|
|
|
SeqCst,
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
impl Copy for Ordering {}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// An `AtomicBool` initialized to `false`.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
2014-10-06 16:14:00 -07:00
|
|
|
pub const INIT_ATOMIC_BOOL: AtomicBool =
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicBool { v: UnsafeCell { value: 0 } };
|
2014-11-19 10:35:47 -05:00
|
|
|
/// An `AtomicInt` initialized to `0`.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
2014-10-06 16:14:00 -07:00
|
|
|
pub const INIT_ATOMIC_INT: AtomicInt =
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicInt { v: UnsafeCell { value: 0 } };
|
2014-11-19 10:35:47 -05:00
|
|
|
/// An `AtomicUint` initialized to `0`.
|
2014-08-04 15:42:36 -07:00
|
|
|
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
2014-10-06 16:14:00 -07:00
|
|
|
pub const INIT_ATOMIC_UINT: AtomicUint =
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicUint { v: UnsafeCell { value: 0, } };
|
2014-05-12 21:30:48 -07:00
|
|
|
|
|
|
|
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
|
2014-10-06 16:14:00 -07:00
|
|
|
const UINT_TRUE: uint = -1;
|
2014-05-12 21:30:48 -07:00
|
|
|
|
|
|
|
impl AtomicBool {
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Creates a new `AtomicBool`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::AtomicBool;
|
|
|
|
///
|
|
|
|
/// let atomic_true = AtomicBool::new(true);
|
|
|
|
/// let atomic_false = AtomicBool::new(false);
|
|
|
|
/// ```
|
2014-10-27 09:14:57 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn new(v: bool) -> AtomicBool {
|
|
|
|
let val = if v { UINT_TRUE } else { 0 };
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicBool { v: UnsafeCell::new(val) }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Loads a value from the bool.
|
|
|
|
///
|
|
|
|
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Release` or `AcqRel`.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_bool = AtomicBool::new(true);
|
|
|
|
///
|
|
|
|
/// let value = some_bool.load(Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn load(&self, order: Ordering) -> bool {
|
2014-06-25 12:47:34 -07:00
|
|
|
unsafe { atomic_load(self.v.get() as *const uint, order) > 0 }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the bool.
|
|
|
|
///
|
|
|
|
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_bool = AtomicBool::new(true);
|
|
|
|
///
|
|
|
|
/// some_bool.store(false, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Acquire` or `AcqRel`.
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn store(&self, val: bool, order: Ordering) {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_store(self.v.get(), val, order); }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the bool, returning the old value.
|
|
|
|
///
|
|
|
|
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_bool = AtomicBool::new(true);
|
|
|
|
///
|
|
|
|
/// let value = some_bool.swap(false, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn swap(&self, val: bool, order: Ordering) -> bool {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_swap(self.v.get(), val, order) > 0 }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the bool if the current value is the same as the expected value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// If the return value is equal to `old` then the value was updated.
|
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// `swap` also takes an `Ordering` argument which describes the memory ordering of this
|
|
|
|
/// operation.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// # Examples
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicBool, Ordering};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// let some_bool = AtomicBool::new(true);
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// let value = some_bool.store(false, Ordering::Relaxed);
|
2014-05-12 21:30:48 -07:00
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool {
|
|
|
|
let old = if old { UINT_TRUE } else { 0 };
|
|
|
|
let new = if new { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) > 0 }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Logical "and" with a boolean value.
|
|
|
|
///
|
|
|
|
/// Performs a logical "and" operation on the current value and the argument `val`, and sets
|
|
|
|
/// the new value to the result.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// Returns the previous value.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicBool, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_and(false, SeqCst));
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_and(true, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(false);
|
|
|
|
/// assert_eq!(false, foo.fetch_and(false, SeqCst));
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_and(self.v.get(), val, order) > 0 }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Logical "nand" with a boolean value.
|
|
|
|
///
|
|
|
|
/// Performs a logical "nand" operation on the current value and the argument `val`, and sets
|
|
|
|
/// the new value to the result.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// Returns the previous value.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicBool, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_nand(false, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_nand(true, SeqCst));
|
|
|
|
/// assert_eq!(0, foo.load(SeqCst) as int);
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(false);
|
|
|
|
/// assert_eq!(false, foo.fetch_nand(false, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_nand(self.v.get(), val, order) > 0 }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Logical "or" with a boolean value.
|
|
|
|
///
|
|
|
|
/// Performs a logical "or" operation on the current value and the argument `val`, and sets the
|
|
|
|
/// new value to the result.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// Returns the previous value.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicBool, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_or(false, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_or(true, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(false);
|
|
|
|
/// assert_eq!(false, foo.fetch_or(false, SeqCst));
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_or(self.v.get(), val, order) > 0 }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Logical "xor" with a boolean value.
|
|
|
|
///
|
|
|
|
/// Performs a logical "xor" operation on the current value and the argument `val`, and sets
|
|
|
|
/// the new value to the result.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// Returns the previous value.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicBool, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_xor(false, SeqCst));
|
|
|
|
/// assert_eq!(true, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(true);
|
|
|
|
/// assert_eq!(true, foo.fetch_xor(true, SeqCst));
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
///
|
|
|
|
/// let foo = AtomicBool::new(false);
|
|
|
|
/// assert_eq!(false, foo.fetch_xor(false, SeqCst));
|
|
|
|
/// assert_eq!(false, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
|
|
|
|
let val = if val { UINT_TRUE } else { 0 };
|
|
|
|
|
|
|
|
unsafe { atomic_xor(self.v.get(), val, order) > 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AtomicInt {
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Creates a new `AtomicInt`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::AtomicInt;
|
|
|
|
///
|
|
|
|
/// let atomic_forty_two = AtomicInt::new(42);
|
|
|
|
/// ```
|
2014-10-27 09:14:57 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn new(v: int) -> AtomicInt {
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicInt {v: UnsafeCell::new(v)}
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Loads a value from the int.
|
|
|
|
///
|
|
|
|
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Release` or `AcqRel`.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicInt, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_int = AtomicInt::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_int.load(Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn load(&self, order: Ordering) -> int {
|
2014-06-25 12:47:34 -07:00
|
|
|
unsafe { atomic_load(self.v.get() as *const int, order) }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the int.
|
|
|
|
///
|
|
|
|
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicInt, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_int = AtomicInt::new(5);
|
|
|
|
///
|
|
|
|
/// some_int.store(10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Acquire` or `AcqRel`.
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn store(&self, val: int, order: Ordering) {
|
|
|
|
unsafe { atomic_store(self.v.get(), val, order); }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the int, returning the old value.
|
|
|
|
///
|
|
|
|
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicInt, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_int = AtomicInt::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_int.swap(10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn swap(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_swap(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the int if the current value is the same as the expected value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// If the return value is equal to `old` then the value was updated.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
|
|
|
|
/// this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicInt, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_int = AtomicInt::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Add an int to the current value, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicInt, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicInt::new(0);
|
|
|
|
/// assert_eq!(0, foo.fetch_add(10, SeqCst));
|
|
|
|
/// assert_eq!(10, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_add(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_add(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Subtract an int from the current value, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicInt, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicInt::new(0);
|
|
|
|
/// assert_eq!(0, foo.fetch_sub(10, SeqCst));
|
|
|
|
/// assert_eq!(-10, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_sub(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise and with the current int, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-10-04 13:29:09 +02:00
|
|
|
/// use std::sync::atomic::{AtomicInt, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-10-04 13:29:09 +02:00
|
|
|
/// let foo = AtomicInt::new(0b101101);
|
2014-05-12 21:30:48 -07:00
|
|
|
/// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b100001, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_and(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_and(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise or with the current int, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-10-04 13:29:09 +02:00
|
|
|
/// use std::sync::atomic::{AtomicInt, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-10-04 13:29:09 +02:00
|
|
|
/// let foo = AtomicInt::new(0b101101);
|
2014-05-12 21:30:48 -07:00
|
|
|
/// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b111111, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_or(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_or(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise xor with the current int, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-10-04 13:29:09 +02:00
|
|
|
/// use std::sync::atomic::{AtomicInt, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-10-04 13:29:09 +02:00
|
|
|
/// let foo = AtomicInt::new(0b101101);
|
2014-05-12 21:30:48 -07:00
|
|
|
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b011110, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
|
|
|
|
unsafe { atomic_xor(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AtomicUint {
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Creates a new `AtomicUint`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::AtomicUint;
|
|
|
|
///
|
|
|
|
/// let atomic_forty_two = AtomicUint::new(42u);
|
|
|
|
/// ```
|
2014-10-27 09:14:57 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn new(v: uint) -> AtomicUint {
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicUint { v: UnsafeCell::new(v) }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Loads a value from the uint.
|
|
|
|
///
|
|
|
|
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Release` or `AcqRel`.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicUint, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_uint = AtomicUint::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_uint.load(Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn load(&self, order: Ordering) -> uint {
|
2014-06-25 12:47:34 -07:00
|
|
|
unsafe { atomic_load(self.v.get() as *const uint, order) }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the uint.
|
|
|
|
///
|
|
|
|
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicUint, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_uint = AtomicUint::new(5);
|
|
|
|
///
|
|
|
|
/// some_uint.store(10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Acquire` or `AcqRel`.
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn store(&self, val: uint, order: Ordering) {
|
|
|
|
unsafe { atomic_store(self.v.get(), val, order); }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the uint, returning the old value.
|
|
|
|
///
|
|
|
|
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicUint, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_uint = AtomicUint::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_uint.swap(10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn swap(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_swap(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the uint if the current value is the same as the expected value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// If the return value is equal to `old` then the value was updated.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
|
|
|
|
/// this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicUint, Ordering};
|
|
|
|
///
|
|
|
|
/// let some_uint = AtomicUint::new(5);
|
|
|
|
///
|
|
|
|
/// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Add to the current uint, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicUint, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicUint::new(0);
|
|
|
|
/// assert_eq!(0, foo.fetch_add(10, SeqCst));
|
|
|
|
/// assert_eq!(10, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_add(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Subtract from the current uint, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicUint, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicUint::new(10);
|
|
|
|
/// assert_eq!(10, foo.fetch_sub(10, SeqCst));
|
|
|
|
/// assert_eq!(0, foo.load(SeqCst));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_sub(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise and with the current uint, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicUint, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicUint::new(0b101101);
|
|
|
|
/// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b100001, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_and(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise or with the current uint, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicUint, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicUint::new(0b101101);
|
|
|
|
/// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b111111, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_or(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Bitwise xor with the current uint, returning the previous value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
/// use std::sync::atomic::{AtomicUint, SeqCst};
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// let foo = AtomicUint::new(0b101101);
|
|
|
|
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst));
|
|
|
|
/// assert_eq!(0b011110, foo.load(SeqCst));
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
|
|
|
|
unsafe { atomic_xor(self.v.get(), val, order) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> AtomicPtr<T> {
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Creates a new `AtomicPtr`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::AtomicPtr;
|
|
|
|
///
|
|
|
|
/// let ptr = &mut 5i;
|
|
|
|
/// let atomic_ptr = AtomicPtr::new(ptr);
|
|
|
|
/// ```
|
2014-10-27 09:14:57 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn new(p: *mut T) -> AtomicPtr<T> {
|
2014-12-13 23:06:44 -05:00
|
|
|
AtomicPtr { p: UnsafeCell::new(p as uint) }
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Loads a value from the pointer.
|
|
|
|
///
|
|
|
|
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Release` or `AcqRel`.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
///
|
|
|
|
/// let ptr = &mut 5i;
|
|
|
|
/// let some_ptr = AtomicPtr::new(ptr);
|
|
|
|
///
|
|
|
|
/// let value = some_ptr.load(Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn load(&self, order: Ordering) -> *mut T {
|
|
|
|
unsafe {
|
2014-06-25 12:47:34 -07:00
|
|
|
atomic_load(self.p.get() as *const *mut T, order) as *mut T
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the pointer.
|
|
|
|
///
|
|
|
|
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
///
|
|
|
|
/// let ptr = &mut 5i;
|
|
|
|
/// let some_ptr = AtomicPtr::new(ptr);
|
|
|
|
///
|
|
|
|
/// let other_ptr = &mut 10i;
|
|
|
|
///
|
|
|
|
/// some_ptr.store(other_ptr, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-08-04 15:42:36 -07:00
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// Panics if `order` is `Acquire` or `AcqRel`.
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn store(&self, ptr: *mut T, order: Ordering) {
|
|
|
|
unsafe { atomic_store(self.p.get(), ptr as uint, order); }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the pointer, returning the old value.
|
|
|
|
///
|
|
|
|
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
///
|
|
|
|
/// let ptr = &mut 5i;
|
|
|
|
/// let some_ptr = AtomicPtr::new(ptr);
|
|
|
|
///
|
|
|
|
/// let other_ptr = &mut 10i;
|
|
|
|
///
|
|
|
|
/// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
|
|
|
|
unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T }
|
|
|
|
}
|
|
|
|
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Stores a value into the pointer if the current value is the same as the expected value.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// If the return value is equal to `old` then the value was updated.
|
2014-11-19 10:35:47 -05:00
|
|
|
///
|
|
|
|
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
|
|
|
|
/// this operation.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
///
|
|
|
|
/// let ptr = &mut 5i;
|
|
|
|
/// let some_ptr = AtomicPtr::new(ptr);
|
|
|
|
///
|
|
|
|
/// let other_ptr = &mut 10i;
|
|
|
|
/// let another_ptr = &mut 10i;
|
|
|
|
///
|
|
|
|
/// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
|
|
|
|
/// ```
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
|
|
|
|
unsafe {
|
|
|
|
atomic_compare_and_swap(self.p.get(), old as uint,
|
|
|
|
new as uint, order) as *mut T
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
|
|
|
|
match order {
|
|
|
|
Release => intrinsics::atomic_store_rel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_store_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_store(dst, val),
|
2014-10-09 15:17:22 -04:00
|
|
|
Acquire => panic!("there is no such thing as an acquire store"),
|
|
|
|
AcqRel => panic!("there is no such thing as an acquire/release store"),
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-06-25 12:47:34 -07:00
|
|
|
unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
|
2014-05-12 21:30:48 -07:00
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_load_acq(dst),
|
|
|
|
Relaxed => intrinsics::atomic_load_relaxed(dst),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_load(dst),
|
2014-10-09 15:17:22 -04:00
|
|
|
Release => panic!("there is no such thing as a release load"),
|
|
|
|
AcqRel => panic!("there is no such thing as an acquire/release load"),
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_xchg_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_xchg_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_xchg(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the old value (like __sync_fetch_and_add).
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_xadd_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_xadd_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_xadd(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the old value (like __sync_fetch_and_sub).
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_xsub_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_xsub_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_xsub(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
|
|
|
|
Release => intrinsics::atomic_cxchg_rel(dst, old, new),
|
|
|
|
AcqRel => intrinsics::atomic_cxchg_acqrel(dst, old, new),
|
|
|
|
Relaxed => intrinsics::atomic_cxchg_relaxed(dst, old, new),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_cxchg(dst, old, new),
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_and_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_and_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_and_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_and_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_and(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_nand_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_nand_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_nand(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_or_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_or_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_or_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_or_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_or(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2014-11-14 20:39:41 -08:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_xor_acq(dst, val),
|
|
|
|
Release => intrinsics::atomic_xor_rel(dst, val),
|
|
|
|
AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
|
|
|
|
Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
|
2014-08-04 15:42:36 -07:00
|
|
|
SeqCst => intrinsics::atomic_xor(dst, val)
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// An atomic fence.
|
|
|
|
///
|
|
|
|
/// A fence 'A' which has `Release` ordering semantics, synchronizes with a
|
|
|
|
/// fence 'B' with (at least) `Acquire` semantics, if and only if there exists
|
|
|
|
/// atomic operations X and Y, both operating on some atomic object 'M' such
|
2014-11-06 23:14:02 +00:00
|
|
|
/// that A is sequenced before X, Y is synchronized before B and Y observes
|
2014-05-12 21:30:48 -07:00
|
|
|
/// the change to M. This provides a happens-before dependence between A and B.
|
|
|
|
///
|
|
|
|
/// Atomic operations with `Release` or `Acquire` semantics can also synchronize
|
|
|
|
/// with a fence.
|
|
|
|
///
|
2014-11-06 23:14:02 +00:00
|
|
|
/// A fence which has `SeqCst` ordering, in addition to having both `Acquire`
|
|
|
|
/// and `Release` semantics, participates in the global program order of the
|
|
|
|
/// other `SeqCst` operations and/or fences.
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
|
|
|
/// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
|
|
|
|
///
|
2014-11-12 03:36:09 +09:00
|
|
|
/// # Panics
|
2014-05-12 21:30:48 -07:00
|
|
|
///
|
2014-11-19 10:35:47 -05:00
|
|
|
/// Panics if `order` is `Relaxed`.
|
2014-05-12 21:30:48 -07:00
|
|
|
#[inline]
|
2014-08-04 15:42:36 -07:00
|
|
|
#[stable]
|
2014-05-12 21:30:48 -07:00
|
|
|
pub fn fence(order: Ordering) {
|
|
|
|
unsafe {
|
|
|
|
match order {
|
|
|
|
Acquire => intrinsics::atomic_fence_acq(),
|
|
|
|
Release => intrinsics::atomic_fence_rel(),
|
|
|
|
AcqRel => intrinsics::atomic_fence_acqrel(),
|
|
|
|
SeqCst => intrinsics::atomic_fence(),
|
2014-10-09 15:17:22 -04:00
|
|
|
Relaxed => panic!("there is no such thing as a relaxed fence")
|
2014-05-12 21:30:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|