1
1
use fmt;
2
2
use sync:: atomic:: { AtomicUsize , Ordering } ;
3
- use sync:: { mutex , MutexGuard , PoisonError } ;
4
- use sys_common:: condvar as sys;
3
+ use sync:: { MutexGuard , PoisonError } ;
4
+ use sys_common:: { condvar as sys, AsInner } ;
5
5
use sys_common:: mutex as sys_mutex;
6
6
use sys_common:: poison:: { self , LockResult } ;
7
7
use time:: { Duration , Instant } ;
@@ -198,16 +198,11 @@ impl Condvar {
198
198
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
199
199
pub fn wait < ' a , T > ( & self , guard : MutexGuard < ' a , T > )
200
200
-> LockResult < MutexGuard < ' a , T > > {
201
- let poisoned = unsafe {
202
- let lock = mutex:: guard_lock ( & guard) ;
203
- self . verify ( lock) ;
204
- self . inner . wait ( lock) ;
205
- mutex:: guard_poison ( & guard) . get ( )
206
- } ;
207
- if poisoned {
208
- Err ( PoisonError :: new ( guard) )
209
- } else {
210
- Ok ( guard)
201
+ unsafe {
202
+ let lock = MutexGuard :: into_mutex ( guard) ;
203
+ self . verify ( lock. as_inner ( ) ) ;
204
+ self . inner . wait ( lock. as_inner ( ) ) ;
205
+ MutexGuard :: new ( lock)
211
206
}
212
207
}
213
208
@@ -399,16 +394,15 @@ impl Condvar {
399
394
pub fn wait_timeout < ' a , T > ( & self , guard : MutexGuard < ' a , T > ,
400
395
dur : Duration )
401
396
-> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
402
- let ( poisoned , result) = unsafe {
403
- let lock = mutex :: guard_lock ( & guard) ;
404
- self . verify ( lock) ;
405
- let success = self . inner . wait_timeout ( lock, dur) ;
406
- ( mutex :: guard_poison ( & guard ) . get ( ) , WaitTimeoutResult ( !success) )
397
+ let ( guard , result) = unsafe {
398
+ let lock = MutexGuard :: into_mutex ( guard) ;
399
+ self . verify ( lock. as_inner ( ) ) ;
400
+ let success = self . inner . wait_timeout ( lock. as_inner ( ) , dur) ;
401
+ ( MutexGuard :: new ( lock ) , WaitTimeoutResult ( !success) )
407
402
} ;
408
- if poisoned {
409
- Err ( PoisonError :: new ( ( guard, result) ) )
410
- } else {
411
- Ok ( ( guard, result) )
403
+ match guard {
404
+ Ok ( g) => Ok ( ( g, result) ) ,
405
+ Err ( p) => Err ( PoisonError :: new ( ( p. into_inner ( ) , result) ) )
412
406
}
413
407
}
414
408
@@ -568,7 +562,10 @@ impl Condvar {
568
562
unsafe { self . inner . notify_all ( ) }
569
563
}
570
564
571
- fn verify ( & self , mutex : & sys_mutex:: Mutex ) {
565
+ /// # Safety
566
+ ///
567
+ /// The mutex must be locked when passed to this function.
568
+ unsafe fn verify ( & self , mutex : & sys_mutex:: Mutex ) {
572
569
let addr = mutex as * const _ as usize ;
573
570
match self . mutex . compare_and_swap ( 0 , addr, Ordering :: SeqCst ) {
574
571
// If we got out 0, then we have successfully bound the mutex to
@@ -581,8 +578,12 @@ impl Condvar {
581
578
582
579
// Anything else and we're using more than one mutex on this cvar,
583
580
// which is currently disallowed.
584
- _ => panic ! ( "attempted to use a condition variable with two \
585
- mutexes") ,
581
+ _ => {
582
+ // unlock the mutex before panicking
583
+ mutex. raw_unlock ( ) ;
584
+ panic ! ( "attempted to use a condition variable with two \
585
+ mutexes")
586
+ }
586
587
}
587
588
}
588
589
}
0 commit comments