about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-18 04:07:27 -0700
committerbors <bors@rust-lang.org>2013-05-18 04:07:27 -0700
commit3a323c1b2d755b86b1987bba3454bb2f0f92b1c8 (patch)
treef40a70ca983986a7333a3764dd95887e208fef11
parenteb0e2f45ec5eb84ac3b30e7ce92fb70415d232d3 (diff)
parent4b13895c2f43024b2b0986d4c2ddcb742926c3c6 (diff)
downloadrust-3a323c1b2d755b86b1987bba3454bb2f0f92b1c8.tar.gz
rust-3a323c1b2d755b86b1987bba3454bb2f0f92b1c8.zip
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).
-rw-r--r--doc/tutorial-tasks.md73
-rw-r--r--src/libstd/future.rs14
2 files changed, 68 insertions, 19 deletions
diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md
index 402cfa84afc..c9e0377dd13 100644
--- a/doc/tutorial-tasks.md
+++ b/doc/tutorial-tasks.md
@@ -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
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index be33c0f4663..ef9318e8d3d 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -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.
      */