/** * 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); #error["%s group waiting", myname]; let x = future::get(option::unwrap(res)); assert x == task::success; } 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(); }