Skip to content

Commit 8492b6a

Browse files
committed
Auto merge of #33579 - Amanieu:atomic_bool2, r=alexcrichton
Make AtomicBool the same size as bool Reopening #32365 This allows `AtomicBool` to be transmuted to a `bool`, which makes it more consistent with the other atomic types. Note that this now guarantees that the atomic type will always contain a valid `bool` value, which wasn't the case before (due to `fetch_nand`). r? @alexcrichton
2 parents 5029a60 + 915fa57 commit 8492b6a

File tree

1 file changed

+36
-58
lines changed

1 file changed

+36
-58
lines changed

src/libcore/sync/atomic.rs

+36-58
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,22 @@ use default::Default;
8383
use fmt;
8484

8585
/// A boolean type which can be safely shared between threads.
86-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
86+
#[cfg(any(stage0, target_has_atomic = "8"))]
8787
#[stable(feature = "rust1", since = "1.0.0")]
8888
pub struct AtomicBool {
89-
v: UnsafeCell<usize>,
89+
v: UnsafeCell<u8>,
9090
}
9191

92-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
92+
#[cfg(any(stage0, target_has_atomic = "8"))]
9393
#[stable(feature = "rust1", since = "1.0.0")]
9494
impl Default for AtomicBool {
9595
fn default() -> Self {
96-
Self::new(Default::default())
96+
Self::new(false)
9797
}
9898
}
9999

100100
// Send is implicitly implemented for AtomicBool.
101-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
101+
#[cfg(any(stage0, target_has_atomic = "8"))]
102102
#[stable(feature = "rust1", since = "1.0.0")]
103103
unsafe impl Sync for AtomicBool {}
104104

@@ -162,15 +162,11 @@ pub enum Ordering {
162162
}
163163

164164
/// An `AtomicBool` initialized to `false`.
165-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
165+
#[cfg(any(stage0, target_has_atomic = "8"))]
166166
#[stable(feature = "rust1", since = "1.0.0")]
167167
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
168168

