Skip to content
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

A small section of futures in the tutorial on tasks and correction to the doc in future.rs #6537

Closed
wants to merge 10 commits into from
72 changes: 59 additions & 13 deletions doc/tutorial-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,24 @@ in the core and standard libraries, which are still under development
and do not always present a consistent or complete interface.

For your reference, these are the standard modules involved in Rust
concurrency at this writing.
concurrency at this writing:

* [`core::task`] - All code relating to tasks and task scheduling
* [`core::comm`] - The message passing interface
* [`core::pipes`] - The underlying messaging infrastructure
* [`std::comm`] - Additional messaging types based on `core::pipes`
* [`std::sync`] - More exotic synchronization tools, including locks
* [`core::task`] - All code relating to tasks and task scheduling,
* [`core::comm`] - The message passing interface,
* [`core::pipes`] - The underlying messaging infrastructure,
* [`std::comm`] - Additional messaging types based on `core::pipes`,
* [`std::sync`] - More exotic synchronization tools, including locks,
* [`std::arc`] - The ARC (atomically reference counted) type,
for safely sharing immutable data
for safely sharing immutable data,
* [`std::future`] - A type representing values that may be computed concurrently and retrieved at a later time.

[`core::task`]: core/task.html
[`core::comm`]: core/comm.html
[`core::pipes`]: core/pipes.html
[`std::comm`]: std/comm.html
[`std::sync`]: std/sync.html
[`std::arc`]: std/arc.html
[`std::future`]: std/future.html

# Basics

Expand All @@ -70,7 +72,7 @@ closure in the new task.

~~~~
# use core::io::println;
use core::task::spawn;
# use core::task::spawn;

// Print something profound in a different task using a named function
fn print_message() { println("I am running in a different task!"); }
Expand Down Expand Up @@ -145,8 +147,8 @@ endpoint. Consider the following example of calculating two results
concurrently:

~~~~
use core::task::spawn;
use core::comm::{stream, Port, Chan};
# use core::task::spawn;
# use core::comm::{stream, Port, Chan};

let (port, chan): (Port<int>, Chan<int>) = stream();

Expand Down Expand Up @@ -233,7 +235,8 @@ Instead we can use a `SharedChan`, a type that allows a single

~~~
# use core::task::spawn;
use core::comm::{stream, SharedChan};
# use core::comm::{stream, SharedChan};
use core::comm::SharedChan;

let (port, chan) = stream();
let chan = SharedChan::new(chan);
Expand Down Expand Up @@ -282,6 +285,49 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() );
# fn some_expensive_computation(_i: uint) -> int { 42 }
~~~

## Futures
With `std::future`, rust has a mechanism for requesting a computation and getting the result
later.

The basic example below illustrates this.
~~~
fn fib(n: uint) -> uint {
// lengthy computation returning an uint
}

let mut delayed_fib = future::spawn (|| fib(5000) );
make_a_sandwich();
println(fmt!("fib(5000) = %?", delayed_fib.get()))
~~~

The call to `future::spawn` returns immediately a `future` object regardless of how long it
takes to run `fib(5000)`. You can then make yourself a sandwich while the computation of `fib` is
running. The result of the execution of the method is obtained by calling `get` on the future.
This call will block until the value is available (*i.e.* the computation is complete). Note that
the future needs to be mutable so that it can save the result for next time `get` is called.

Here is another example showing how futures allow you to background computations. The workload will
be distributed on the available cores.
~~~
fn partial_sum(start: uint) -> f64 {
let mut local_sum = 0f64;
for uint::range(start*100000, (start+1)*100000) |num| {
local_sum += (num as f64 + 1).pow(-2.0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a mistake on the gist btw, the + 1 here needs to be + 1.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I should have double-checked. I have just made a fix for it.

}
local_sum
}

fn main() {
let mut futures = vec::from_fn(1000, |ind| do std::future::spawn { partial_sum(ind) });

let mut final_res = 0f64;
for futures.each_mut |ft| {
final_res += ft.get();
}
println(fmt!("π^2/6 is not far from : %?", final_res));
}
~~~

# Handling task failure

Rust has a built-in mechanism for raising exceptions. The `fail!()` macro
Expand Down Expand Up @@ -363,8 +409,8 @@ either task fails, it kills the other one.
~~~
# fn sleep_forever() { loop { task::yield() } }
# do task::try {
do task::spawn {
do task::spawn {
do spawn {
do spawn {
fail!(); // All three tasks will fail.
}
sleep_forever(); // Will get woken up by force, then fail
Expand Down
12 changes: 6 additions & 6 deletions src/libstd/future.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -15,9 +15,9 @@
* # Example
*
* ~~~
* let delayed_fib = future::spawn {|| fib(5000) };
* let mut delayed_fib = future::spawn (|| fib(5000) );
* make_a_sandwich();
* io::println(fmt!("fib(5000) = %?", delayed_fib.get()))
* println(fmt!("fib(5000) = %?", delayed_fib.get()))
* ~~~
*/

Expand Down Expand Up @@ -51,7 +51,7 @@ priv enum FutureState<A> {
/// Methods on the `future` type
pub impl<A:Copy> Future<A> {
fn get(&mut self) -> A {
//! Get the value of the future
//! Get the value of the future.
*(self.get_ref())
}
}
Expand Down Expand Up @@ -87,7 +87,7 @@ pub impl<A> Future<A> {

pub fn from_value<A>(val: A) -> Future<A> {
/*!
* Create a future from a value
* Create a future from a value.
*
* The value is immediately available and calling `get` later will
* not block.
Expand Down Expand Up @@ -117,7 +117,7 @@ pub fn from_fn<A>(f: ~fn() -> A) -> Future<A> {
/*!
* Create a future from a function.
*
* The first time that the value is requested it will be retreived by
* The first time that the value is requested it will be retrieved by
* calling the function. Note that this function is a local
* function. It is not spawned into another task.
*/
Expand Down