Skip to content

Made std::task::TaskBuilder::future_result() easier to use #9926

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libextra/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ mod tests {
do 5.times {
let arc3 = arc.clone();
let mut builder = task::task();
builder.future_result(|r| children.push(r));
children.push(builder.future_result());
do builder.spawn {
do arc3.read |num| {
assert!(*num >= 0);
Expand Down
6 changes: 2 additions & 4 deletions src/libextra/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,14 +870,12 @@ pub fn run_test(force_ignore: bool,
testfn: ~fn()) {
let testfn_cell = ::std::cell::Cell::new(testfn);
do task::spawn {
let mut result_future = None; // task::future_result(builder);

let mut task = task::task();
task.unlinked();
task.future_result(|r| { result_future = Some(r) });
let result_future = task.future_result();
task.spawn(testfn_cell.take());

let task_result = result_future.unwrap().recv();
let task_result = result_future.recv();
let test_result = calc_result(&desc,
task_result == task::Success);
monitor_ch.send((desc.clone(), test_result));
Expand Down
1 change: 0 additions & 1 deletion src/libstd/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,6 @@ mod tests {
use str::OwnedStr;
use vec::ImmutableVector;
use to_str::ToStr;
use fmt::Default;

pub fn op1() -> Result<int, ~str> { Ok(666) }
pub fn op2() -> Result<int, ~str> { Err(~"sadface") }
Expand Down
25 changes: 0 additions & 25 deletions src/libstd/rt/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,29 +621,4 @@ mod test {
a.next = Some(b);
}
}

// XXX: This is a copy of test_future_result in std::task.
// It can be removed once the scheduler is turned on by default.
#[test]
fn future_result() {
do run_in_newsched_task {
use option::{Some, None};
use task::*;

let mut result = None;
let mut builder = task();
builder.future_result(|r| result = Some(r));
do builder.spawn {}
assert_eq!(result.unwrap().recv(), Success);

result = None;
let mut builder = task();
builder.future_result(|r| result = Some(r));
builder.unlinked();
do builder.spawn {
fail2!();
}
assert_eq!(result.unwrap().recv(), Failure);
}
}
}
57 changes: 26 additions & 31 deletions src/libstd/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,24 +258,22 @@ impl TaskBuilder {
self.opts.indestructible = true;
}

/**
* Get a future representing the exit status of the task.
*
* Taking the value of the future will block until the child task
* terminates. The future-receiving callback specified will be called
* *before* the task is spawned; as such, do not invoke .get() within the
* closure; rather, store it in an outer variable/list for later use.
*
* Note that the future returning by this function is only useful for
* obtaining the value of the next task to be spawning with the
* builder. If additional tasks are spawned with the same builder
* then a new result future must be obtained prior to spawning each
* task.
*
* # Failure
* Fails if a future_result was already set for this task.
*/
pub fn future_result(&mut self, blk: &fn(v: Port<TaskResult>)) {
/// Get a future representing the exit status of the task.
///
/// Taking the value of the future will block until the child task
/// terminates. The future result return value will be created *before* the task is
/// spawned; as such, do not invoke .get() on it directly;
/// rather, store it in an outer variable/list for later use.
///
/// Note that the future returned by this function is only useful for
/// obtaining the value of the next task to be spawning with the
/// builder. If additional tasks are spawned with the same builder
/// then a new result future must be obtained prior to spawning each
/// task.
///
/// # Failure
/// Fails if a future_result was already set for this task.
pub fn future_result(&mut self) -> Port<TaskResult> {
// FIXME (#3725): Once linked failure and notification are
// handled in the library, I can imagine implementing this by just
// registering an arbitrary number of task::on_exit handlers and
Expand All @@ -288,10 +286,10 @@ impl TaskBuilder {
// Construct the future and give it to the caller.
let (notify_pipe_po, notify_pipe_ch) = stream::<TaskResult>();

blk(notify_pipe_po);

// Reconfigure self to use a notify channel.
self.opts.notify_chan = Some(notify_pipe_ch);

notify_pipe_po
}

/// Name the task-to-be. Currently the name is used for identification
Expand Down Expand Up @@ -398,15 +396,14 @@ impl TaskBuilder {
*/
pub fn try<T:Send>(&mut self, f: ~fn() -> T) -> Result<T,()> {
let (po, ch) = stream::<T>();
let mut result = None;

self.future_result(|r| { result = Some(r); });
let result = self.future_result();

do self.spawn {
ch.send(f());
}

match result.unwrap().recv() {
match result.recv() {
Success => result::Ok(po.recv()),
Failure => result::Err(())
}
Expand Down Expand Up @@ -1024,27 +1021,25 @@ fn test_add_wrapper() {

#[test]
fn test_future_result() {
let mut result = None;
let mut builder = task();
builder.future_result(|r| result = Some(r));
let result = builder.future_result();
do builder.spawn {}
assert_eq!(result.unwrap().recv(), Success);
assert_eq!(result.recv(), Success);

result = None;
let mut builder = task();
builder.future_result(|r| result = Some(r));
let result = builder.future_result();
builder.unlinked();
do builder.spawn {
fail2!();
}
assert_eq!(result.unwrap().recv(), Failure);
assert_eq!(result.recv(), Failure);
}

#[test] #[should_fail]
fn test_back_to_the_future_result() {
let mut builder = task();
builder.future_result(util::ignore);
builder.future_result(util::ignore);
builder.future_result();
builder.future_result();
}

#[test]
Expand Down
11 changes: 4 additions & 7 deletions src/libstd/unstable/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,32 +580,29 @@ mod tests {
// Now try the same thing, but with the child task blocking.
let x = Exclusive::new(~~"hello");
let x2 = Cell::new(x.clone());
let mut res = None;
let mut builder = task::task();
builder.future_result(|r| res = Some(r));
let res = builder.future_result();
do builder.spawn {
let x2 = x2.take();
assert!(x2.unwrap() == ~~"hello");
}
// Have to get rid of our reference before blocking.
util::ignore(x);
res.unwrap().recv();
res.recv();
}

#[test] #[should_fail]
fn exclusive_new_unwrap_conflict() {
let x = Exclusive::new(~~"hello");
let x2 = Cell::new(x.clone());
let mut res = None;
let mut builder = task::task();
builder.future_result(|r| res = Some(r));
let res = builder.future_result();
do builder.spawn {
let x2 = x2.take();
assert!(x2.unwrap() == ~~"hello");
}
assert!(x.unwrap() == ~~"hello");
// See #4689 for why this can't be just "res.recv()".
assert!(res.unwrap().recv() == task::Success);
assert!(res.recv() == task::Success);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/msgsend-pipes-shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn run(args: &[~str]) {
for _ in range(0u, workers) {
let to_child = to_child.clone();
let mut builder = task::task();
builder.future_result(|r| worker_results.push(r));
worker_results.push(builder.future_result());
do builder.spawn {
for _ in range(0u, size / workers) {
//error2!("worker {:?}: sending {:?} bytes", i, num_bytes);
Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/msgsend-pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn run(args: &[~str]) {
for _ in range(0u, workers) {
let to_child = to_child.clone();
let mut builder = task::task();
builder.future_result(|r| worker_results.push(r));
worker_results.push(builder.future_result());
do builder.spawn {
for _ in range(0u, size / workers) {
//error2!("worker {:?}: sending {:?} bytes", i, num_bytes);
Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/shootout-pfib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fn stress(num_tasks: int) {
let mut results = ~[];
for i in range(0, num_tasks) {
let mut builder = task::task();
builder.future_result(|r| results.push(r));
results.push(builder.future_result());
do builder.spawn {
stress_task(i);
}
Expand Down
5 changes: 2 additions & 3 deletions src/test/bench/task-perf-linked-failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ fn grandchild_group(num_tasks: uint) {
}

fn spawn_supervised_blocking(myname: &str, f: ~fn()) {
let mut res = None;
let mut builder = task::task();
builder.future_result(|r| res = Some(r));
let res = builder.future_result();
builder.supervised();
builder.spawn(f);
error2!("{} group waiting", myname);
let x = res.unwrap().recv();
let x = res.recv();
assert_eq!(x, task::Success);
}

Expand Down
5 changes: 2 additions & 3 deletions src/test/run-pass/task-comm-12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ fn start(_task_number: int) { info2!("Started / Finished task."); }

fn test00() {
let i: int = 0;
let mut result = None;
let mut builder = task::task();
builder.future_result(|r| result = Some(r));
let result = builder.future_result();
do builder.spawn {
start(i)
}
Expand All @@ -33,7 +32,7 @@ fn test00() {
}

// Try joining tasks that have already finished.
result.unwrap().recv();
result.recv();

info2!("Joined task.");
}
2 changes: 1 addition & 1 deletion src/test/run-pass/task-comm-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn test00() {
while i < number_of_tasks {
let ch = ch.clone();
let mut builder = task::task();
builder.future_result(|r| results.push(r));
results.push(builder.future_result());
builder.spawn({
let i = i;
|| test00_start(&ch, i, number_of_messages)
Expand Down
5 changes: 2 additions & 3 deletions src/test/run-pass/task-comm-9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ fn test00() {
let (p, ch) = comm::stream();
let number_of_messages: int = 10;

let mut result = None;
let mut builder = task::task();
builder.future_result(|r| result = Some(r));
let result = builder.future_result();
do builder.spawn {
test00_start(&ch, number_of_messages);
}
Expand All @@ -42,7 +41,7 @@ fn test00() {
i += 1;
}

result.unwrap().recv();
result.recv();

assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2);
}
5 changes: 2 additions & 3 deletions src/test/run-pass/yield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@
use std::task;

pub fn main() {
let mut result = None;
let mut builder = task::task();
builder.future_result(|r| { result = Some(r); });
let result = builder.future_result();
builder.spawn(child);
error2!("1");
task::deschedule();
error2!("2");
task::deschedule();
error2!("3");
result.unwrap().recv();
result.recv();
}

fn child() {
Expand Down
5 changes: 2 additions & 3 deletions src/test/run-pass/yield1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
use std::task;

pub fn main() {
let mut result = None;
let mut builder = task::task();
builder.future_result(|r| { result = Some(r); });
let result = builder.future_result();
builder.spawn(child);
error2!("1");
task::deschedule();
result.unwrap().recv();
result.recv();
}

fn child() { error2!("2"); }