Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add task-perf-linked-failure.rs

  • Loading branch information...
commit f57760c609d636d2e4698a26848f5c990d417265 1 parent fe2f3d2
@bblum bblum authored
View
4 src/test/bench/task-perf-jargon-metal-smoke.rs
@@ -3,12 +3,12 @@
// Each child task has to enlist as a descendant in each of its ancestor
// groups, but that shouldn't have to happen for already-dead groups.
//
-// The filename is a reference; google it in quotes.
+// The filename is a song reference; google it in quotes.
fn child_generation(gens_left: uint) {
// This used to be O(n^2) in the number of generations that ever existed.
// With this code, only as many generations are alive at a time as tasks
- // alive at a time,
+ // alive at a time,
do task::spawn_supervised {
if gens_left & 1 == 1 {
task::yield(); // shake things up a bit
View
67 src/test/bench/task-perf-linked-failure.rs
@@ -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();
+}
Please sign in to comment.
Something went wrong with that request. Please try again.