parent
ba801d8116
commit
7a1e486b2a
1 changed files with 55 additions and 12 deletions
|
@ -226,7 +226,7 @@ impl<T:Send> MutexArc<T> {
|
||||||
// not already unsafe. See borrow_rwlock, far below.
|
// not already unsafe. See borrow_rwlock, far below.
|
||||||
(&(*state).lock).lock(|| {
|
(&(*state).lock).lock(|| {
|
||||||
check_poison(true, (*state).failed);
|
check_poison(true, (*state).failed);
|
||||||
let _z = PoisonOnFail(&mut (*state).failed);
|
let _z = PoisonOnFail::new(&mut (*state).failed);
|
||||||
blk(&mut (*state).data)
|
blk(&mut (*state).data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ impl<T:Send> MutexArc<T> {
|
||||||
let state = self.x.get();
|
let state = self.x.get();
|
||||||
(&(*state).lock).lock_cond(|cond| {
|
(&(*state).lock).lock_cond(|cond| {
|
||||||
check_poison(true, (*state).failed);
|
check_poison(true, (*state).failed);
|
||||||
let _z = PoisonOnFail(&mut (*state).failed);
|
let _z = PoisonOnFail::new(&mut (*state).failed);
|
||||||
blk(&mut (*state).data,
|
blk(&mut (*state).data,
|
||||||
&Condvar {is_mutex: true,
|
&Condvar {is_mutex: true,
|
||||||
failed: &mut (*state).failed,
|
failed: &mut (*state).failed,
|
||||||
|
@ -311,7 +311,8 @@ fn check_poison(is_mutex: bool, failed: bool) {
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
struct PoisonOnFail {
|
struct PoisonOnFail {
|
||||||
failed: *mut bool,
|
flag: *mut bool,
|
||||||
|
failed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for PoisonOnFail {
|
impl Drop for PoisonOnFail {
|
||||||
|
@ -319,16 +320,19 @@ impl Drop for PoisonOnFail {
|
||||||
unsafe {
|
unsafe {
|
||||||
/* assert!(!*self.failed);
|
/* assert!(!*self.failed);
|
||||||
-- might be false in case of cond.wait() */
|
-- might be false in case of cond.wait() */
|
||||||
if task::failing() {
|
if !self.failed && task::failing() {
|
||||||
*self.failed = true;
|
*self.flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn PoisonOnFail<'r>(failed: &'r mut bool) -> PoisonOnFail {
|
impl PoisonOnFail {
|
||||||
PoisonOnFail {
|
fn new<'a>(flag: &'a mut bool) -> PoisonOnFail {
|
||||||
failed: failed
|
PoisonOnFail {
|
||||||
|
flag: flag,
|
||||||
|
failed: task::failing()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +396,7 @@ impl<T:Freeze + Send> RWArc<T> {
|
||||||
let state = self.x.get();
|
let state = self.x.get();
|
||||||
(*borrow_rwlock(state)).write(|| {
|
(*borrow_rwlock(state)).write(|| {
|
||||||
check_poison(false, (*state).failed);
|
check_poison(false, (*state).failed);
|
||||||
let _z = PoisonOnFail(&mut (*state).failed);
|
let _z = PoisonOnFail::new(&mut (*state).failed);
|
||||||
blk(&mut (*state).data)
|
blk(&mut (*state).data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -407,7 +411,7 @@ impl<T:Freeze + Send> RWArc<T> {
|
||||||
let state = self.x.get();
|
let state = self.x.get();
|
||||||
(*borrow_rwlock(state)).write_cond(|cond| {
|
(*borrow_rwlock(state)).write_cond(|cond| {
|
||||||
check_poison(false, (*state).failed);
|
check_poison(false, (*state).failed);
|
||||||
let _z = PoisonOnFail(&mut (*state).failed);
|
let _z = PoisonOnFail::new(&mut (*state).failed);
|
||||||
blk(&mut (*state).data,
|
blk(&mut (*state).data,
|
||||||
&Condvar {is_mutex: false,
|
&Condvar {is_mutex: false,
|
||||||
failed: &mut (*state).failed,
|
failed: &mut (*state).failed,
|
||||||
|
@ -463,7 +467,7 @@ impl<T:Freeze + Send> RWArc<T> {
|
||||||
blk(RWWriteMode {
|
blk(RWWriteMode {
|
||||||
data: &mut (*state).data,
|
data: &mut (*state).data,
|
||||||
token: write_mode,
|
token: write_mode,
|
||||||
poison: PoisonOnFail(&mut (*state).failed)
|
poison: PoisonOnFail::new(&mut (*state).failed)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -563,7 +567,7 @@ impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let cvar = Condvar {
|
let cvar = Condvar {
|
||||||
is_mutex: false,
|
is_mutex: false,
|
||||||
failed: &mut *poison.failed,
|
failed: &mut *poison.flag,
|
||||||
cond: cond
|
cond: cond
|
||||||
};
|
};
|
||||||
blk(data, &cvar)
|
blk(data, &cvar)
|
||||||
|
@ -714,6 +718,25 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mutex_arc_access_in_unwind() {
|
||||||
|
let arc = MutexArc::new(1i);
|
||||||
|
let arc2 = arc.clone();
|
||||||
|
task::try::<()>(proc() {
|
||||||
|
struct Unwinder {
|
||||||
|
i: MutexArc<int>
|
||||||
|
}
|
||||||
|
impl Drop for Unwinder {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.i.access(|num| *num += 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _u = Unwinder { i: arc2 };
|
||||||
|
fail!();
|
||||||
|
});
|
||||||
|
assert_eq!(2, arc.access(|n| *n));
|
||||||
|
}
|
||||||
|
|
||||||
#[test] #[should_fail]
|
#[test] #[should_fail]
|
||||||
fn test_rw_arc_poison_wr() {
|
fn test_rw_arc_poison_wr() {
|
||||||
let arc = RWArc::new(1);
|
let arc = RWArc::new(1);
|
||||||
|
@ -840,6 +863,26 @@ mod tests {
|
||||||
assert_eq!(*num, 10);
|
assert_eq!(*num, 10);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rw_arc_access_in_unwind() {
|
||||||
|
let arc = RWArc::new(1i);
|
||||||
|
let arc2 = arc.clone();
|
||||||
|
task::try::<()>(proc() {
|
||||||
|
struct Unwinder {
|
||||||
|
i: RWArc<int>
|
||||||
|
}
|
||||||
|
impl Drop for Unwinder {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.i.write(|num| *num += 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _u = Unwinder { i: arc2 };
|
||||||
|
fail!();
|
||||||
|
});
|
||||||
|
assert_eq!(2, arc.read(|n| *n));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rw_downgrade() {
|
fn test_rw_downgrade() {
|
||||||
// (1) A downgrader gets in write mode and does cond.wait.
|
// (1) A downgrader gets in write mode and does cond.wait.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue