@@ -51,13 +51,15 @@ closure is limited to capturing `Send`-able data from its environment
51
51
ensures that ` spawn ` can safely move the entire closure and all its
52
52
associated state into an entirely different thread for execution.
53
53
54
- ``` {rust,ignore}
55
- # use std::thread::spawn;
56
- # fn generate_thread_number() -> int { 0 }
54
+ ``` rust
55
+ use std :: thread :: Thread ;
56
+
57
+ fn generate_thread_number () -> i32 { 4 } // a very simple generation
58
+
57
59
// Generate some state locally
58
60
let child_thread_number = generate_thread_number ();
59
61
60
- spawn(move || {
62
+ Thread :: spawn (move || {
61
63
// Capture it in the remote thread. The `move` keyword indicates
62
64
// that this closure should move `child_thread_number` into its
63
65
// environment, rather than capturing a reference into the
@@ -77,40 +79,44 @@ The simplest way to create a channel is to use the `channel` function to create
77
79
of a channel, and a * receiver* is the receiving endpoint. Consider the following
78
80
example of calculating two results concurrently:
79
81
80
- ``` {rust,ignore}
81
- # use std::thread::spawn;
82
+ ``` rust
83
+ use std :: thread :: Thread ;
84
+ use std :: sync :: mpsc;
82
85
83
- let (tx, rx): (Sender<int >, Receiver<int >) = channel();
86
+ let (tx , rx ): (mpsc :: Sender <u32 >, mpsc :: Receiver <u32 >) = mpsc :: channel ();
84
87
85
- spawn(move || {
88
+ Thread :: spawn (move || {
86
89
let result = some_expensive_computation ();
87
90
tx . send (result );
88
91
});
89
92
90
93
some_other_expensive_computation ();
91
94
let result = rx . recv ();
92
- # fn some_expensive_computation() -> int { 42 }
93
- # fn some_other_expensive_computation() {}
95
+
96
+ fn some_expensive_computation () -> u32 { 42 } // very expensive ;)
97
+ fn some_other_expensive_computation () {} // even more so
94
98
```
95
99
96
100
Let's examine this example in detail. First, the ` let ` statement creates a
97
101
stream for sending and receiving integers (the left-hand side of the ` let ` ,
98
102
` (tx, rx) ` , is an example of a destructuring let: the pattern separates a tuple
99
103
into its component parts).
100
104
101
- ``` {rust,ignore}
102
- let (tx, rx): (Sender<int>, Receiver<int>) = channel();
105
+ ``` rust
106
+ # use std :: sync :: mpsc;
107
+ let (tx , rx ): (mpsc :: Sender <u32 >, mpsc :: Receiver <u32 >) = mpsc :: channel ();
103
108
```
104
109
105
110
The child thread will use the sender to send data to the parent thread, which will
106
111
wait to receive the data on the receiver. The next statement spawns the child
107
112
thread.
108
113
109
- ``` {rust,ignore}
110
- # use std::thread::spawn;
111
- # fn some_expensive_computation() -> int { 42 }
112
- # let (tx, rx) = channel();
113
- spawn(move || {
114
+ ``` rust
115
+ # use std :: thread :: Thread ;
116
+ # use std :: sync :: mpsc;
117
+ # fn some_expensive_computation () -> u32 { 42 }
118
+ # let (tx , rx ) = mpsc :: channel ();
119
+ Thread :: spawn (move || {
114
120
let result = some_expensive_computation ();
115
121
tx . send (result );
116
122
});
@@ -125,9 +131,10 @@ computation, then sends the result over the captured channel.
125
131
Finally, the parent continues with some other expensive computation, then waits
126
132
for the child's result to arrive on the receiver:
127
133
128
- ``` {rust,ignore}
134
+ ``` rust
135
+ # use std :: sync :: mpsc;
129
136
# fn some_other_expensive_computation () {}
130
- # let (tx, rx) = channel::<int >();
137
+ # let (tx , rx ) = mpsc :: channel :: <u32 >();
131
138
# tx . send (0 );
132
139
some_other_expensive_computation ();
133
140
let result = rx . recv ();
@@ -140,8 +147,9 @@ single `Receiver` value. What if our example needed to compute multiple
140
147
results across a number of threads? The following program is ill-typed:
141
148
142
149
``` {rust,ignore}
143
- # fn some_expensive_computation() -> int { 42 }
144
- let (tx, rx) = channel();
150
+ # use std::sync::mpsc;
151
+ # fn some_expensive_computation() -> u32 { 42 }
152
+ let (tx, rx) = mpsc::channel();
145
153
146
154
spawn(move || {
147
155
tx.send(some_expensive_computation());
@@ -156,19 +164,22 @@ spawn(move || {
156
164
157
165
Instead we can clone the ` tx ` , which allows for multiple senders.
158
166
159
- ``` {rust,ignore}
160
- let (tx, rx) = channel();
167
+ ``` rust
168
+ use std :: thread :: Thread ;
169
+ use std :: sync :: mpsc;
170
+
171
+ let (tx , rx ) = mpsc :: channel ();
161
172
162
- for init_val in range(0u, 3) {
173
+ for init_val in 0 .. 3 {
163
174
// Create a new channel handle to distribute to the child thread
164
175
let child_tx = tx . clone ();
165
- spawn(move || {
176
+ Thread :: spawn (move || {
166
177
child_tx . send (some_expensive_computation (init_val ));
167
178
});
168
179
}
169
180
170
- let result = rx.recv() + rx.recv() + rx.recv();
171
- # fn some_expensive_computation(_i: uint ) -> int { 42 }
181
+ let result = rx . recv (). unwrap () + rx . recv (). unwrap () + rx . recv () . unwrap ();
182
+ # fn some_expensive_computation (_i : u32 ) -> u32 { 42 }
172
183
```
173
184
174
185
Cloning a ` Sender ` produces a new handle to the same channel, allowing multiple
@@ -181,21 +192,22 @@ Note that the above cloning example is somewhat contrived since you could also
181
192
simply use three ` Sender ` pairs, but it serves to illustrate the point. For
182
193
reference, written with multiple streams, it might look like the example below.
183
194
184
- ``` {rust,ignore}
185
- # use std::thread::spawn;
195
+ ``` rust
196
+ use std :: thread :: Thread ;
197
+ use std :: sync :: mpsc;
186
198
187
199
// Create a vector of ports, one for each child thread
188
- let rxs = Vec::from_fn(3, | init_val| {
189
- let (tx, rx) = channel();
190
- spawn(move || {
200
+ let rxs = ( 0 .. 3 ) . map ( | & : init_val | {
201
+ let (tx , rx ) = mpsc :: channel ();
202
+ Thread :: spawn (move || {
191
203
tx . send (some_expensive_computation (init_val ));
192
204
});
193
205
rx
194
- });
206
+ }). collect :: < Vec < _ >>() ;
195
207
196
208
// Wait on each port, accumulating the results
197
- let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
198
- # fn some_expensive_computation(_i: uint ) -> int { 42 }
209
+ let result = rxs . iter (). fold (0 , | & : accum , rx | accum + rx . recv () . unwrap () );
210
+ # fn some_expensive_computation (_i : u32 ) -> u32 { 42 }
199
211
```
200
212
201
213
## Backgrounding computations: Futures
0 commit comments