1
1
use crate :: error:: Error ;
2
2
use crate :: fmt;
3
+
4
+ #[ cfg( panic = "unwind" ) ]
3
5
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
6
+ #[ cfg( panic = "unwind" ) ]
4
7
use crate :: thread;
5
8
6
9
pub struct Flag {
10
+ #[ cfg( panic = "unwind" ) ]
7
11
failed : AtomicBool ,
8
12
}
9
13
@@ -21,7 +25,10 @@ pub struct Flag {
21
25
impl Flag {
22
26
#[ inline]
23
27
pub const fn new ( ) -> Flag {
24
- Flag { failed : AtomicBool :: new ( false ) }
28
+ Flag {
29
+ #[ cfg( panic = "unwind" ) ]
30
+ failed : AtomicBool :: new ( false ) ,
31
+ }
25
32
}
26
33
27
34
/// Check the flag for an unguarded borrow, where we only care about existing poison.
@@ -33,29 +40,46 @@ impl Flag {
33
40
/// Check the flag for a guarded borrow, where we may also set poison when `done`.
34
41
#[ inline]
35
42
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
+ } ;
37
47
if self . get ( ) { Err ( PoisonError :: new ( ret) ) } else { Ok ( ret) }
38
48
}
39
49
40
50
#[ inline]
51
+ #[ cfg( panic = "unwind" ) ]
41
52
pub fn done ( & self , guard : & Guard ) {
42
53
if !guard. panicking && thread:: panicking ( ) {
43
54
self . failed . store ( true , Ordering :: Relaxed ) ;
44
55
}
45
56
}
46
57
47
58
#[ inline]
59
+ #[ cfg( not( panic = "unwind" ) ) ]
60
+ pub fn done ( & self , _guard : & Guard ) { }
61
+
62
+ #[ inline]
63
+ #[ cfg( panic = "unwind" ) ]
48
64
pub fn get ( & self ) -> bool {
49
65
self . failed . load ( Ordering :: Relaxed )
50
66
}
51
67
68
+ #[ inline( always) ]
69
+ #[ cfg( not( panic = "unwind" ) ) ]
70
+ pub fn get ( & self ) -> bool {
71
+ false
72
+ }
73
+
52
74
#[ inline]
53
75
pub fn clear ( & self ) {
76
+ #[ cfg( panic = "unwind" ) ]
54
77
self . failed . store ( false , Ordering :: Relaxed )
55
78
}
56
79
}
57
80
58
81
pub struct Guard {
82
+ #[ cfg( panic = "unwind" ) ]
59
83
panicking : bool ,
60
84
}
61
85
@@ -95,6 +119,8 @@ pub struct Guard {
95
119
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
96
120
pub struct PoisonError < T > {
97
121
guard : T ,
122
+ #[ cfg( not( panic = "unwind" ) ) ]
123
+ _never : !,
98
124
}
99
125
100
126
/// An enumeration of possible errors associated with a [`TryLockResult`] which
@@ -165,11 +191,27 @@ impl<T> PoisonError<T> {
165
191
///
166
192
/// This is generally created by methods like [`Mutex::lock`](crate::sync::Mutex::lock)
167
193
/// or [`RwLock::read`](crate::sync::RwLock::read).
194
+ ///
195
+ /// This method may panic if std was built with `panic="abort"`.
196
+ #[ cfg( panic = "unwind" ) ]
168
197
#[ stable( feature = "sync_poison" , since = "1.2.0" ) ]
169
198
pub fn new ( guard : T ) -> PoisonError < T > {
170
199
PoisonError { guard }
171
200
}
172
201
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
+
173
215
/// Consumes this error indicating that a lock is poisoned, returning the
174
216
/// underlying guard to allow access regardless.
175
217
///
@@ -225,6 +267,7 @@ impl<T> From<PoisonError<T>> for TryLockError<T> {
225
267
impl < T > fmt:: Debug for TryLockError < T > {
226
268
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
227
269
match * self {
270
+ #[ cfg( panic = "unwind" ) ]
228
271
TryLockError :: Poisoned ( ..) => "Poisoned(..)" . fmt ( f) ,
229
272
TryLockError :: WouldBlock => "WouldBlock" . fmt ( f) ,
230
273
}
@@ -235,6 +278,7 @@ impl<T> fmt::Debug for TryLockError<T> {
235
278
impl < T > fmt:: Display for TryLockError < T > {
236
279
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
237
280
match * self {
281
+ #[ cfg( panic = "unwind" ) ]
238
282
TryLockError :: Poisoned ( ..) => "poisoned lock: another task failed inside" ,
239
283
TryLockError :: WouldBlock => "try_lock failed because the operation would block" ,
240
284
}
@@ -247,6 +291,7 @@ impl<T> Error for TryLockError<T> {
247
291
#[ allow( deprecated, deprecated_in_future) ]
248
292
fn description ( & self ) -> & str {
249
293
match * self {
294
+ #[ cfg( panic = "unwind" ) ]
250
295
TryLockError :: Poisoned ( ref p) => p. description ( ) ,
251
296
TryLockError :: WouldBlock => "try_lock failed because the operation would block" ,
252
297
}
@@ -255,6 +300,7 @@ impl<T> Error for TryLockError<T> {
255
300
#[ allow( deprecated) ]
256
301
fn cause ( & self ) -> Option < & dyn Error > {
257
302
match * self {
303
+ #[ cfg( panic = "unwind" ) ]
258
304
TryLockError :: Poisoned ( ref p) => Some ( p) ,
259
305
_ => None ,
260
306
}
@@ -267,6 +313,7 @@ where
267
313
{
268
314
match result {
269
315
Ok ( t) => Ok ( f ( t) ) ,
316
+ #[ cfg( panic = "unwind" ) ]
270
317
Err ( PoisonError { guard } ) => Err ( PoisonError :: new ( f ( guard) ) ) ,
271
318
}
272
319
}
0 commit comments