]> git.lizzy.rs Git - rust.git/commitdiff
Make AtomicBool the same size as bool
authorAmanieu d'Antras <amanieu@gmail.com>
Thu, 12 May 2016 15:12:05 +0000 (16:12 +0100)
committerAmanieu d'Antras <amanieu@gmail.com>
Fri, 13 May 2016 16:54:06 +0000 (17:54 +0100)
src/libcore/sync/atomic.rs

index cf3e45cf3de79baf85a79adc15b4121353477a1c..49b923286d88894c3d9ba347378675680a6886d5 100644 (file)
 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 {