use intrinsics;
use cell::UnsafeCell;
+use result::Result::{self, Ok, Err};
+
use default::Default;
use fmt;
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
- self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
+ Ok(x) => x,
+ Err(x) => x,
+ }
}
/// Stores a value into the `bool` if the current value is the same as the `current` value.
///
- /// The return value is always the previous value. If it is equal to `current`, then the value
- /// was updated.
+ /// The return value is a result indicating whether the new value was written and containing
+ /// the previous value. On success this value is guaranteed to be equal to `new`.
///
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
/// operation. The first describes the required ordering if the operation succeeds while the
/// false,
/// Ordering::Acquire,
/// Ordering::Relaxed),
- /// true);
+ /// Ok(true));
/// assert_eq!(some_bool.load(Ordering::Relaxed), false);
///
/// assert_eq!(some_bool.compare_exchange(true, true,
/// Ordering::SeqCst,
/// Ordering::Acquire),
- /// false);
+ /// Err(false));
/// assert_eq!(some_bool.load(Ordering::Relaxed), false);
/// ```
#[inline]
current: bool,
new: bool,
success: Ordering,
- failure: Ordering) -> bool {
+ failure: Ordering) -> Result<bool, bool> {
let current = if current { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 };
- unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) > 0 }
+ match unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } {
+ Ok(x) => Ok(x > 0),
+ Err(x) => Err(x > 0),
+ }
}
/// Stores a value into the `bool` if the current value is the same as the `current` value.
///
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
/// comparison succeeds, which can result in more efficient code on some platforms. The
- /// returned value is a tuple of the existing value and a flag indicating whether the
- /// new value was written.
+ /// return value is a result indicating whether the new value was written and containing the
+ /// previous value.
///
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
/// ordering of this operation. The first describes the required ordering if the operation
/// let new = true;
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
- /// let result = val.compare_exchange_weak(old, new,
- /// Ordering::SeqCst,
- /// Ordering::Relaxed);
- /// if result.1 {
- /// break;
- /// } else {
- /// old = result.0;
+ /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+ /// Ok(_) => break,
+ /// Err(x) => old = x,
/// }
/// }
/// ```
current: bool,
new: bool,
success: Ordering,
- failure: Ordering) -> (bool, bool) {
+ failure: Ordering) -> Result<bool, bool> {
let current = if current { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 };
- let result = unsafe {
- atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
- };
- (result.0 > 0, result.1)
+ match unsafe { atomic_compare_exchange_weak(self.v.get(), current, new,
+ success, failure) } {
+ Ok(x) => Ok(x > 0),
+ Err(x) => Err(x > 0),
+ }
}
/// Logical "and" with a boolean value.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, current: isize, new: isize, order: Ordering) -> isize {
- self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
+ Ok(x) => x,
+ Err(x) => x,
+ }
}
/// Stores a value into the `isize` if the current value is the same as the `current` value.
///
- /// The return value is always the previous value. If it is equal to `current`, then the value
- /// was updated.
+ /// The return value is a result indicating whether the new value was written and containing
+ /// the previous value. On success this value is guaranteed to be equal to `new`.
///
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
/// operation. The first describes the required ordering if the operation succeeds while the
/// assert_eq!(some_isize.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
- /// 5);
+ /// Ok(5));
/// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_isize.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
- /// 10);
+ /// Err(10));
/// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
/// ```
#[inline]
current: isize,
new: isize,
success: Ordering,
- failure: Ordering) -> isize {
+ failure: Ordering) -> Result<isize, isize> {
unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
}
///
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
/// comparison succeeds, which can result in more efficient code on some platforms. The
- /// returned value is a tuple of the existing value and a flag indicating whether the
- /// new value was written.
+ /// return value is a result indicating whether the new value was written and containing the
+ /// previous value.
///
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
/// ordering of this operation. The first describes the required ordering if the operation
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
- /// let result = val.compare_exchange_weak(old, new,
- /// Ordering::SeqCst,
- /// Ordering::Relaxed);
- /// if result.1 {
- /// break;
- /// } else {
- /// old = result.0;
+ /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+ /// Ok(_) => break,
+ /// Err(x) => old = x,
/// }
/// }
/// ```
current: isize,
new: isize,
success: Ordering,
- failure: Ordering) -> (isize, bool) {
+ failure: Ordering) -> Result<isize, isize> {
unsafe { atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) }
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, current: usize, new: usize, order: Ordering) -> usize {
- self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
+ Ok(x) => x,
+ Err(x) => x,
+ }
}
/// Stores a value into the `usize` if the current value is the same as the `current` value.
///
- /// The return value is always the previous value. If it is equal to `current`, then the value
- /// was updated.
+ /// The return value is a result indicating whether the new value was written and containing
+ /// the previous value. On success this value is guaranteed to be equal to `new`.
///
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
/// operation. The first describes the required ordering if the operation succeeds while the
/// assert_eq!(some_isize.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
- /// 5);
+ /// Ok(5));
/// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_isize.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
- /// 10);
+ /// Err(10));
/// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
/// ```
#[inline]
current: usize,
new: usize,
success: Ordering,
- failure: Ordering) -> usize {
+ failure: Ordering) -> Result<usize, usize> {
unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
}
///
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
/// comparison succeeds, which can result in more efficient code on some platforms. The
- /// returned value is a tuple of the existing value and a flag indicating whether the
- /// new value was written.
+ /// return value is a result indicating whether the new value was written and containing the
+ /// previous value.
///
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
/// ordering of this operation. The first describes the required ordering if the operation
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
- /// let result = val.compare_exchange_weak(old, new,
- /// Ordering::SeqCst,
- /// Ordering::Relaxed);
- /// if result.1 {
- /// break;
- /// } else {
- /// old = result.0;
+ /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+ /// Ok(_) => break,
+ /// Err(x) => old = x,
/// }
/// }
/// ```
current: usize,
new: usize,
success: Ordering,
- failure: Ordering) -> (usize, bool) {
+ failure: Ordering) -> Result<usize, usize> {
unsafe { atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) }
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
- self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+ match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
+ Ok(x) => x,
+ Err(x) => x,
+ }
}
/// Stores a value into the pointer if the current value is the same as the `current` value.
///
- /// The return value is always the previous value. If it is equal to `current`, then the value
- /// was updated.
+ /// The return value is a result indicating whether the new value was written and containing
+ /// the previous value. On success this value is guaranteed to be equal to `new`.
///
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
/// operation. The first describes the required ordering if the operation succeeds while the
current: *mut T,
new: *mut T,
success: Ordering,
- failure: Ordering) -> *mut T {
+ failure: Ordering) -> Result<*mut T, *mut T> {
unsafe {
- atomic_compare_exchange(self.p.get() as *mut usize, current as usize,
- new as usize, success, failure) as *mut T
+ let res = atomic_compare_exchange(self.p.get() as *mut usize,
+ current as usize,
+ new as usize,
+ success,
+ failure);
+ match res {
+ Ok(x) => Ok(x as *mut T),
+ Err(x) => Err(x as *mut T),
+ }
}
}
///
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
/// comparison succeeds, which can result in more efficient code on some platforms. The
- /// returned value is a tuple of the existing value and a flag indicating whether the
- /// new value was written.
+ /// return value is a result indicating whether the new value was written and containing the
+ /// previous value.
///
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
/// ordering of this operation. The first describes the required ordering if the operation
/// let new = &mut 10;
/// let mut old = some_ptr.load(Ordering::Relaxed);
/// loop {
- /// let result = some_ptr.compare_exchange_weak(old, new,
- /// Ordering::SeqCst,
- /// Ordering::Relaxed);
- /// if result.1 {
- /// break;
- /// } else {
- /// old = result.0;
+ /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+ /// Ok(_) => break,
+ /// Err(x) => old = x,
/// }
/// }
/// ```
current: *mut T,
new: *mut T,
success: Ordering,
- failure: Ordering) -> (*mut T, bool) {
- let result = unsafe {
- atomic_compare_exchange_weak(self.p.get() as *mut usize, current as usize,
- new as usize, success, failure)
- };
- (result.0 as *mut T, result.1)
+ failure: Ordering) -> Result<*mut T, *mut T> {
+ unsafe {
+ let res = atomic_compare_exchange_weak(self.p.get() as *mut usize,
+ current as usize,
+ new as usize,
+ success,
+ failure);
+ match res {
+ Ok(x) => Ok(x as *mut T),
+ Err(x) => Err(x as *mut T),
+ }
+ }
}
}
old: T,
new: T,
success: Ordering,
- failure: Ordering) -> T {
- match (success, failure) {
+ failure: Ordering) -> Result<T, T> {
+ let (val, ok) = match (success, failure) {
(Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
(Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
(AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
(_, Release) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, AcqRel) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
+ };
+ if ok {
+ Ok(val)
+ } else {
+ Err(val)
}
}
old: T,
new: T,
success: Ordering,
- _: Ordering) -> T {
- match success {
+ _: Ordering) -> Result<T, T>
+ where T: ::cmp::Eq + ::marker::Copy
+{
+ let val = match success {
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),
SeqCst => intrinsics::atomic_cxchg(dst, old, new),
+ };
+ if val == old {
+ Ok(val)
+ } else {
+ Err(val)
}
}
old: T,
new: T,
success: Ordering,
- failure: Ordering) -> (T, bool) {
- match (success, failure) {
+ failure: Ordering) -> Result<T, T> {
+ let (val, ok) = match (success, failure) {
(Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
(Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
(AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
(_, Release) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, AcqRel) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
+ };
+ if ok {
+ Ok(val)
+ } else {
+ Err(val)
}
}
old: T,
new: T,
success: Ordering,
- failure: Ordering) -> (T, bool)
+ failure: Ordering) -> Result<T, T>
where T: ::cmp::Eq + ::marker::Copy
{
- let result = atomic_compare_exchange(dst, old, new, success, failure);
- (result, result == old)
+ atomic_compare_exchange(dst, old, new, success, failure)
}
#[inline]
(_, name) if name.starts_with("atomic_") => {
let split: Vec<&str> = name.split('_').collect();
+ let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
let (order, failorder) = match split.len() {
2 => (llvm::SequentiallyConsistent, llvm::SequentiallyConsistent),
3 => match split[2] {
"acq" => (llvm::Acquire, llvm::Acquire),
"rel" => (llvm::Release, llvm::Monotonic),
"acqrel" => (llvm::AcquireRelease, llvm::Acquire),
- "failrelaxed" if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+ "failrelaxed" if is_cxchg =>
(llvm::SequentiallyConsistent, llvm::Monotonic),
- "failacq" if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+ "failacq" if is_cxchg =>
(llvm::SequentiallyConsistent, llvm::Acquire),
_ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
},
4 => match (split[2], split[3]) {
- ("acq", "failrelaxed") if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+ ("acq", "failrelaxed") if is_cxchg =>
(llvm::Acquire, llvm::Monotonic),
- ("acqrel", "failrelaxed") if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+ ("acqrel", "failrelaxed") if is_cxchg =>
(llvm::AcquireRelease, llvm::Monotonic),
_ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
},
};
match split[1] {
- "cxchg" => {
+ "cxchg" | "cxchgweak" => {
let cmp = from_immediate(bcx, llargs[1]);
let src = from_immediate(bcx, llargs[2]);
let ptr = PointerCast(bcx, llargs[0], val_ty(src).ptr_to());
- let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, llvm::False);
- ExtractValue(bcx, res, 0)
- }
-
- "cxchgweak" => {
- let cmp = from_immediate(bcx, llargs[1]);
- let src = from_immediate(bcx, llargs[2]);
- let ptr = PointerCast(bcx, llargs[0], val_ty(src).ptr_to());
- let val = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, llvm::True);
+ let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
+ let val = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, weak);
let result = ExtractValue(bcx, val, 0);
let success = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
- Store(bcx, result, StructGEP(bcx, llresult, 0));
+ Store(bcx,
+ result,
+ PointerCast(bcx, StructGEP(bcx, llresult, 0), val_ty(src).ptr_to()));
Store(bcx, success, StructGEP(bcx, llresult, 1));
C_nil(ccx)
}
}
to_immediate(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
}
+
"store" => {
let val = from_immediate(bcx, llargs[1]);
let ptr = PointerCast(bcx, llargs[0], val_ty(val).ptr_to());
fn main() {
// Make sure trans can emit all the intrinsics correctly
- ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed);
- ATOMIC.compare_exchange(0, 1, Acquire, Relaxed);
- ATOMIC.compare_exchange(0, 1, Release, Relaxed);
- ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed);
- ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed);
- ATOMIC.compare_exchange(0, 1, Acquire, Acquire);
- ATOMIC.compare_exchange(0, 1, AcqRel, Acquire);
- ATOMIC.compare_exchange(0, 1, SeqCst, Acquire);
- ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst);
- ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed);
- ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed);
- ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed);
- ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed);
- ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed);
- ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire);
- ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire);
- ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire);
- ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst);
+ ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok();
+ ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok();
+ ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok();
+ ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok();
+ ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
+ ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
+ ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
+ ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
+ ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();
+ ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok();
+ ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok();
+ ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok();
+ ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
+ ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
+ ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
+ ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
+ ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
+ ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}