Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
69 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,67 @@ | |||
/** | |||
* 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(); | |||
} |