@@ -48,8 +48,8 @@ concurrency at this writing:
48
48
* [ ` std::task ` ] - All code relating to tasks and task scheduling,
49
49
* [ ` std::comm ` ] - The message passing interface,
50
50
* [ ` sync::DuplexStream ` ] - An extension of ` pipes::stream ` that allows both sending and receiving,
51
- * [ ` sync::SyncChan ` ] - An extension of ` pipes::stream ` that provides synchronous message sending,
52
- * [ ` sync::SyncPort ` ] - An extension of ` pipes::stream ` that acknowledges each message received,
51
+ * [ ` sync::SyncSender ` ] - An extension of ` pipes::stream ` that provides synchronous message sending,
52
+ * [ ` sync::SyncReceiver ` ] - An extension of ` pipes::stream ` that acknowledges each message received,
53
53
* [ ` sync::rendezvous ` ] - Creates a stream whose channel, upon sending a message, blocks until the
54
54
message is received.
55
55
* [ ` sync::Arc ` ] - The Arc (atomically reference counted) type, for safely sharing immutable data,
@@ -70,8 +70,8 @@ concurrency at this writing:
70
70
[ `std::task` ] : std/task/index.html
71
71
[ `std::comm` ] : std/comm/index.html
72
72
[ `sync::DuplexStream` ] : sync/struct.DuplexStream.html
73
- [ `sync::SyncChan ` ] : sync/struct.SyncChan .html
74
- [ `sync::SyncPort ` ] : sync/struct.SyncPort .html
73
+ [ `sync::SyncSender ` ] : sync/struct.SyncSender .html
74
+ [ `sync::SyncReceiver ` ] : sync/struct.SyncReceiver .html
75
75
[ `sync::rendezvous` ] : sync/fn.rendezvous.html
76
76
[ `sync::Arc` ] : sync/struct.Arc.html
77
77
[ `sync::RWArc` ] : sync/struct.RWArc.html
@@ -141,118 +141,115 @@ receiving messages. Pipes are low-level communication building-blocks and so
141
141
come in a variety of forms, each one appropriate for a different use case. In
142
142
what follows, we cover the most commonly used varieties.
143
143
144
- The simplest way to create a pipe is to use ` Chan::new `
145
- function to create a ` (Port, Chan ) ` pair. In Rust parlance, a * channel *
146
- is a sending endpoint of a pipe, and a * port * is the receiving
144
+ The simplest way to create a pipe is to use the ` channel `
145
+ function to create a ` (Sender, Receiver ) ` pair. In Rust parlance, a * sender *
146
+ is a sending endpoint of a pipe, and a * receiver * is the receiving
147
147
endpoint. Consider the following example of calculating two results
148
148
concurrently:
149
149
150
150
~~~~
151
151
# use std::task::spawn;
152
152
153
- let (port, chan ): (Port <int>, Chan <int>) = Chan::new ();
153
+ let (tx, rx ): (Sender <int>, Receiver <int>) = channel ();
154
154
155
155
spawn(proc() {
156
156
let result = some_expensive_computation();
157
- chan .send(result);
157
+ tx .send(result);
158
158
});
159
159
160
160
some_other_expensive_computation();
161
- let result = port .recv();
161
+ let result = rx .recv();
162
162
# fn some_expensive_computation() -> int { 42 }
163
163
# fn some_other_expensive_computation() {}
164
164
~~~~
165
165
166
166
Let's examine this example in detail. First, the ` let ` statement creates a
167
167
stream for sending and receiving integers (the left-hand side of the ` let ` ,
168
- ` (chan, port ) ` , is an example of a * destructuring let* : the pattern separates
168
+ ` (tx, rx ) ` , is an example of a * destructuring let* : the pattern separates
169
169
a tuple into its component parts).
170
170
171
171
~~~~
172
- let (port, chan ): (Port <int>, Chan <int>) = Chan::new ();
172
+ let (tx, rx ): (Sender <int>, Receiver <int>) = channel ();
173
173
~~~~
174
174
175
- The child task will use the channel to send data to the parent task,
176
- which will wait to receive the data on the port . The next statement
175
+ The child task will use the sender to send data to the parent task,
176
+ which will wait to receive the data on the receiver . The next statement
177
177
spawns the child task.
178
178
179
179
~~~~
180
180
# use std::task::spawn;
181
181
# fn some_expensive_computation() -> int { 42 }
182
- # let (port, chan ) = Chan::new ();
182
+ # let (tx, rx ) = channel ();
183
183
spawn(proc() {
184
184
let result = some_expensive_computation();
185
- chan .send(result);
185
+ tx .send(result);
186
186
});
187
187
~~~~
188
188
189
- Notice that the creation of the task closure transfers ` chan ` to the child
190
- task implicitly: the closure captures ` chan ` in its environment. Both ` Chan `
191
- and ` Port ` are sendable types and may be captured into tasks or otherwise
189
+ Notice that the creation of the task closure transfers ` tx ` to the child
190
+ task implicitly: the closure captures ` tx ` in its environment. Both ` Sender `
191
+ and ` Receiver ` are sendable types and may be captured into tasks or otherwise
192
192
transferred between them. In the example, the child task runs an expensive
193
193
computation, then sends the result over the captured channel.
194
194
195
195
Finally, the parent continues with some other expensive
196
196
computation, then waits for the child's result to arrive on the
197
- port :
197
+ receiver :
198
198
199
199
~~~~
200
200
# fn some_other_expensive_computation() {}
201
- # let (port, chan ) = Chan ::<int>::new ();
202
- # chan .send(0);
201
+ # let (tx, rx ) = channel ::<int>();
202
+ # tx .send(0);
203
203
some_other_expensive_computation();
204
- let result = port .recv();
204
+ let result = rx .recv();
205
205
~~~~
206
206
207
- The ` Port ` and ` Chan ` pair created by ` Chan::new ` enables efficient
207
+ The ` Sender ` and ` Receiver ` pair created by ` channel ` enables efficient
208
208
communication between a single sender and a single receiver, but multiple
209
- senders cannot use a single ` Chan ` , and multiple receivers cannot use a single
210
- ` Port ` . What if our example needed to compute multiple results across a number
211
- of tasks? The following program is ill-typed:
209
+ senders cannot use a single ` Sender ` value , and multiple receivers cannot use a
210
+ single ` Receiver ` value . What if our example needed to compute multiple
211
+ results across a number of tasks? The following program is ill-typed:
212
212
213
213
~~~ {.ignore}
214
- # use std::task::{spawn};
215
214
# fn some_expensive_computation() -> int { 42 }
216
- let (port, chan ) = Chan::new ();
215
+ let (tx, rx ) = channel ();
217
216
218
217
spawn(proc() {
219
- chan .send(some_expensive_computation());
218
+ tx .send(some_expensive_computation());
220
219
});
221
220
222
- // ERROR! The previous spawn statement already owns the channel ,
221
+ // ERROR! The previous spawn statement already owns the sender ,
223
222
// so the compiler will not allow it to be captured again
224
223
spawn(proc() {
225
- chan .send(some_expensive_computation());
224
+ tx .send(some_expensive_computation());
226
225
});
227
226
~~~
228
227
229
- Instead we can clone the ` chan ` , which allows for multiple senders.
228
+ Instead we can clone the ` tx ` , which allows for multiple senders.
230
229
231
230
~~~
232
- # use std::task::spawn;
233
-
234
- let (port, chan) = Chan::new();
231
+ let (tx, rx) = channel();
235
232
236
233
for init_val in range(0u, 3) {
237
234
// Create a new channel handle to distribute to the child task
238
- let child_chan = chan .clone();
235
+ let child_tx = tx .clone();
239
236
spawn(proc() {
240
- child_chan .send(some_expensive_computation(init_val));
237
+ child_tx .send(some_expensive_computation(init_val));
241
238
});
242
239
}
243
240
244
- let result = port .recv() + port .recv() + port .recv();
241
+ let result = rx .recv() + rx .recv() + rx .recv();
245
242
# fn some_expensive_computation(_i: uint) -> int { 42 }
246
243
~~~
247
244
248
- Cloning a ` Chan ` produces a new handle to the same channel, allowing multiple
249
- tasks to send data to a single port . It also upgrades the channel internally in
245
+ Cloning a ` Sender ` produces a new handle to the same channel, allowing multiple
246
+ tasks to send data to a single receiver . It upgrades the channel internally in
250
247
order to allow this functionality, which means that channels that are not
251
248
cloned can avoid the overhead required to handle multiple senders. But this
252
249
fact has no bearing on the channel's usage: the upgrade is transparent.
253
250
254
251
Note that the above cloning example is somewhat contrived since
255
- you could also simply use three ` Chan ` pairs, but it serves to
252
+ you could also simply use three ` Sender ` pairs, but it serves to
256
253
illustrate the point. For reference, written with multiple streams, it
257
254
might look like the example below.
258
255
@@ -261,16 +258,16 @@ might look like the example below.
261
258
# use std::vec;
262
259
263
260
// Create a vector of ports, one for each child task
264
- let ports = vec::from_fn(3, |init_val| {
265
- let (port, chan ) = Chan::new ();
261
+ let rxs = vec::from_fn(3, |init_val| {
262
+ let (tx, rx ) = channel ();
266
263
spawn(proc() {
267
- chan .send(some_expensive_computation(init_val));
264
+ tx .send(some_expensive_computation(init_val));
268
265
});
269
- port
266
+ rx
270
267
});
271
268
272
269
// Wait on each port, accumulating the results
273
- let result = ports .iter().fold(0, |accum, port | accum + port .recv() );
270
+ let result = rxs .iter().fold(0, |accum, rx | accum + rx .recv() );
274
271
# fn some_expensive_computation(_i: uint) -> int { 42 }
275
272
~~~
276
273
@@ -281,7 +278,7 @@ later.
281
278
The basic example below illustrates this.
282
279
283
280
~~~
284
- # extern crate sync;
281
+ extern crate sync;
285
282
286
283
# fn main() {
287
284
# fn make_a_sandwich() {};
@@ -342,9 +339,10 @@ Here is a small example showing how to use Arcs. We wish to run concurrently sev
342
339
a single large vector of floats. Each task needs the full vector to perform its duty.
343
340
344
341
~~~
345
- # extern crate sync;
346
- extern crate rand;
347
- # use std::vec;
342
+ extern crate rand;
343
+ extern crate sync;
344
+
345
+ use std::vec;
348
346
use sync::Arc;
349
347
350
348
fn pnorm(nums: &~[f64], p: uint) -> f64 {
@@ -358,11 +356,11 @@ fn main() {
358
356
let numbers_arc = Arc::new(numbers);
359
357
360
358
for num in range(1u, 10) {
361
- let (port, chan) = Chan::new ();
362
- chan .send(numbers_arc.clone());
359
+ let (tx, rx) = channel ();
360
+ tx .send(numbers_arc.clone());
363
361
364
362
spawn(proc() {
365
- let local_arc : Arc<~[f64]> = port .recv();
363
+ let local_arc : Arc<~[f64]> = rx .recv();
366
364
let task_numbers = local_arc.get();
367
365
println!("{}-norm = {}", num, pnorm(task_numbers, num));
368
366
});
@@ -395,8 +393,8 @@ and a clone of it is sent to each task
395
393
# fn main() {
396
394
# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
397
395
# let numbers_arc = Arc::new(numbers);
398
- # let (port, chan) = Chan::new ();
399
- chan .send(numbers_arc.clone());
396
+ # let (tx, rx) = channel ();
397
+ tx .send(numbers_arc.clone());
400
398
# }
401
399
~~~
402
400
@@ -412,9 +410,9 @@ Each task recovers the underlying data by
412
410
# fn main() {
413
411
# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
414
412
# let numbers_arc=Arc::new(numbers);
415
- # let (port, chan) = Chan::new ();
416
- # chan .send(numbers_arc.clone());
417
- # let local_arc : Arc<~[f64]> = port .recv();
413
+ # let (tx, rx) = channel ();
414
+ # tx .send(numbers_arc.clone());
415
+ # let local_arc : Arc<~[f64]> = rx .recv();
418
416
let task_numbers = local_arc.get();
419
417
# }
420
418
~~~
@@ -486,19 +484,18 @@ proceed).
486
484
487
485
A very common thing to do is to spawn a child task where the parent
488
486
and child both need to exchange messages with each other. The
489
- function ` sync::comm::DuplexStream() ` supports this pattern. We'll
487
+ function ` sync::comm::duplex ` supports this pattern. We'll
490
488
look briefly at how to use it.
491
489
492
- To see how ` DuplexStream() ` works, we will create a child task
490
+ To see how ` duplex ` works, we will create a child task
493
491
that repeatedly receives a ` uint ` message, converts it to a string, and sends
494
492
the string in response. The child terminates when it receives ` 0 ` .
495
493
Here is the function that implements the child task:
496
494
497
495
~~~
498
- # extern crate sync;
496
+ extern crate sync;
499
497
# fn main() {
500
- # use sync::DuplexStream;
501
- fn stringifier(channel: &DuplexStream<~str, uint>) {
498
+ fn stringifier(channel: &sync::DuplexStream<~str, uint>) {
502
499
let mut value: uint;
503
500
loop {
504
501
value = channel.recv();
@@ -520,10 +517,10 @@ response itself is simply the stringified version of the received value,
520
517
Here is the code for the parent task:
521
518
522
519
~~~
523
- # extern crate sync;
520
+ extern crate sync;
524
521
# use std::task::spawn;
525
522
# use sync::DuplexStream;
526
- # fn stringifier(channel: &DuplexStream<~ str, uint>) {
523
+ # fn stringifier(channel: &sync:: DuplexStream<~ str, uint>) {
527
524
# let mut value: uint;
528
525
# loop {
529
526
# value = channel.recv();
@@ -533,7 +530,7 @@ Here is the code for the parent task:
533
530
# }
534
531
# fn main() {
535
532
536
- let (from_child, to_child) = DuplexStream::new ();
533
+ let (from_child, to_child) = sync::duplex ();
537
534
538
535
spawn(proc() {
539
536
stringifier(&to_child);
0 commit comments