169-
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
170-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
171-
const UINT_TRUE: usize = !0;
172-
173-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
169+
#[cfg(any(stage0, target_has_atomic = "8"))]
174170
impl AtomicBool {
175171
/// Creates a new `AtomicBool`.
176172
///
@@ -185,7 +181,7 @@ impl AtomicBool {
185181
#[inline]
186182
#[stable(feature = "rust1", since = "1.0.0")]
187183
pub const fn new(v: bool) -> AtomicBool {
188-
AtomicBool { v: UnsafeCell::new(-(v as isize) as usize) }
184+
AtomicBool { v: UnsafeCell::new(v as u8) }
189185
}
190186

191187
/// Loads a value from the bool.
@@ -208,7 +204,7 @@ impl AtomicBool {
208204
#[inline]
209205
#[stable(feature = "rust1", since = "1.0.0")]
210206
pub fn load(&self, order: Ordering) -> bool {
211-
unsafe { atomic_load(self.v.get(), order) > 0 }
207+
unsafe { atomic_load(self.v.get(), order) != 0 }
212208
}
213209

214210
/// Stores a value into the bool.
@@ -232,9 +228,7 @@ impl AtomicBool {
232228
#[inline]
233229
#[stable(feature = "rust1", since = "1.0.0")]
234230
pub fn store(&self, val: bool, order: Ordering) {
235-
let val = if val { UINT_TRUE } else { 0 };
236-
237-
unsafe { atomic_store(self.v.get(), val, order); }
231+
unsafe { atomic_store(self.v.get(), val as u8, order); }
238232
}
239233

240234
/// Stores a value into the bool, returning the old value.
@@ -254,9 +248,7 @@ impl AtomicBool {
254248
#[inline]
255249
#[stable(feature = "rust1", since = "1.0.0")]
256250
pub fn swap(&self, val: bool, order: Ordering) -> bool {
257-
let val = if val { UINT_TRUE } else { 0 };
258-
259-
unsafe { atomic_swap(self.v.get(), val, order) > 0 }
251+
unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
260252
}
261253

262254
/// Stores a value into the `bool` if the current value is the same as the `current` value.
@@ -327,12 +319,10 @@ impl AtomicBool {
327319
new: bool,
328320
success: Ordering,
329321
failure: Ordering) -> Result<bool, bool> {
330-
let current = if current { UINT_TRUE } else { 0 };
331-
let new = if new { UINT_TRUE } else { 0 };
332-
333-
match unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } {
334-
Ok(x) => Ok(x > 0),
335-
Err(x) => Err(x > 0),
322+
match unsafe { atomic_compare_exchange(self.v.get(), current as u8, new as u8,
323+
success, failure) } {
324+
Ok(x) => Ok(x != 0),
325+
Err(x) => Err(x != 0),
336326
}
337327
}
338328

@@ -373,13 +363,10 @@ impl AtomicBool {
373363
new: bool,
374364
success: Ordering,
375365
failure: Ordering) -> Result<bool, bool> {
376-
let current = if current { UINT_TRUE } else { 0 };
377-
let new = if new { UINT_TRUE } else { 0 };
378-
379-
match unsafe { atomic_compare_exchange_weak(self.v.get(), current, new,
366+
match unsafe { atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8,
380367
success, failure) } {
381-
Ok(x) => Ok(x > 0),
382-
Err(x) => Err(x > 0),
368+
Ok(x) => Ok(x != 0),
369+
Err(x) => Err(x != 0),
383370
}
384371
}
385372

@@ -410,9 +397,7 @@ impl AtomicBool {
410397
#[inline]
411398
#[stable(feature = "rust1", since = "1.0.0")]
412399
pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
413-
let val = if val { UINT_TRUE } else { 0 };
414-
415-
unsafe { atomic_and(self.v.get(), val, order) > 0 }
400+
unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
416401
}
417402

418403
/// Logical "nand" with a boolean value.
@@ -443,9 +428,20 @@ impl AtomicBool {
443428
#[inline]
444429
#[stable(feature = "rust1", since = "1.0.0")]
445430
pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
446-
let val = if val { UINT_TRUE } else { 0 };
447-
448-
unsafe { atomic_nand(self.v.get(), val, order) > 0 }
431+
// We can't use atomic_nand here because it can result in a bool with
432+
// an invalid value. This happens because the atomic operation is done
433+
// with an 8-bit integer internally, which would set the upper 7 bits.
434+
// So we just use a compare-exchange loop instead, which is what the
435+
// intrinsic actually expands to anyways on many platforms.
436+
let mut old = self.load(Relaxed);
437+
loop {
438+
let new = !(old && val);
439+
match self.compare_exchange_weak(old, new, order, Relaxed) {
440+
Ok(_) => break,
441+
Err(x) => old = x,
442+
}
443+
}
444+
old
449445
}
450446

451447
/// Logical "or" with a boolean value.
@@ -475,9 +471,7 @@ impl AtomicBool {
475471
#[inline]
476472
#[stable(feature = "rust1", since = "1.0.0")]
477473
pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
478-
let val = if val { UINT_TRUE } else { 0 };
479-
480-
unsafe { atomic_or(self.v.get(), val, order) > 0 }
474+
unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
481475
}
482476

483477
/// Logical "xor" with a boolean value.
@@ -507,9 +501,7 @@ impl AtomicBool {
507501
#[inline]
508502
#[stable(feature = "rust1", since = "1.0.0")]
509503
pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
510-
let val = if val { UINT_TRUE } else { 0 };
511-
512-
unsafe { atomic_xor(self.v.get(), val, order) > 0 }
504+
unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
513505
}
514506
}
515507

@@ -1263,18 +1255,6 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
12631255
}
12641256
}
12651257

1266-
#[inline]
1267-
unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
1268-
match order {
1269-
Acquire => intrinsics::atomic_nand_acq(dst, val),
1270-
Release => intrinsics::atomic_nand_rel(dst, val),
1271-
AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
1272-
Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
1273-
SeqCst => intrinsics::atomic_nand(dst, val)
1274-
}
1275-
}
1276-
1277-
12781258
#[inline]
12791259
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
12801260
match order {
@@ -1286,7 +1266,6 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
12861266
}
12871267
}
12881268

1289-
12901269
#[inline]
12911270
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
12921271
match order {
@@ -1298,7 +1277,6 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
12981277
}
12991278
}
13001279

1301-
13021280
/// An atomic fence.
13031281
///
13041282
/// A fence 'A' which has `Release` ordering semantics, synchronizes with a
@@ -1334,7 +1312,7 @@ pub fn fence(order: Ordering) {
13341312
}
13351313

13361314

1337-
#[cfg(any(stage0, target_has_atomic = "ptr"))]
1315+
#[cfg(any(stage0, target_has_atomic = "8"))]
13381316
#[stable(feature = "atomic_debug", since = "1.3.0")]
13391317
impl fmt::Debug for AtomicBool {
13401318
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

0 commit comments

Comments
 (0)