about summary refs log tree commit diff
path: root/src/libstd/task/spawn.rs
diff options
context:
space:
mode:
authorMarvin Löbel <loebel.marvin@gmail.com>2013-10-11 23:20:34 +0200
committerMarvin Löbel <loebel.marvin@gmail.com>2013-10-28 08:50:32 +0100
commitfa8e71a8257f4226ab532d4bf268d3ecbfa98eb4 (patch)
tree0b8051814dd8a5ef08e663c172e2b456065d625d /src/libstd/task/spawn.rs
parentcb5b21eba713ff3888b2741db4c9e7d841cfde02 (diff)
downloadrust-fa8e71a8257f4226ab532d4bf268d3ecbfa98eb4.tar.gz
rust-fa8e71a8257f4226ab532d4bf268d3ecbfa98eb4.zip
Allow fail messages to be caught, and introduce the Any trait
Some code cleanup, sorting of import blocks

Removed std::unstable::UnsafeArc's use of Either

Added run-fail tests for the new FailWithCause impls

Changed future_result and try to return Result<(), ~Any>.

- Internally, there is an enum of possible fail messages passend around.
- In case of linked failure or a string message, the ~Any gets
  lazyly allocated in future_results recv method.
- For that, future result now returns a wrapper around a Port.
- Moved and renamed task::TaskResult into rt::task::UnwindResult
  and made it an internal enum.
- Introduced a replacement typedef `type TaskResult = Result<(), ~Any>`.
Diffstat (limited to 'src/libstd/task/spawn.rs')
-rw-r--r--src/libstd/task/spawn.rs60
1 files changed, 34 insertions, 26 deletions
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index fbe2988f77c..235e67048f6 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -76,21 +76,24 @@ use prelude::*;
 use cast::transmute;
 use cast;
 use cell::Cell;
-use container::MutableMap;
 use comm::{Chan, GenericChan, oneshot};
+use container::MutableMap;
 use hashmap::{HashSet, HashSetMoveIterator};
 use local_data;
-use task::{Failure, SingleThreaded};
-use task::{Success, TaskOpts, TaskResult};
-use task::unkillable;
-use uint;
-use util;
-use unstable::sync::Exclusive;
 use rt::in_green_task_context;
 use rt::local::Local;
-use rt::task::{Task, Sched};
 use rt::shouldnt_be_public::{Scheduler, KillHandle, WorkQueue, Thread, EventLoop};
+use rt::task::{Task, Sched};
+use rt::task::{UnwindReasonLinked, UnwindReasonStr};
+use rt::task::{UnwindResult, Success, Failure};
 use rt::uv::uvio::UvEventLoop;
+use send_str::IntoSendStr;
+use task::SingleThreaded;
+use task::TaskOpts;
+use task::unkillable;
+use uint;
+use unstable::sync::Exclusive;
+use util;
 
 #[cfg(test)] use task::default_task_opts;
 #[cfg(test)] use comm;
@@ -321,7 +324,7 @@ impl Drop for Taskgroup {
         do RuntimeGlue::with_task_handle_and_failing |me, failing| {
             if failing {
                 for x in self.notifier.mut_iter() {
-                    x.failed = true;
+                    x.task_result = Some(Failure(UnwindReasonLinked));
                 }
                 // Take everybody down with us. After this point, every
                 // other task in the group will see 'tg' as none, which
@@ -353,7 +356,7 @@ pub fn Taskgroup(tasks: TaskGroupArc,
        ancestors: AncestorList,
        mut notifier: Option<AutoNotify>) -> Taskgroup {
     for x in notifier.mut_iter() {
-        x.failed = false;
+        x.task_result = Some(Success);
     }
 
     Taskgroup {
@@ -364,21 +367,28 @@ pub fn Taskgroup(tasks: TaskGroupArc,
 }
 
 struct AutoNotify {
-    notify_chan: Chan<TaskResult>,
-    failed: bool,
+    notify_chan: Chan<UnwindResult>,
+
+    // XXX: By value self drop would allow this to be a plain UnwindResult
+    task_result: Option<UnwindResult>,
 }
 
-impl Drop for AutoNotify {
-    fn drop(&mut self) {
-        let result = if self.failed { Failure } else { Success };
-        self.notify_chan.send(result);
+impl AutoNotify {
+    pub fn new(chan: Chan<UnwindResult>) -> AutoNotify {
+        AutoNotify {
+            notify_chan: chan,
+
+            // Un-set above when taskgroup successfully made.
+            task_result: Some(Failure(UnwindReasonStr("AutoNotify::new()".into_send_str())))
+        }
     }
 }
 
-fn AutoNotify(chan: Chan<TaskResult>) -> AutoNotify {
-    AutoNotify {
-        notify_chan: chan,
-        failed: true // Un-set above when taskgroup successfully made.
+impl Drop for AutoNotify {
+    fn drop(&mut self) {
+        let result = self.task_result.take_unwrap();
+
+        self.notify_chan.send(result);
     }
 }
 
@@ -675,10 +685,8 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
     if opts.notify_chan.is_some() {
         let notify_chan = opts.notify_chan.take_unwrap();
         let notify_chan = Cell::new(notify_chan);
-        let on_exit: ~fn(bool) = |success| {
-            notify_chan.take().send(
-                if success { Success } else { Failure }
-            )
+        let on_exit: ~fn(UnwindResult) = |task_result| {
+            notify_chan.take().send(task_result)
         };
         task.death.on_exit = Some(on_exit);
     }
@@ -721,7 +729,7 @@ fn test_spawn_raw_notify_success() {
     };
     do spawn_raw(opts) {
     }
-    assert_eq!(notify_po.recv(), Success);
+    assert!(notify_po.recv().is_success());
 }
 
 #[test]
@@ -738,5 +746,5 @@ fn test_spawn_raw_notify_failure() {
     do spawn_raw(opts) {
         fail!();
     }
-    assert_eq!(notify_po.recv(), Failure);
+    assert!(notify_po.recv().is_failure());
 }