Skip to content

Commit 1b4bbc8

Browse files
committed
auto merge of #11109 : sfackler/rust/arc, r=alexcrichton
Closes #11097
2 parents 9e00272 + 2490b59 commit 1b4bbc8

File tree

1 file changed

+58
-15
lines changed

1 file changed

+58
-15
lines changed

src/libextra/arc.rs

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use std::borrow;
5151
/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
5252
pub struct Condvar<'a> {
5353
priv is_mutex: bool,
54-
priv failed: &'a mut bool,
54+
priv failed: &'a bool,
5555
priv cond: &'a sync::Condvar<'a>
5656
}
5757

@@ -226,7 +226,7 @@ impl<T:Send> MutexArc<T> {
226226
// not already unsafe. See borrow_rwlock, far below.
227227
(&(*state).lock).lock(|| {
228228
check_poison(true, (*state).failed);
229-
let _z = PoisonOnFail(&mut (*state).failed);
229+
let _z = PoisonOnFail::new(&mut (*state).failed);
230230
blk(&mut (*state).data)
231231
})
232232
}
@@ -239,10 +239,10 @@ impl<T:Send> MutexArc<T> {
239239
let state = self.x.get();
240240
(&(*state).lock).lock_cond(|cond| {
241241
check_poison(true, (*state).failed);
242-
let _z = PoisonOnFail(&mut (*state).failed);
242+
let _z = PoisonOnFail::new(&mut (*state).failed);
243243
blk(&mut (*state).data,
244244
&Condvar {is_mutex: true,
245-
failed: &mut (*state).failed,
245+
failed: &(*state).failed,
246246
cond: cond })
247247
})
248248
}
@@ -311,24 +311,28 @@ fn check_poison(is_mutex: bool, failed: bool) {
311311

312312
#[doc(hidden)]
313313
struct PoisonOnFail {
314-
failed: *mut bool,
314+
flag: *mut bool,
315+
failed: bool,
315316
}
316317

317318
impl Drop for PoisonOnFail {
318319
fn drop(&mut self) {
319320
unsafe {
320321
/* assert!(!*self.failed);
321322
-- 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;
324325
}
325326
}
326327
}
327328
}
328329

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+
}
332336
}
333337
}
334338

@@ -392,7 +396,7 @@ impl<T:Freeze + Send> RWArc<T> {
392396
let state = self.x.get();
393397
(*borrow_rwlock(state)).write(|| {
394398
check_poison(false, (*state).failed);
395-
let _z = PoisonOnFail(&mut (*state).failed);
399+
let _z = PoisonOnFail::new(&mut (*state).failed);
396400
blk(&mut (*state).data)
397401
})
398402
}
@@ -407,10 +411,10 @@ impl<T:Freeze + Send> RWArc<T> {
407411
let state = self.x.get();
408412
(*borrow_rwlock(state)).write_cond(|cond| {
409413
check_poison(false, (*state).failed);
410-
let _z = PoisonOnFail(&mut (*state).failed);
414+
let _z = PoisonOnFail::new(&mut (*state).failed);
411415
blk(&mut (*state).data,
412416
&Condvar {is_mutex: false,
413-
failed: &mut (*state).failed,
417+
failed: &(*state).failed,
414418
cond: cond})
415419
})
416420
}
@@ -463,7 +467,7 @@ impl<T:Freeze + Send> RWArc<T> {
463467
blk(RWWriteMode {
464468
data: &mut (*state).data,
465469
token: write_mode,
466-
poison: PoisonOnFail(&mut (*state).failed)
470+
poison: PoisonOnFail::new(&mut (*state).failed)
467471
})
468472
})
469473
}
@@ -563,7 +567,7 @@ impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
563567
unsafe {
564568
let cvar = Condvar {
565569
is_mutex: false,
566-
failed: &mut *poison.failed,
570+
failed: &*poison.flag,
567571
cond: cond
568572
};
569573
blk(data, &cvar)
@@ -714,6 +718,25 @@ mod tests {
714718
}
715719
}
716720

721+
#[test]
722+
fn test_mutex_arc_access_in_unwind() {
723+
let arc = MutexArc::new(1i);
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+
717740
#[test] #[should_fail]
718741
fn test_rw_arc_poison_wr() {
719742
let arc = RWArc::new(1);
@@ -840,6 +863,26 @@ mod tests {
840863
assert_eq!(*num, 10);
841864
})
842865
}
866+
867+
#[test]
868+
fn test_rw_arc_access_in_unwind() {
869+
let arc = RWArc::new(1i);
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+
843886
#[test]
844887
fn test_rw_downgrade() {
845888
// (1) A downgrader gets in write mode and does cond.wait.

0 commit comments

Comments
 (0)