From ced8393f203fc661df7a5a0159a5edfd826eef12 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 14 Jul 2011 19:39:53 -0700 Subject: [PATCH] Modify task::join to indicate how the task terminated This involves sticking yet another field into the task structure --- src/lib/task.rs | 14 +++++++++++--- src/rt/rust_builtin.cpp | 7 ++++++- src/rt/rust_task.cpp | 4 +++- src/rt/rust_task.h | 3 +++ src/test/run-pass/lib-task.rs | 19 +++++++++++++++++++ src/test/run-pass/spawn.rs | 2 +- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/lib/task.rs b/src/lib/task.rs index 90885f2ab46a..64ab745e4b9c 100644 --- a/src/lib/task.rs +++ b/src/lib/task.rs @@ -1,7 +1,7 @@ native "rust" mod rustrt { fn task_sleep(uint time_in_us); fn task_yield(); - fn task_join(task t); + fn task_join(task t) -> int; fn task_unsupervise(); fn pin_task(); fn unpin_task(); @@ -20,8 +20,16 @@ fn yield() { ret rustrt::task_yield(); } -fn join(task t) { - ret rustrt::task_join(t); +tag task_result { + tr_success; + tr_failure; +} + +fn join(task t) -> task_result { + alt (rustrt::task_join(t)) { + 0 { tr_success } + _ { tr_failure } + } } fn unsupervise() { diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index e8900dd730ac..bdabbb1ed379 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -410,7 +410,7 @@ task_yield(rust_task *task) { task->yield(1); } -extern "C" CDECL void +extern "C" CDECL intptr_t task_join(rust_task *task, rust_task *join_task) { // If the other task is already dying, we don't have to wait for it. join_task->lock.lock(); @@ -423,6 +423,11 @@ task_join(rust_task *task, rust_task *join_task) { else { join_task->lock.unlock(); } + if (!join_task->failed) { + return 0; + } else { + return -1; + } } extern "C" CDECL void diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index fd9a2cc862cb..d56cb8b6276b 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -82,7 +82,8 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state, running_on(-1), pinned_on(-1), local_region(&sched->srv->local_region), - _on_wakeup(NULL) + _on_wakeup(NULL), + failed(false) { LOGPTR(sched, "new task", (uintptr_t)this); DLOG(sched, task, "sizeof(task) = %d (0x%x)", sizeof *this, sizeof *this); @@ -230,6 +231,7 @@ rust_task::fail() { // FIXME: implement unwinding again. if (this == sched->root_task) sched->fail(); + failed = true; } void diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 0babf4ab7e7f..17d1a9838a74 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -89,6 +89,9 @@ rust_task : public maybe_proxy, wakeup_callback *_on_wakeup; + // Indicates that the task ended in failure + bool failed; + lock_and_signal lock; // Only a pointer to 'name' is kept, so it must live as long as this task. diff --git a/src/test/run-pass/lib-task.rs b/src/test/run-pass/lib-task.rs index 58258d400d3c..52ea933a0ce7 100644 --- a/src/test/run-pass/lib-task.rs +++ b/src/test/run-pass/lib-task.rs @@ -15,8 +15,27 @@ fn test_unsupervise() { spawn f(); } +fn test_join() { + fn winner() { + } + + auto wintask = spawn winner(); + + assert task::join(wintask) == task::tr_success; + + fn failer() { + task::unsupervise(); + fail; + } + + auto failtask = spawn failer(); + + assert task::join(failtask) == task::tr_failure; +} + fn main() { // FIXME: Why aren't we running this? //test_sleep(); test_unsupervise(); + test_join(); } \ No newline at end of file diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index db695a1dd8b7..e6279498a2f4 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -5,7 +5,7 @@ use std; fn main() { auto t = spawn child(10); - std::task::join(t) + std::task::join(t); } fn child(int i) {