Allow failing in arc::exclusive; poison to fail subsequent accesses (fix #3092)
This commit is contained in:
parent
190ecc220a
commit
be2e4ef624
1 changed files with 31 additions and 9 deletions
|
@ -81,11 +81,12 @@ fn clone<T: const send>(rc: &arc<T>) -> arc<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// An arc over mutable data that is protected by a lock.
|
// An arc over mutable data that is protected by a lock.
|
||||||
type ex_data<T: send> = {lock: sys::little_lock, mut data: T};
|
type ex_data<T: send> =
|
||||||
|
{lock: sys::little_lock, mut failed: bool, mut data: T};
|
||||||
type exclusive<T: send> = arc_destruct<ex_data<T>>;
|
type exclusive<T: send> = arc_destruct<ex_data<T>>;
|
||||||
|
|
||||||
fn exclusive<T:send >(-data: T) -> exclusive<T> {
|
fn exclusive<T:send >(-data: T) -> exclusive<T> {
|
||||||
let data = ~{mut count: 1, data: {lock: sys::little_lock(),
|
let data = ~{mut count: 1, data: {lock: sys::little_lock(), failed: false,
|
||||||
data: data}};
|
data: data}};
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = unsafe::reinterpret_cast(data);
|
let ptr = unsafe::reinterpret_cast(data);
|
||||||
|
@ -128,12 +129,18 @@ impl<T: send> exclusive<T> {
|
||||||
let ptr: ~arc_data<ex_data<T>> =
|
let ptr: ~arc_data<ex_data<T>> =
|
||||||
unsafe::reinterpret_cast(self.data);
|
unsafe::reinterpret_cast(self.data);
|
||||||
assert ptr.count > 0;
|
assert ptr.count > 0;
|
||||||
let r = {
|
let ptr2: &arc_data<ex_data<T>> = unsafe::reinterpret_cast(&*ptr);
|
||||||
let rec: &ex_data<T> = &(*ptr).data;
|
|
||||||
do rec.lock.lock { f(&mut rec.data) }
|
|
||||||
};
|
|
||||||
unsafe::forget(ptr);
|
unsafe::forget(ptr);
|
||||||
r
|
let rec: &ex_data<T> = &(*ptr2).data;
|
||||||
|
do rec.lock.lock {
|
||||||
|
if rec.failed {
|
||||||
|
fail ~"Poisoned arc::exclusive - another task failed inside!";
|
||||||
|
}
|
||||||
|
rec.failed = true;
|
||||||
|
let result = f(&mut rec.data);
|
||||||
|
rec.failed = false;
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,12 +175,11 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore] // this can probably infinite loop too.
|
|
||||||
fn exclusive_arc() {
|
fn exclusive_arc() {
|
||||||
let mut futures = ~[];
|
let mut futures = ~[];
|
||||||
|
|
||||||
let num_tasks = 10u;
|
let num_tasks = 10u;
|
||||||
let count = 1000u;
|
let count = 10u;
|
||||||
|
|
||||||
let total = exclusive(~mut 0u);
|
let total = exclusive(~mut 0u);
|
||||||
|
|
||||||
|
@ -194,4 +200,20 @@ mod tests {
|
||||||
assert **total == num_tasks * count
|
assert **total == num_tasks * count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||||
|
fn exclusive_poison() {
|
||||||
|
// Tests that if one task fails inside of an exclusive, subsequent
|
||||||
|
// accesses will also fail.
|
||||||
|
let x = arc::exclusive(1);
|
||||||
|
let x2 = x.clone();
|
||||||
|
do task::try {
|
||||||
|
do x2.with |one| {
|
||||||
|
assert *one == 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
do x.with |one| {
|
||||||
|
assert *one == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue