about summary refs log tree commit diff
path: root/src/libstd/task
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-01 18:01:42 -0700
committerbors <bors@rust-lang.org>2013-08-01 18:01:42 -0700
commit5890fcf87295d5b7a8f4ffa8d9918f755f72baf8 (patch)
tree6bdd10dda4a962843c3dce5dee33e509152e95cb /src/libstd/task
parentd346f1a40e0d0ebe24e60d418f304641fc26f9b0 (diff)
parentce761f4980e6cdc6115608e6db551bdf1c49387f (diff)
downloadrust-5890fcf87295d5b7a8f4ffa8d9918f755f72baf8.tar.gz
rust-5890fcf87295d5b7a8f4ffa8d9918f755f72baf8.zip
auto merge of #8116 : toddaaro/rust/tls-tk-pr-pre, r=brson
Merged with task killing code this time around.
Diffstat (limited to 'src/libstd/task')
-rw-r--r--src/libstd/task/mod.rs231
-rw-r--r--src/libstd/task/spawn.rs43
2 files changed, 165 insertions, 109 deletions
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index d0124407bd4..7a864ecb867 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -677,121 +677,190 @@ fn block_forever() { let (po, _ch) = stream::<()>(); po.recv(); }
 
 #[test] #[ignore(cfg(windows))]
 fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port
-    let (po, ch) = stream();
-    let ch = SharedChan::new(ch);
-    do spawn_unlinked {
-        let ch = ch.clone();
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let (po, ch) = stream();
+        let ch = SharedChan::new(ch);
         do spawn_unlinked {
-            // Give middle task a chance to fail-but-not-kill-us.
-            do 16.times { task::yield(); }
-            ch.send(()); // If killed first, grandparent hangs.
+            let ch = ch.clone();
+            do spawn_unlinked {
+                // Give middle task a chance to fail-but-not-kill-us.
+                do 16.times { task::yield(); }
+                ch.send(()); // If killed first, grandparent hangs.
+            }
+            fail!(); // Shouldn't kill either (grand)parent or (grand)child.
         }
-        fail!(); // Shouldn't kill either (grand)parent or (grand)child.
+        po.recv();
     }
-    po.recv();
 }
 #[test] #[ignore(cfg(windows))]
 fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails
-    do spawn_unlinked { fail!(); }
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        do spawn_unlinked { fail!(); }
+    }
 }
 #[test] #[ignore(cfg(windows))]
 fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails
-    do spawn_supervised { fail!(); }
-    // Give child a chance to fail-but-not-kill-us.
-    do 16.times { task::yield(); }
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        do spawn_supervised { fail!(); }
+        // Give child a chance to fail-but-not-kill-us.
+        do 16.times { task::yield(); }
+    }
 }
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_unlinked_sup_fail_down() {
-    do spawn_supervised { block_forever(); }
-    fail!(); // Shouldn't leave a child hanging around.
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            do spawn_supervised { block_forever(); }
+            fail!(); // Shouldn't leave a child hanging around.
+        };
+        assert!(result.is_err());
+    }
 }
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
-    // Unidirectional "parenting" shouldn't override bidirectional linked.
-    // We have to cheat with opts - the interface doesn't support them because
-    // they don't make sense (redundant with task().supervised()).
-    let mut b0 = task();
-    b0.opts.linked = true;
-    b0.opts.supervised = true;
-
-    do b0.spawn {
-        fail!();
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Unidirectional "parenting" shouldn't override bidirectional linked.
+            // We have to cheat with opts - the interface doesn't support them because
+            // they don't make sense (redundant with task().supervised()).
+            let mut b0 = task();
+            b0.opts.linked = true;
+            b0.opts.supervised = true;
+
+            do b0.spawn {
+                fail!();
+            }
+            block_forever(); // We should get punted awake
+        };
+        assert!(result.is_err());
     }
