Skip to content

Commit

Permalink
Allow failing in arc::exclusive; poison to fail subsequent accesses (fix
Browse files Browse the repository at this point in the history
  • Loading branch information
bblum committed Aug 9, 2012
1 parent 190ecc2 commit be2e4ef
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions src/libcore/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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>>;

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}};
unsafe {
let ptr = unsafe::reinterpret_cast(data);
Expand Down Expand Up @@ -128,12 +129,18 @@ impl<T: send> exclusive<T> {
let ptr: ~arc_data<ex_data<T>> =
unsafe::reinterpret_cast(self.data);
assert ptr.count > 0;
let r = {
let rec: &ex_data<T> = &(*ptr).data;
do rec.lock.lock { f(&mut rec.data) }
};
let ptr2: &arc_data<ex_data<T>> = unsafe::reinterpret_cast(&*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
}
}
}

Expand Down Expand Up @@ -168,12 +175,11 @@ mod tests {
}

#[test]
#[ignore] // this can probably infinite loop too.
fn exclusive_arc() {
let mut futures = ~[];

let num_tasks = 10u;
let count = 1000u;
let count = 10u;

let total = exclusive(~mut 0u);

Expand All @@ -194,4 +200,20 @@ mod tests {
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;
}
}
}

0 comments on commit be2e4ef

Please sign in to comment.