@@ -51,7 +51,7 @@ use std::borrow;
51
51
/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
52
52
pub struct Condvar < ' a > {
53
53
priv is_mutex : bool ,
54
- priv failed : & ' a mut bool ,
54
+ priv failed : & ' a bool ,
55
55
priv cond : & ' a sync:: Condvar < ' a >
56
56
}
57
57
@@ -226,7 +226,7 @@ impl<T:Send> MutexArc<T> {
226
226
// not already unsafe. See borrow_rwlock, far below.
227
227
( & ( * state) . lock ) . lock ( || {
228
228
check_poison ( true , ( * state) . failed ) ;
229
- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
229
+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
230
230
blk ( & mut ( * state) . data )
231
231
} )
232
232
}
@@ -239,10 +239,10 @@ impl<T:Send> MutexArc<T> {
239
239
let state = self . x . get ( ) ;
240
240
( & ( * state) . lock ) . lock_cond ( |cond| {
241
241
check_poison ( true , ( * state) . failed ) ;
242
- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
242
+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
243
243
blk ( & mut ( * state) . data ,
244
244
& Condvar { is_mutex : true ,
245
- failed : & mut ( * state) . failed ,
245
+ failed : & ( * state) . failed ,
246
246
cond : cond } )
247
247
} )
248
248
}
@@ -311,24 +311,28 @@ fn check_poison(is_mutex: bool, failed: bool) {
311
311
312
312
#[ doc( hidden) ]
313
313
struct PoisonOnFail {
314
- failed : * mut bool ,
314
+ flag : * mut bool ,
315
+ failed : bool ,
315
316
}
316
317
317
318
impl Drop for PoisonOnFail {
318
319
fn drop ( & mut self ) {
319
320
unsafe {
320
321
/* assert!(!*self.failed);
321
322
-- might be false in case of cond.wait() */
322
- if task:: failing ( ) {
323
- * self . failed = true ;
323
+ if ! self . failed && task:: failing ( ) {
324
+ * self . flag = true ;
324
325
}
325
326
}
326
327
}
327
328
}
328
329
329
- fn PoisonOnFail < ' r > ( failed : & ' r mut bool ) -> PoisonOnFail {
330
- PoisonOnFail {
331
- failed : failed
330
+ impl PoisonOnFail {
331
+ fn new < ' a > ( flag : & ' a mut bool ) -> PoisonOnFail {
332
+ PoisonOnFail {
333
+ flag : flag,
334
+ failed : task:: failing ( )
335
+ }
332
336
}
333
337
}
334
338
@@ -392,7 +396,7 @@ impl<T:Freeze + Send> RWArc<T> {
392
396
let state = self . x . get ( ) ;
393
397
( * borrow_rwlock ( state) ) . write ( || {
394
398
check_poison ( false , ( * state) . failed ) ;
395
- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
399
+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
396
400
blk ( & mut ( * state) . data )
397
401
} )
398
402
}
@@ -407,10 +411,10 @@ impl<T:Freeze + Send> RWArc<T> {
407
411
let state = self . x . get ( ) ;
408
412
( * borrow_rwlock ( state) ) . write_cond ( |cond| {
409
413
check_poison ( false , ( * state) . failed ) ;
410
- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
414
+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
411
415
blk ( & mut ( * state) . data ,
412
416
& Condvar { is_mutex : false ,
413
- failed : & mut ( * state) . failed ,
417
+ failed : & ( * state) . failed ,
414
418
cond : cond} )
415
419
} )
416
420
}
@@ -463,7 +467,7 @@ impl<T:Freeze + Send> RWArc<T> {
463
467
blk ( RWWriteMode {
464
468
data : & mut ( * state) . data ,
465
469
token : write_mode,
466
- poison : PoisonOnFail ( & mut ( * state) . failed )
470
+ poison : PoisonOnFail :: new ( & mut ( * state) . failed )
467
471
} )
468
472
} )
469
473
}
@@ -563,7 +567,7 @@ impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
563
567
unsafe {
564
568
let cvar = Condvar {
565
569
is_mutex : false ,
566
- failed : & mut * poison. failed ,
570
+ failed : & * poison. flag ,
567
571
cond : cond
568
572
} ;
569
573
blk ( data, & cvar)
@@ -714,6 +718,25 @@ mod tests {
714
718
}
715
719
}
716
720
721
+ #[ test]
722
+ fn test_mutex_arc_access_in_unwind ( ) {
723
+ let arc = MutexArc :: new ( 1 i) ;
724
+ let arc2 = arc. clone ( ) ;
725
+ task:: try :: < ( ) > ( proc ( ) {
726
+ struct Unwinder {
727
+ i : MutexArc < int >
728
+ }
729
+ impl Drop for Unwinder {
730
+ fn drop ( & mut self ) {
731
+ self . i . access ( |num| * num += 1 ) ;
732
+ }
733
+ }
734
+ let _u = Unwinder { i : arc2 } ;
735
+ fail ! ( ) ;
736
+ } ) ;
737
+ assert_eq ! ( 2 , arc. access( |n| * n) ) ;
738
+ }
739
+
717
740
#[ test] #[ should_fail]
718
741
fn test_rw_arc_poison_wr ( ) {
719
742
let arc = RWArc :: new ( 1 ) ;
@@ -840,6 +863,26 @@ mod tests {
840
863
assert_eq ! ( * num, 10 ) ;
841
864
} )
842
865
}
866
+
867
+ #[ test]
868
+ fn test_rw_arc_access_in_unwind ( ) {
869
+ let arc = RWArc :: new ( 1 i) ;
870
+ let arc2 = arc. clone ( ) ;
871
+ task:: try :: < ( ) > ( proc ( ) {
872
+ struct Unwinder {
873
+ i : RWArc < int >
874
+ }
875
+ impl Drop for Unwinder {
876
+ fn drop ( & mut self ) {
877
+ self . i . write ( |num| * num += 1 ) ;
878
+ }
879
+ }
880
+ let _u = Unwinder { i : arc2 } ;
881
+ fail ! ( ) ;
882
+ } ) ;
883
+ assert_eq ! ( 2 , arc. read( |n| * n) ) ;
884
+ }
885
+
843
886
#[ test]
844
887
fn test_rw_downgrade ( ) {
845
888
// (1) A downgrader gets in write mode and does cond.wait.
0 commit comments