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 06:01:39 -0700
committerbors <bors@rust-lang.org>2013-08-01 06:01:39 -0700
commit18d124b9b5dcb9915e5e1489eed81ed6a8b90c39 (patch)
tree08815543f7ba4e527622ab5c654f87b17d91c252 /src/libstd/task
parent9824d90ffd7684eca7171c4e019fd85b9317904e (diff)
parentbc7cee7bbf816be7a712c06a93015dc3c6fd5611 (diff)
downloadrust-18d124b9b5dcb9915e5e1489eed81ed6a8b90c39.tar.gz
rust-18d124b9b5dcb9915e5e1489eed81ed6a8b90c39.zip
auto merge of #8158 : bblum/rust/task-cleanup, r=brson
r? @brson
Diffstat (limited to 'src/libstd/task')
-rw-r--r--src/libstd/task/mod.rs112
-rw-r--r--src/libstd/task/spawn.rs2
2 files changed, 59 insertions, 55 deletions
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 6de0c78d00b..aff4bc12039 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -120,6 +120,8 @@ pub struct SchedOpts {
  *
  * * notify_chan - Enable lifecycle notifications on the given channel
  *
+ * * name - A name for the task-to-be, for identification in failure messages.
+ *
  * * sched - Specify the configuration of a new scheduler to create the task
  *           in
  *
@@ -139,6 +141,7 @@ pub struct TaskOpts {
     watched: bool,
     indestructible: bool,
     notify_chan: Option<Chan<TaskResult>>,
+    name: Option<~str>,
     sched: SchedOpts
 }
 
@@ -185,6 +188,7 @@ impl TaskBuilder {
         self.consumed = true;
         let gen_body = self.gen_body.take();
         let notify_chan = self.opts.notify_chan.take();
+        let name = self.opts.name.take();
         TaskBuilder {
             opts: TaskOpts {
                 linked: self.opts.linked,
@@ -192,6 +196,7 @@ impl TaskBuilder {
                 watched: self.opts.watched,
                 indestructible: self.opts.indestructible,
                 notify_chan: notify_chan,
+                name: name,
                 sched: self.opts.sched
             },
             gen_body: gen_body,
@@ -199,9 +204,7 @@ impl TaskBuilder {
             consumed: false
         }
     }
-}
 
-impl TaskBuilder {
     /// Decouple the child task's failure from the parent's. If either fails,
     /// the other will not be killed.
     pub fn unlinked(&mut self) {
@@ -281,6 +284,12 @@ impl TaskBuilder {
         self.opts.notify_chan = Some(notify_pipe_ch);
     }
 
+    /// Name the task-to-be. Currently the name is used for identification
+    /// only in failure messages.
+    pub fn name(&mut self, name: ~str) {
+        self.opts.name = Some(name);
+    }
+
     /// Configure a custom scheduler mode for the task.
     pub fn sched_mode(&mut self, mode: SchedMode) {
         self.opts.sched.mode = mode;
@@ -333,6 +342,7 @@ impl TaskBuilder {
     pub fn spawn(&mut self, f: ~fn()) {
         let gen_body = self.gen_body.take();
         let notify_chan = self.opts.notify_chan.take();
+        let name = self.opts.name.take();
         let x = self.consume();
         let opts = TaskOpts {
             linked: x.opts.linked,
@@ -340,6 +350,7 @@ impl TaskBuilder {
             watched: x.opts.watched,
             indestructible: x.opts.indestructible,
             notify_chan: notify_chan,
+            name: name,
             sched: x.opts.sched
         };
         let f = match gen_body {
@@ -408,6 +419,7 @@ pub fn default_task_opts() -> TaskOpts {
         watched: true,
         indestructible: false,
         notify_chan: None,
+        name: None,
         sched: SchedOpts {
             mode: DefaultScheduler,
         }
@@ -507,6 +519,21 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
 
 /* Lifecycle functions */
 
+/// Read the name of the current task.
+pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
+    use rt::task::Task;
+
+    match context() {
+        TaskContext => do Local::borrow::<Task, U> |task| {
+            match task.name {
+                Some(ref name) => blk(Some(name.as_slice())),
+                None => blk(None)
+            }
+        },
+        _ => fail!("no task name exists in %?", context()),
+    }
+}
+
 pub fn yield() {
     //! Yield control to the task scheduler
 
@@ -628,44 +655,6 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
     }
 }
 
-/**
- * A stronger version of unkillable that also inhibits scheduling operations.
- * For use with exclusive Arcs, which use pthread mutexes directly.
- */
-pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
-    use rt::task::Task;
-
-    match context() {
-        OldTaskContext => {
-            let t = rt::rust_get_task();
-            do (|| {
-                rt::rust_task_inhibit_kill(t);
-                rt::rust_task_inhibit_yield(t);
-                f()
-            }).finally {
-                rt::rust_task_allow_yield(t);
-                rt::rust_task_allow_kill(t);
-            }
-        }
-        TaskContext => {
-            let t = Local::unsafe_borrow::<Task>();
-            do (|| {
-                // It's important to inhibit kill after inhibiting yield, because
-                // inhibit-kill might fail if we were already killed, and the
-                // inhibit-yield must happen to match the finally's allow-yield.
-                (*t).death.inhibit_yield();
-                (*t).death.inhibit_kill((*t).unwinder.unwinding);
-                f()
-            }).finally {
-                (*t).death.allow_kill((*t).unwinder.unwinding);
-                (*t).death.allow_yield();
-            }
-        }
-        // FIXME(#3095): As in unkillable().
-        _ => f()
-    }
-}
-
 #[test] #[should_fail] #[ignore(cfg(windows))]
 fn test_cant_dup_task_builder() {
     let mut builder = task();
@@ -806,6 +795,34 @@ fn test_spawn_linked_sup_propagate_sibling() {
 }
 
 #[test]
+fn test_unnamed_task() {
+    use rt::test::run_in_newsched_task;
+
+    do run_in_newsched_task {
+        do spawn {
+            do with_task_name |name| {
+                assert!(name.is_none());
+            }
+        }
+    }
+}
+
+#[test]
+fn test_named_task() {
+    use rt::test::run_in_newsched_task;
+
+    do run_in_newsched_task {
+        let mut t = task();
+        t.name(~"ada lovelace");
+        do t.spawn {
+            do with_task_name |name| {
+                assert!(name.get() == "ada lovelace");
+            }
+        }
+    }
+}
+
+#[test]
 fn test_run_basic() {
     let (po, ch) = stream::<()>();
     let mut builder = task();
@@ -1122,21 +1139,6 @@ fn test_unkillable_nested() {
     po.recv();
 }
 
-#[test] #[should_fail] #[ignore(cfg(windows))]
-fn test_atomically() {
-    unsafe { do atomically { yield(); } }
-}
-
-#[test]
-fn test_atomically2() {
-    unsafe { do atomically { } } yield(); // shouldn't fail
-}
-
-#[test] #[should_fail] #[ignore(cfg(windows))]
-fn test_atomically_nested() {
-    unsafe { do atomically { do atomically { } yield(); } }
-}
-
 #[test]
 fn test_child_doesnt_ref_parent() {
     // If the child refcounts the parent task, this will stack overflow when
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index c7f34974a6e..81db5e690a6 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -725,6 +725,8 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
         task.death.on_exit = Some(on_exit);
     }
 
+    task.name = opts.name.take();
+
     rtdebug!("spawn about to take scheduler");
 
     let sched = Local::take::<Scheduler>();