Make AtomicBool the same size as bool

This commit is contained in:
Amanieu d'Antras 2016-05-12 16:12:05 +01:00
parent e37f8593e4
commit 915fa57a93

View File

@ -83,22 +83,22 @@
use fmt;
/// A boolean type which can be safely shared between threads.
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct AtomicBool {
v: UnsafeCell<usize>,
v: UnsafeCell<u8>,
}
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for AtomicBool {
fn default() -> Self {
Self::new(Default::default())
Self::new(false)
}
}
// Send is implicitly implemented for AtomicBool.
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl Sync for AtomicBool {}
@ -162,15 +162,11 @@ pub enum Ordering {
}
/// An `AtomicBool` initialized to `false`.
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
#[stable(feature = "rust1", since = "1.0.0")]
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
#[cfg(any(stage0, target_has_atomic = "ptr"))]
const UINT_TRUE: usize = !0;
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
impl AtomicBool {
/// Creates a new `AtomicBool`.
///
@ -185,7 +181,7 @@ impl AtomicBool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn new(v: bool) -> AtomicBool {
AtomicBool { v: UnsafeCell::new(-(v as isize) as usize) }
AtomicBool { v: UnsafeCell::new(v as u8) }
}
/// Loads a value from the bool.
@ -208,7 +204,7 @@ pub const fn new(v: bool) -> AtomicBool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn load(&self, order: Ordering) -> bool {
unsafe { atomic_load(self.v.get(), order) > 0 }
unsafe { atomic_load(self.v.get(), order) != 0 }
}
/// Stores a value into the bool.
@ -232,9 +228,7 @@ pub fn load(&self, order: Ordering) -> bool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn store(&self, val: bool, order: Ordering) {
let val = if val { UINT_TRUE } else { 0 };
unsafe { atomic_store(self.v.get(), val, order); }
unsafe { atomic_store(self.v.get(), val as u8, order); }
}
/// Stores a value into the bool, returning the old value.
@ -254,9 +248,7 @@ pub fn store(&self, val: bool, order: Ordering) {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 }
unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
}
/// Stores a value into the `bool` if the current value is the same as the `current` value.
@ -327,12 +319,10 @@ pub fn compare_exchange(&self,
new: bool,
success: Ordering,
failure: Ordering) -> Result<bool, bool> {
let current = if current { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 };
match unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } {
Ok(x) => Ok(x > 0),
Err(x) => Err(x > 0),
match unsafe { atomic_compare_exchange(self.v.get(), current as u8, new as u8,
success, failure) } {
Ok(x) => Ok(x != 0),
Err(x) => Err(x != 0),
}
}
@ -373,13 +363,10 @@ pub fn compare_exchange_weak(&self,
new: bool,
success: Ordering,
failure: Ordering) -> Result<bool, bool> {
let current = if current { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 };
match unsafe { atomic_compare_exchange_weak(self.v.get(), current, new,
match unsafe { atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8,
success, failure) } {
Ok(x) => Ok(x > 0),
Err(x) => Err(x > 0),
Ok(x) => Ok(x != 0),
Err(x) => Err(x != 0),
}
}
@ -410,9 +397,7 @@ pub fn compare_exchange_weak(&self,
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 }
unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
}
/// Logical "nand" with a boolean value.
@ -443,9 +428,20 @@ pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 }
// We can't use atomic_nand here because it can result in a bool with
// an invalid value. This happens because the atomic operation is done
// with an 8-bit integer internally, which would set the upper 7 bits.
// So we just use a compare-exchange loop instead, which is what the
// intrinsic actually expands to anyways on many platforms.
let mut old = self.load(Relaxed);
loop {
let new = !(old && val);
match self.compare_exchange_weak(old, new, order, Relaxed) {
Ok(_) => break,
Err(x) => old = x,
}
}
old
}
/// Logical "or" with a boolean value.
@ -475,9 +471,7 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 }
unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
}
/// Logical "xor" with a boolean value.
@ -507,9 +501,7 @@ pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 }
unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
}
}
@ -1263,18 +1255,6 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
}
#[inline]
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),
SeqCst => intrinsics::atomic_nand(dst, val)
}
}
#[inline]
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
@ -1286,7 +1266,6 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
}
#[inline]
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
@ -1298,7 +1277,6 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
}
/// An atomic fence.
///
/// A fence 'A' which has `Release` ordering semantics, synchronizes with a
@ -1334,7 +1312,7 @@ pub fn fence(order: Ordering) {
}
#[cfg(any(stage0, target_has_atomic = "ptr"))]
#[cfg(any(stage0, target_has_atomic = "8"))]
#[stable(feature = "atomic_debug", since = "1.3.0")]
impl fmt::Debug for AtomicBool {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {