Skip to content

Commit 6b9289c

Browse files
committed
Optimize poison guards to ZSTs when panic=abort
1 parent 03d488b commit 6b9289c

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

library/std/src/sync/poison.rs

+49-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use crate::error::Error;
22
use crate::fmt;
3+
4+
#[cfg(panic = "unwind")]
35
use crate::sync::atomic::{AtomicBool, Ordering};
6+
#[cfg(panic = "unwind")]
47
use crate::thread;
58

69
pub struct Flag {
10+
#[cfg(panic = "unwind")]
711
failed: AtomicBool,
812
}
913

@@ -21,7 +25,10 @@ pub struct Flag {
2125
impl Flag {
2226
#[inline]
2327
pub const fn new() -> Flag {
24-
Flag { failed: AtomicBool::new(false) }
28+
Flag {
29+
#[cfg(panic = "unwind")]
30+
failed: AtomicBool::new(false),
31+
}
2532
}
2633

2734
/// Check the flag for an unguarded borrow, where we only care about existing poison.
@@ -33,29 +40,46 @@ impl Flag {
3340
/// Check the flag for a guarded borrow, where we may also set poison when `done`.
3441
#[inline]
3542
pub fn guard(&self) -> LockResult<Guard> {
36-
let ret = Guard { panicking: thread::panicking() };
43+
let ret = Guard {
44+
#[cfg(panic = "unwind")]
45+
panicking: thread::panicking(),
46+
};
3747
if self.get() { Err(PoisonError::new(ret)) } else { Ok(ret) }
3848
}
3949

4050
#[inline]
51+
#[cfg(panic = "unwind")]
4152
pub fn done(&self, guard: &Guard) {
4253
if !guard.panicking && thread::panicking() {
4354
self.failed.store(true, Ordering::Relaxed);
4455
}
4556
}
4657

4758
#[inline]
59+
#[cfg(not(panic = "unwind"))]
60+
pub fn done(&self, _guard: &Guard) {}
61+
62+
#[inline]
63+
#[cfg(panic = "unwind")]
4864
pub fn get(&self) -> bool {
4965
self.failed.load(Ordering::Relaxed)
5066
}
5167

68+
#[inline(always)]
69+
#[cfg(not(panic = "unwind"))]
70+
pub fn get(&self) -> bool {
71+
false
72+
}
73+
5274
#[inline]
5375
pub fn clear(&self) {
76+
#[cfg(panic = "unwind")]
5477
self.failed.store(false, Ordering::Relaxed)
5578
}
5679
}
5780

5881
pub struct Guard {
82+
#[cfg(panic = "unwind")]
5983
panicking: bool,
6084
}
6185

@@ -95,6 +119,8 @@ pub struct Guard {
95119
#[stable(feature = "rust1", since = "1.0.0")]
96120
pub struct PoisonError<T> {
97121
guard: T,
122+
#[cfg(not(panic = "unwind"))]
123+
_never: !,
98124
}
99125

100126
/// An enumeration of possible errors associated with a [`TryLockResult`] which
@@ -165,11 +191,27 @@ impl<T> PoisonError<T> {
165191
///
166192
/// This is generally created by methods like [`Mutex::lock`](crate::sync::Mutex::lock)
167193
/// or [`RwLock::read`](crate::sync::RwLock::read).
194+
///
195+
/// This method may panic if std was built with `panic="abort"`.
196+
#[cfg(panic = "unwind")]
168197
#[stable(feature = "sync_poison", since = "1.2.0")]
169198
pub fn new(guard: T) -> PoisonError<T> {
170199
PoisonError { guard }
171200
}
172201

202+
/// Creates a `PoisonError`.
203+
///
204+
/// This is generally created by methods like [`Mutex::lock`](crate::sync::Mutex::lock)
205+
/// or [`RwLock::read`](crate::sync::RwLock::read).
206+
///
207+
/// This method may panic if std was built with `panic="abort"`.
208+
#[cfg(not(panic = "unwind"))]
209+
#[stable(feature = "sync_poison", since = "1.2.0")]
210+
#[track_caller]
211+
pub fn new(_guard: T) -> PoisonError<T> {
212+
panic!("PoisonError created in a libstd built with panic=\"abort\"")
213+
}
214+
173215
/// Consumes this error indicating that a lock is poisoned, returning the
174216
/// underlying guard to allow access regardless.
175217
///
@@ -225,6 +267,7 @@ impl<T> From<PoisonError<T>> for TryLockError<T> {
225267
impl<T> fmt::Debug for TryLockError<T> {
226268
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227269
match *self {
270+
#[cfg(panic = "unwind")]
228271
TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
229272
TryLockError::WouldBlock => "WouldBlock".fmt(f),
230273
}
@@ -235,6 +278,7 @@ impl<T> fmt::Debug for TryLockError<T> {
235278
impl<T> fmt::Display for TryLockError<T> {
236279
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237280
match *self {
281+
#[cfg(panic = "unwind")]
238282
TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
239283
TryLockError::WouldBlock => "try_lock failed because the operation would block",
240284
}
@@ -247,6 +291,7 @@ impl<T> Error for TryLockError<T> {
247291
#[allow(deprecated, deprecated_in_future)]
248292
fn description(&self) -> &str {
249293
match *self {
294+
#[cfg(panic = "unwind")]
250295
TryLockError::Poisoned(ref p) => p.description(),
251296
TryLockError::WouldBlock => "try_lock failed because the operation would block",
252297
}
@@ -255,6 +300,7 @@ impl<T> Error for TryLockError<T> {
255300
#[allow(deprecated)]
256301
fn cause(&self) -> Option<&dyn Error> {
257302
match *self {
303+
#[cfg(panic = "unwind")]
258304
TryLockError::Poisoned(ref p) => Some(p),
259305
_ => None,
260306
}
@@ -267,6 +313,7 @@ where
267313
{
268314
match result {
269315
Ok(t) => Ok(f(t)),
316+
#[cfg(panic = "unwind")]
270317
Err(PoisonError { guard }) => Err(PoisonError::new(f(guard))),
271318
}
272319
}

0 commit comments

Comments
 (0)