about summary refs log tree commit diff
path: root/src/doc/guide-tasks.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/guide-tasks.md')
-rw-r--r--src/doc/guide-tasks.md50
1 files changed, 28 insertions, 22 deletions
diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md
index c2309ba479e..1938d3e3878 100644
--- a/src/doc/guide-tasks.md
+++ b/src/doc/guide-tasks.md
@@ -29,10 +29,11 @@ with a closure argument. `spawn` executes the closure in the new task.
 fn print_message() { println!("I am running in a different task!"); }
 spawn(print_message);
 
-// Alternatively, use a `proc` expression instead of a named function.
-// The `proc` expression evaluates to an (unnamed) proc.
-// That proc will call `println!(...)` when the spawned task runs.
-spawn(proc() println!("I am also running in a different task!") );
+// Alternatively, use a `move ||` expression instead of a named function.
+// `||` expressions evaluate to an unnamed closures. The `move` keyword
+// indicates that the closure should take ownership of any variables it
+// touches.
+spawn(move || println!("I am also running in a different task!"));
 ```
 
 In Rust, a task is not a concept that appears in the language semantics.
@@ -40,11 +41,13 @@ Instead, Rust's type system provides all the tools necessary to implement safe
 concurrency: particularly, ownership. The language leaves the implementation
 details to the standard library.
 
-The `spawn` function has a very simple type signature: `fn spawn(f: proc():
-Send)`. Because it accepts only procs, and procs contain only owned data,
-`spawn` can safely move the entire proc and all its associated state into an
-entirely different task for execution. Like any closure, the function passed to
-`spawn` may capture an environment that it carries across tasks.
+The `spawn` function has the type signature: `fn
+spawn<F:FnOnce()+Send>(f: F)`.  This indicates that it takes as
+argument a closure (of type `F`) that it will run exactly once. This
+closure is limited to capturing `Send`-able data form its environment
+(that is, data which is deeply owned). Limiting the closure to `Send`
+ensures that `spawn` can safely move the entire closure and all its
+associated state into an entirely different task for execution.
 
 ```{rust}
 # use std::task::spawn;
@@ -52,8 +55,11 @@ entirely different task for execution. Like any closure, the function passed to
 // Generate some state locally
 let child_task_number = generate_task_number();
 
-spawn(proc() {
-    // Capture it in the remote task
+spawn(move || {
+    // Capture it in the remote task. The `move` keyword indicates
+    // that this closure should move `child_task_number` into its
+    // environment, rather than capturing a reference into the
+    // enclosing stack frame.
     println!("I am child number {}", child_task_number);
 });
 ```
@@ -74,7 +80,7 @@ example of calculating two results concurrently:
 
 let (tx, rx): (Sender<int>, Receiver<int>) = channel();
 
-spawn(proc() {
+spawn(move || {
     let result = some_expensive_computation();
     tx.send(result);
 });
@@ -102,7 +108,7 @@ task.
 # use std::task::spawn;
 # fn some_expensive_computation() -> int { 42 }
 # let (tx, rx) = channel();
-spawn(proc() {
+spawn(move || {
     let result = some_expensive_computation();
     tx.send(result);
 });
@@ -135,13 +141,13 @@ results across a number of tasks? The following program is ill-typed:
 # fn some_expensive_computation() -> int { 42 }
 let (tx, rx) = channel();
 
-spawn(proc() {
+spawn(move || {
     tx.send(some_expensive_computation());
 });
 
 // ERROR! The previous spawn statement already owns the sender,
 // so the compiler will not allow it to be captured again
-spawn(proc() {
+spawn(move || {
     tx.send(some_expensive_computation());
 });
 ```
@@ -154,7 +160,7 @@ let (tx, rx) = channel();
 for init_val in range(0u, 3) {
     // Create a new channel handle to distribute to the child task
     let child_tx = tx.clone();
-    spawn(proc() {
+    spawn(move || {
         child_tx.send(some_expensive_computation(init_val));
     });
 }
@@ -179,7 +185,7 @@ reference, written with multiple streams, it might look like the example below.
 // Create a vector of ports, one for each child task
 let rxs = Vec::from_fn(3, |init_val| {
     let (tx, rx) = channel();
-    spawn(proc() {
+    spawn(move || {
         tx.send(some_expensive_computation(init_val));
     });
     rx
@@ -207,7 +213,7 @@ fn fib(n: u64) -> u64 {
     12586269025
 }
 
-let mut delayed_fib = Future::spawn(proc() fib(50));
+let mut delayed_fib = Future::spawn(move || fib(50));
 make_a_sandwich();
 println!("fib(50) = {}", delayed_fib.get())
 # }
@@ -236,7 +242,7 @@ fn partial_sum(start: uint) -> f64 {
 }
 
 fn main() {
-    let mut futures = Vec::from_fn(200, |ind| Future::spawn( proc() { partial_sum(ind) }));
+    let mut futures = Vec::from_fn(200, |ind| Future::spawn(move || partial_sum(ind)));
 
     let mut final_res = 0f64;
     for ft in futures.iter_mut()  {
@@ -278,7 +284,7 @@ fn main() {
     for num in range(1u, 10) {
         let task_numbers = numbers_arc.clone();
 
-        spawn(proc() {
+        spawn(move || {
             println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
         });
     }
@@ -312,7 +318,7 @@ if it were local.
 # let numbers_arc = Arc::new(numbers);
 # let num = 4;
 let task_numbers = numbers_arc.clone();
-spawn(proc() {
+spawn(move || {
     // Capture task_numbers and use it as if it was the underlying vector
     println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
 });
@@ -344,7 +350,7 @@ result with an `int` field (representing a successful result) or an `Err` result
 # use std::task;
 # fn some_condition() -> bool { false }
 # fn calculate_result() -> int { 0 }
-let result: Result<int, Box<std::any::Any + Send>> = task::try(proc() {
+let result: Result<int, Box<std::any::Any + Send>> = task::try(move || {
     if some_condition() {
         calculate_result()
     } else {