-    block_forever(); // We should get punted awake
 }
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
-    // We have to cheat with opts - the interface doesn't support them because
-    // they don't make sense (redundant with task().supervised()).
-    let mut b0 = task();
-    b0.opts.linked = true;
-    b0.opts.supervised = true;
-    do b0.spawn { block_forever(); }
-    fail!(); // *both* mechanisms would be wrong if this didn't kill the child
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // We have to cheat with opts - the interface doesn't support them because
+            // they don't make sense (redundant with task().supervised()).
+            let mut b0 = task();
+            b0.opts.linked = true;
+            b0.opts.supervised = true;
+            do b0.spawn { block_forever(); }
+            fail!(); // *both* mechanisms would be wrong if this didn't kill the child
+        };
+        assert!(result.is_err());
+    }
 }
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
-    // Default options are to spawn linked & unsupervised.
-    do spawn { fail!(); }
-    block_forever(); // We should get punted awake
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Default options are to spawn linked & unsupervised.
+            do spawn { fail!(); }
+            block_forever(); // We should get punted awake
+        };
+        assert!(result.is_err());
+    }
 }
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_unsup_fail_down() { // parent fails; child fails
-    // Default options are to spawn linked & unsupervised.
-    do spawn { block_forever(); }
-    fail!();
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Default options are to spawn linked & unsupervised.
+            do spawn { block_forever(); }
+            fail!();
+        };
+        assert!(result.is_err());
+    }
 }
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_unsup_default_opts() { // parent fails; child fails
-    // Make sure the above test is the same as this one.
-    let mut builder = task();
-    builder.linked();
-    do builder.spawn { block_forever(); }
-    fail!();
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Make sure the above test is the same as this one.
+            let mut builder = task();
+            builder.linked();
+            do builder.spawn { block_forever(); }
+            fail!();
+        };
+        assert!(result.is_err());
+    }
 }
 
 // A couple bonus linked failure tests - testing for failure propagation even
 // when the middle task exits successfully early before kill signals are sent.
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_failure_propagate_grandchild() {
-    // Middle task exits; does grandparent's failure propagate across the gap?
-    do spawn_supervised {
-        do spawn_supervised { block_forever(); }
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Middle task exits; does grandparent's failure propagate across the gap?
+            do spawn_supervised {
+                do spawn_supervised { block_forever(); }
+            }
+            do 16.times { task::yield(); }
+            fail!();
+        };
+        assert!(result.is_err());
     }
-    do 16.times { task::yield(); }
-    fail!();
 }
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_failure_propagate_secondborn() {
-    // First-born child exits; does parent's failure propagate to sibling?
-    do spawn_supervised {
-        do spawn { block_forever(); } // linked
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // First-born child exits; does parent's failure propagate to sibling?
+            do spawn_supervised {
+                do spawn { block_forever(); } // linked
+            }
+            do 16.times { task::yield(); }
+            fail!();
+        };
+        assert!(result.is_err());
     }
-    do 16.times { task::yield(); }
-    fail!();
 }
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_failure_propagate_nephew_or_niece() {
-    // Our sibling exits; does our failure propagate to sibling's child?
-    do spawn { // linked
-        do spawn_supervised { block_forever(); }
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Our sibling exits; does our failure propagate to sibling's child?
+            do spawn { // linked
+                do spawn_supervised { block_forever(); }
+            }
+            do 16.times { task::yield(); }
+            fail!();
+        };
+        assert!(result.is_err());
     }
