@@ -5,15 +5,16 @@ use core::time::Duration;
5
5
6
6
use std:: cell:: RefCell ;
7
7
8
- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
9
- use std:: sync:: Condvar as StdCondvar ;
10
- use std:: sync:: Mutex as StdMutex ;
11
- use std:: sync:: MutexGuard as StdMutexGuard ;
8
+ use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
12
9
use std:: sync:: RwLock as StdRwLock ;
13
10
use std:: sync:: RwLockReadGuard as StdRwLockReadGuard ;
14
11
use std:: sync:: RwLockWriteGuard as StdRwLockWriteGuard ;
15
12
16
- pub use std:: sync:: WaitTimeoutResult ;
13
+ use parking_lot:: Condvar as StdCondvar ;
14
+ use parking_lot:: Mutex as StdMutex ;
15
+ use parking_lot:: MutexGuard as StdMutexGuard ;
16
+
17
+ pub use parking_lot:: WaitTimeoutResult ;
17
18
18
19
use crate :: prelude:: * ;
19
20
@@ -46,21 +47,19 @@ impl Condvar {
46
47
& ' a self , guard : MutexGuard < ' a , T > , condition : F ,
47
48
) -> LockResult < MutexGuard < ' a , T > > {
48
49
let mutex: & ' a Mutex < T > = guard. mutex ;
49
- self . inner
50
- . wait_while ( guard. into_inner ( ) , condition)
51
- . map ( |lock| MutexGuard { mutex, lock } )
52
- . map_err ( |_| ( ) )
50
+ let mut lock = guard. into_inner ( ) ;
51
+ self . inner . wait_while ( & mut lock, condition) ;
52
+ Ok ( MutexGuard { mutex, lock : Some ( lock) } )
53
53
}
54
54
55
55
#[ allow( unused) ]
56
56
pub fn wait_timeout_while < ' a , T , F : FnMut ( & mut T ) -> bool > (
57
57
& ' a self , guard : MutexGuard < ' a , T > , dur : Duration , condition : F ,
58
58
) -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
59
59
let mutex = guard. mutex ;
60
- self . inner
61
- . wait_timeout_while ( guard. into_inner ( ) , dur, condition)
62
- . map_err ( |_| ( ) )
63
- . map ( |( lock, e) | ( MutexGuard { mutex, lock } , e) )
60
+ let mut lock = guard. into_inner ( ) ;
61
+ let e = self . inner . wait_while_for ( & mut lock, condition, dur) ;
62
+ Ok ( ( MutexGuard { mutex, lock : Some ( lock) } , e) )
64
63
}
65
64
66
65
pub fn notify_all ( & self ) {
@@ -150,7 +149,7 @@ impl LockMetadata {
150
149
LOCKS_INIT . call_once ( || unsafe {
151
150
LOCKS = Some ( StdMutex :: new ( new_hash_map ( ) ) ) ;
152
151
} ) ;
153
- let mut locks = unsafe { LOCKS . as_ref ( ) } . unwrap ( ) . lock ( ) . unwrap ( ) ;
152
+ let mut locks = unsafe { LOCKS . as_ref ( ) } . unwrap ( ) . lock ( ) ;
154
153
match locks. entry ( lock_constr_location) {
155
154
hash_map:: Entry :: Occupied ( e) => {
156
155
assert_eq ! ( lock_constr_colno,
@@ -185,7 +184,7 @@ impl LockMetadata {
185
184
}
186
185
}
187
186
for ( _locked_idx, locked) in held. borrow ( ) . iter ( ) {
188
- for ( locked_dep_idx, _locked_dep) in locked. locked_before . lock ( ) . unwrap ( ) . iter ( ) {
187
+ for ( locked_dep_idx, _locked_dep) in locked. locked_before . lock ( ) . iter ( ) {
189
188
let is_dep_this_lock = * locked_dep_idx == this. lock_idx ;
190
189
let has_same_construction = * locked_dep_idx == locked. lock_idx ;
191
190
if is_dep_this_lock && !has_same_construction {
@@ -210,7 +209,7 @@ impl LockMetadata {
210
209
}
211
210
}
212
211
// Insert any already-held locks in our locked-before set.
213
- let mut locked_before = this. locked_before . lock ( ) . unwrap ( ) ;
212
+ let mut locked_before = this. locked_before . lock ( ) ;
214
213
if !locked_before. contains_key ( & locked. lock_idx ) {
215
214
let lockdep = LockDep { lock : Arc :: clone ( locked) , _lockdep_trace : Backtrace :: new ( ) } ;
216
215
locked_before. insert ( lockdep. lock . lock_idx , lockdep) ;
@@ -237,7 +236,7 @@ impl LockMetadata {
237
236
// Since a try-lock will simply fail if the lock is held already, we do not
238
237
// consider try-locks to ever generate lockorder inversions. However, if a try-lock
239
238
// succeeds, we do consider it to have created lockorder dependencies.
240
- let mut locked_before = this. locked_before . lock ( ) . unwrap ( ) ;
239
+ let mut locked_before = this. locked_before . lock ( ) ;
241
240
for ( locked_idx, locked) in held. borrow ( ) . iter ( ) {
242
241
if !locked_before. contains_key ( locked_idx) {
243
242
let lockdep =
@@ -252,11 +251,17 @@ impl LockMetadata {
252
251
253
252
pub struct Mutex < T : Sized > {
254
253
inner : StdMutex < T > ,
254
+ poisoned : AtomicBool ,
255
255
deps : Arc < LockMetadata > ,
256
256
}
257
+
257
258
impl < T : Sized > Mutex < T > {
258
259
pub ( crate ) fn into_inner ( self ) -> LockResult < T > {
259
- self . inner . into_inner ( ) . map_err ( |_| ( ) )
260
+ if self . poisoned . load ( Ordering :: Acquire ) {
261
+ Err ( ( ) )
262
+ } else {
263
+ Ok ( self . inner . into_inner ( ) )
264
+ }
260
265
}
261
266
}
262
267
@@ -278,14 +283,14 @@ impl<T: Sized + fmt::Debug> fmt::Debug for Mutex<T> {
278
283
#[ must_use = "if unused the Mutex will immediately unlock" ]
279
284
pub struct MutexGuard < ' a , T : Sized + ' a > {
280
285
mutex : & ' a Mutex < T > ,
281
- lock : StdMutexGuard < ' a , T > ,
286
+ lock : Option < StdMutexGuard < ' a , T > > ,
282
287
}
283
288
284
289
impl < ' a , T : Sized > MutexGuard < ' a , T > {
285
290
fn into_inner ( self ) -> StdMutexGuard < ' a , T > {
286
291
// Somewhat unclear why we cannot move out of self.lock, but doing so gets E0509.
287
292
unsafe {
288
- let v: StdMutexGuard < ' a , T > = std:: ptr:: read ( & self . lock ) ;
293
+ let v: StdMutexGuard < ' a , T > = std:: ptr:: read ( self . lock . as_ref ( ) . unwrap ( ) ) ;
289
294
std:: mem:: forget ( self ) ;
290
295
v
291
296
}
@@ -297,44 +302,63 @@ impl<T: Sized> Drop for MutexGuard<'_, T> {
297
302
LOCKS_HELD . with ( |held| {
298
303
held. borrow_mut ( ) . remove ( & self . mutex . deps . lock_idx ) ;
299
304
} ) ;
305
+ if std:: thread:: panicking ( ) {
306
+ self . mutex . poisoned . store ( true , Ordering :: Release ) ;
307
+ }
308
+ StdMutexGuard :: unlock_fair ( self . lock . take ( ) . unwrap ( ) ) ;
300
309
}
301
310
}
302
311
303
312
impl < T : Sized > Deref for MutexGuard < ' _ , T > {
304
313
type Target = T ;
305
314
306
315
fn deref ( & self ) -> & T {
307
- & self . lock . deref ( )
316
+ & self . lock . as_ref ( ) . unwrap ( ) . deref ( )
308
317
}
309
318
}
310
319
311
320
impl < T : Sized > DerefMut for MutexGuard < ' _ , T > {
312
321
fn deref_mut ( & mut self ) -> & mut T {
313
- self . lock . deref_mut ( )
322
+ self . lock . as_mut ( ) . unwrap ( ) . deref_mut ( )
314
323
}
315
324
}
316
325
317
326
impl < T > Mutex < T > {
318
327
pub fn new ( inner : T ) -> Mutex < T > {
319
- Mutex { inner : StdMutex :: new ( inner) , deps : LockMetadata :: new ( ) }
328
+ Mutex {
329
+ inner : StdMutex :: new ( inner) ,
330
+ poisoned : AtomicBool :: new ( false ) ,
331
+ deps : LockMetadata :: new ( ) ,
332
+ }
320
333
}
321
334
322
335
pub fn lock < ' a > ( & ' a self ) -> LockResult < MutexGuard < ' a , T > > {
323
336
LockMetadata :: pre_lock ( & self . deps , false ) ;
324
- self . inner . lock ( ) . map ( |lock| MutexGuard { mutex : self , lock } ) . map_err ( |_| ( ) )
337
+ let lock = self . inner . lock ( ) ;
338
+ if self . poisoned . load ( Ordering :: Acquire ) {
339
+ Err ( ( ) )
340
+ } else {
341
+ Ok ( MutexGuard { mutex : self , lock : Some ( lock) } )
342
+ }
325
343
}
326
344
327
345
pub fn try_lock < ' a > ( & ' a self ) -> LockResult < MutexGuard < ' a , T > > {
328
- let res =
329
- self . inner . try_lock ( ) . map ( |lock| MutexGuard { mutex : self , lock } ) . map_err ( |_| ( ) ) ;
346
+ let res = self . inner . try_lock ( ) . ok_or ( ( ) ) ;
330
347
if res. is_ok ( ) {
348
+ if self . poisoned . load ( Ordering :: Acquire ) {
349
+ return Err ( ( ) ) ;
350
+ }
331
351
LockMetadata :: try_locked ( & self . deps ) ;
332
352
}
333
- res
353
+ res. map ( |lock| MutexGuard { mutex : self , lock : Some ( lock ) } )
334
354
}
335
355
336
356
pub fn get_mut < ' a > ( & ' a mut self ) -> LockResult < & ' a mut T > {
337
- self . inner . get_mut ( ) . map_err ( |_| ( ) )
357
+ if self . poisoned . load ( Ordering :: Acquire ) {
358
+ Err ( ( ) )
359
+ } else {
360
+ Ok ( self . inner . get_mut ( ) )
361
+ }
338
362
}
339
363
}
340
364
@@ -345,9 +369,10 @@ impl<'a, T: 'a> LockTestExt<'a> for Mutex<T> {
345
369
}
346
370
type ExclLock = MutexGuard < ' a , T > ;
347
371
#[ inline]
348
- fn unsafe_well_ordered_double_lock_self ( & ' a self ) -> MutexGuard < T > {
372
+ fn unsafe_well_ordered_double_lock_self ( & ' a self ) -> MutexGuard < ' a , T > {
349
373
LockMetadata :: pre_lock ( & self . deps , true ) ;
350
- self . inner . lock ( ) . map ( |lock| MutexGuard { mutex : self , lock } ) . unwrap ( )
374
+ let lock = self . inner . lock ( ) ;
375
+ MutexGuard { mutex : self , lock : Some ( lock) }
351
376
}
352
377
}
353
378
0 commit comments