@@ -3626,6 +3626,152 @@ guide](http://doc.rust-lang.org/guide-pointers.html#rc-and-arc).
3626
3626
3627
3627
# Tasks
3628
3628
3629
+ Concurrency and parallelism are topics that are of increasing interest to a
3630
+ broad subsection of software developers. Modern computers are often multi-core,
3631
+ to the point that even embedded devices like cell phones have more than one
3632
+ processor. Rust's semantics lend themselves very nicely to solving a number of
3633
+ issues that programmers have with concurrency. Many concurrency errors that are
3634
+ runtime errors in other languages are compile-time errors in Rust.
3635
+
3636
+ Rust's concurrency primitive is called a ** task** . Tasks are lightweight, and
3637
+ do not share memory in an unsafe manner, preferring message passing to
3638
+ communicate. It's worth noting that tasks are implemented as a library, and
3639
+ not part of the language. This means that in the future, other concurrency
3640
+ libraries can be written for Rust to help in specific scenarios. Here's an
3641
+ example of creating a task:
3642
+
3643
+ ``` {rust}
3644
+ spawn(proc() {
3645
+ println!("Hello from a task!");
3646
+ });
3647
+ ```
3648
+
3649
+ The ` spawn ` function takes a proc as an argument, and runs that proc in a new
3650
+ task. A proc takes ownership of its entire environment, and so any variables
3651
+ that you use inside the proc will not be usable afterward:
3652
+
3653
+ ``` {rust,ignore}
3654
+ let mut x = vec![1i, 2i, 3i];
3655
+
3656
+ spawn(proc() {
3657
+ println!("The value of x[0] is: {}", x[0]);
3658
+ });
3659
+
3660
+ println!("The value of x[0] is: {}", x[0]); // error: use of moved value: `x`
3661
+ ```
3662
+
3663
+ ` x ` is now owned by the proc, and so we can't use it anymore. Many other
3664
+ languages would let us do this, but it's not safe to do so. Rust's type system
3665
+ catches the error.
3666
+
3667
+ If tasks were only able to capture these values, they wouldn't be very useful.
3668
+ Luckily, tasks can communicate with each other through ** channel** s. Channels
3669
+ work like this:
3670
+
3671
+ ``` {rust}
3672
+ let (tx, rx) = channel();
3673
+
3674
+ spawn(proc() {
3675
+ tx.send("Hello from a task!".to_string());
3676
+ });
3677
+
3678
+ let message = rx.recv();
3679
+ println!("{}", message);
3680
+ ```
3681
+
3682
+ The ` channel() ` function returns two endpoints: a ` Receiver<T> ` and a
3683
+ ` Sender<T> ` . You can use the ` .send() ` method on the ` Sender<T> ` end, and
3684
+ receive the message on the ` Receiver<T> ` side with the ` recv() ` method. This
3685
+ method blocks until it gets a message. There's a similar method, ` .try_recv() ` ,
3686
+ which returns an ` Option<T> ` and does not block.
3687
+
3688
+ If you want to send messages to the task as well, create two channels!
3689
+
3690
+ ``` {rust}
3691
+ let (tx1, rx1) = channel();
3692
+ let (tx2, rx2) = channel();
3693
+
3694
+ spawn(proc() {
3695
+ tx1.send("Hello from a task!".to_string());
3696
+ let message = rx2.recv();
3697
+ println!("{}", message);
3698
+ });
3699
+
3700
+ let message = rx1.recv();
3701
+ println!("{}", message);
3702
+
3703
+ tx2.send("Goodbye from main!".to_string());
3704
+ ```
3705
+
3706
+ The proc has one sending end and one receiving end, and the main task has one
3707
+ of each as well. Now they can talk back and forth in whatever way they wish.
3708
+
3709
+ Notice as well that because ` Sender ` and ` Receiver ` are generic, while you can
3710
+ pass any kind of information through the channel, the ends are strongly typed.
3711
+ If you try to pass a string, and then an integer, Rust will complain.
3712
+
3713
+ ## Futures
3714
+
3715
+ With these basic primitives, many different concurrency patterns can be
3716
+ developed. Rust includes some of these types in its standard library. For
3717
+ example, if you wish to compute some value in the background, ` Future ` is
3718
+ a useful thing to use:
3719
+
3720
+ ``` {rust}
3721
+ use std::sync::Future;
3722
+
3723
+ let mut delayed_value = Future::spawn(proc() {
3724
+ // just return anything for examples' sake
3725
+
3726
+ 12345i
3727
+ });
3728
+ println!("value = {}", delayed_value.get());
3729
+ ```
3730
+
3731
+ Calling ` Future::spawn ` works just like ` spawn() ` : it takes a proc. In this
3732
+ case, though, you don't need to mess with the channel: just have the proc
3733
+ return the value.
3734
+
3735
+ ` Future::spawn ` will return a value which we can bind with ` let ` . It needs
3736
+ to be mutable, because once the value is computed, it saves a copy of the
3737
+ value, and if it were immutable, it couldn't update itself.
3738
+
3739
+ The proc will go on processing in the background, and when we need the final
3740
+ value, we can call ` get() ` on it. This will block until the result is done,
3741
+ but if it's finished computing in the background, we'll just get the value
3742
+ immediately.
3743
+
3744
+ ## Success and failure
3745
+
3746
+ Tasks don't always succeed, they can also fail. A task that wishes to fail
3747
+ can call the ` fail! ` macro, passing a message:
3748
+
3749
+ ``` {rust}
3750
+ spawn(proc() {
3751
+ fail!("Nope.");
3752
+ });
3753
+ ```
3754
+
3755
+ If a task fails, it is not possible for it to recover. However, it can
3756
+ notify other tasks that it has failed. We can do this with ` task::try ` :
3757
+
3758
+ ``` {rust}
3759
+ use std::task;
3760
+ use std::rand;
3761
+
3762
+ let result = task::try(proc() {
3763
+ if rand::random() {
3764
+ println!("OK");
3765
+ } else {
3766
+ fail!("oops!");
3767
+ }
3768
+ });
3769
+ ```
3770
+
3771
+ This task will randomly fail or succeed. ` task::try ` returns a ` Result `
3772
+ type, so we can handle the response like any other computation that may
3773
+ fail.
3774
+
3629
3775
# Macros
3630
3776
3631
3777
# Unsafe
0 commit comments