rust/src/test/bench/task-perf-linked-failure.rs

68 lines
2.4 KiB
Rust
Raw Normal View History

2012-08-03 19:26:25 -04:00
/**
* Test performance of killing many tasks in a taskgroup.
* Along the way, tests various edge cases of ancestor group management.
* In particular, this tries to get each grandchild task to hit the
* "nobe_is_dead" case in each_ancestor only during task exit, but not during
* task spawn. This makes sure that defunct ancestor groups are handled correctly
* w.r.t. possibly leaving stale *rust_tasks lying around.
*/
// Creates in the background 'num_tasks' tasks, all blocked forever.
// Doesn't return until all such tasks are ready, but doesn't block forever itself.
fn grandchild_group(num_tasks: uint) {
let po = comm::port();
let ch = comm::chan(po);
for num_tasks.times {
do task::spawn { // linked
comm::send(ch, ());
comm::recv(comm::port::<()>()); // block forever
}
}
#error["Grandchild group getting started"];
for num_tasks.times {
// Make sure all above children are fully spawned; i.e., enlisted in
// their ancestor groups.
comm::recv(po);
}
#error["Grandchild group ready to go."];
// Master grandchild task exits early.
}
fn spawn_supervised_blocking(myname: &str, +f: fn~()) {
let mut res = none;
task::task().future_result(|+r| res = some(r)).supervised().spawn(f);
2012-08-03 19:26:25 -04:00
#error["%s group waiting", myname];
let x = future::get(&option::unwrap(res));
2012-08-15 14:10:46 -07:00
assert x == task::Success;
2012-08-03 19:26:25 -04:00
}
fn main(args: ~[~str]) {
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100000"]
} else if args.len() <= 1u {
~[~"", ~"100"]
} else {
copy args
};
let num_tasks = uint::from_str(args[1]).get();
// Main group #0 waits for unsupervised group #1.
// Grandparent group #1 waits for middle group #2, then fails, killing #3.
// Middle group #2 creates grandchild_group #3, waits for it to be ready, exits.
let x: result::result<(),()> = do task::try { // unlinked
do spawn_supervised_blocking("grandparent") {
do spawn_supervised_blocking("middle") {
grandchild_group(num_tasks);
}
// When grandchild group is ready to go, make the middle group exit.
#error["Middle group wakes up and exits"];
}
// Grandparent group waits for middle group to be gone, then fails
#error["Grandparent group wakes up and fails"];
fail;
};
assert x.is_err();
}