mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-15 18:15:01 +00:00
auto merge of #6565 : osaut/rust/futures, r=thestinger
* The example given in future.rs was corrected. * I have added a small section describing futures in tutorial on tasks. It is far from being complete as I am stil learning ! (This is an updated version of PR 6537).
This commit is contained in:
commit
3a323c1b2d
@ -43,15 +43,16 @@ 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
|
||||
@ -59,6 +60,7 @@ concurrency at this writing.
|
||||
[`std::comm`]: std/comm.html
|
||||
[`std::sync`]: std/sync.html
|
||||
[`std::arc`]: std/arc.html
|
||||
[`std::future`]: std/future.html
|
||||
|
||||
# Basics
|
||||
|
||||
@ -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!"); }
|
||||
@ -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();
|
||||
|
||||
@ -233,7 +235,7 @@ 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};
|
||||
|
||||
let (port, chan) = stream();
|
||||
let chan = SharedChan::new(chan);
|
||||
@ -282,6 +284,51 @@ 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 make_a_sandwich() {};
|
||||
fn fib(n: uint) -> uint {
|
||||
// lengthy computation returning an uint
|
||||
12586269025
|
||||
}
|
||||
|
||||
let mut delayed_fib = std::future::spawn (|| fib(50) );
|
||||
make_a_sandwich();
|
||||
println(fmt!("fib(50) = %?", delayed_fib.get()))
|
||||
~~~
|
||||
|
||||
The call to `future::spawn` returns immediately a `future` object regardless of how long it
|
||||
takes to run `fib(50)`. 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.0).pow(-2.0);
|
||||
}
|
||||
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
|
||||
@ -363,8 +410,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
|
||||
|
@ -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.
|
||||
//
|
||||
@ -15,9 +15,11 @@
|
||||
* # Example
|
||||
*
|
||||
* ~~~
|
||||
* let delayed_fib = future::spawn {|| fib(5000) };
|
||||
* # fn fib(n: uint) -> uint {42};
|
||||
* # fn make_a_sandwich() {};
|
||||
* let mut delayed_fib = std::future::spawn (|| fib(5000) );
|
||||
* make_a_sandwich();
|
||||
* io::println(fmt!("fib(5000) = %?", delayed_fib.get()))
|
||||
* println(fmt!("fib(5000) = %?", delayed_fib.get()))
|
||||
* ~~~
|
||||
*/
|
||||
|
||||
@ -51,7 +53,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())
|
||||
}
|
||||
}
|
||||
@ -87,7 +89,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.
|
||||
@ -117,7 +119,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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user