-    do 16.times { task::yield(); }
-    fail!();
 }
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
+#[test] #[ignore(cfg(windows))]
 fn test_spawn_linked_sup_propagate_sibling() {
-    // Middle sibling exits - does eldest's failure propagate to youngest?
-    do spawn { // linked
-        do spawn { block_forever(); } // linked
+    use rt::test::run_in_newsched_task;
+    do run_in_newsched_task {
+        let result: Result<(),()> = do try {
+            // Middle sibling exits - does eldest's failure propagate to youngest?
+            do spawn { // linked
+                do spawn { block_forever(); } // linked
+            }
+            do 16.times { task::yield(); }
+            fail!();
+        };
+        assert!(result.is_err());
     }
-    do 16.times { task::yield(); }
-    fail!();
 }
 
 #[test]
@@ -1149,11 +1218,15 @@ fn test_child_doesnt_ref_parent() {
     fn child_no(x: uint) -> ~fn() {
         return || {
             if x < generations {
-                task::spawn(child_no(x+1));
+                let mut t = task();
+                t.unwatched();
+                t.spawn(child_no(x+1));
             }
         }
     }
-    task::spawn(child_no(0));
+    let mut t = task();
+    t.unwatched();
+    t.spawn(child_no(0));
 }
 
 #[test]
@@ -1167,9 +1240,9 @@ fn test_simple_newsched_spawn() {
 
 #[test] #[ignore(cfg(windows))]
 fn test_spawn_watched() {
-    use rt::test::{run_in_newsched_task, spawntask_try};
+    use rt::test::run_in_newsched_task;
     do run_in_newsched_task {
-        let result = do spawntask_try {
+        let result = do try {
             let mut t = task();
             t.unlinked();
             t.watched();
@@ -1189,9 +1262,9 @@ fn test_spawn_watched() {
 
 #[test] #[ignore(cfg(windows))]
 fn test_indestructible() {
-    use rt::test::{run_in_newsched_task, spawntask_try};
+    use rt::test::run_in_newsched_task;
     do run_in_newsched_task {
-        let result = do spawntask_try {
+        let result = do try {
             let mut t = task();
             t.watched();
             t.supervised();
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 4558f8e32c1..88f214ef4c0 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -653,22 +653,16 @@ fn enlist_many(child: TaskHandle, child_arc: &TaskGroupArc,
 
 pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
     match context() {
-        OldTaskContext => {
-            spawn_raw_oldsched(opts, f)
-        }
-        TaskContext => {
-            spawn_raw_newsched(opts, f)
-        }
-        SchedulerContext => {
-            fail!("can't spawn from scheduler context")
-        }
-        GlobalContext => {
-            fail!("can't spawn from global context")
-        }
+        OldTaskContext   => spawn_raw_oldsched(opts, f),
+        TaskContext      => spawn_raw_newsched(opts, f),
+        SchedulerContext => fail!("can't spawn from scheduler context"),
+        GlobalContext    => fail!("can't spawn from global context"),
     }
 }
 
 fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
+    use rt::sched::*;
+
     let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised));
     let indestructible = opts.indestructible;
 
@@ -700,19 +694,11 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
         }
     };
 
-    let mut task = unsafe {
-        let sched = Local::unsafe_borrow::<Scheduler>();
-        rtdebug!("unsafe borrowed sched");
-
-        if opts.watched {
-            let child_wrapper = Cell::new(child_wrapper);
-            do Local::borrow::<Task, ~Task>() |running_task| {
-                ~running_task.new_child(&mut (*sched).stack_pool, child_wrapper.take())
-            }
-        } else {
-            // An unwatched task is a new root in the exit-code propagation tree
-            ~Task::new_root(&mut (*sched).stack_pool, child_wrapper)
-        }
+    let mut task = if opts.watched {
+        Task::build_child(child_wrapper)
+    } else {
+        // An unwatched task is a new root in the exit-code propagation tree
+        Task::build_root(child_wrapper)
     };
 
     if opts.notify_chan.is_some() {
@@ -727,12 +713,9 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
     }
 
     task.name = opts.name.take();
+    rtdebug!("spawn calling run_task");
+    Scheduler::run_task(task);
 
-    rtdebug!("spawn about to take scheduler");
-
-    let sched = Local::take::<Scheduler>();
-    rtdebug!("took sched in spawn");
-    sched.schedule_task(task);
 }
 
 fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {