@@ -39,26 +39,51 @@ data through the global _exchange heap_.
3939
4040While Rust's type system provides the building blocks needed for safe
4141and efficient tasks, all of the task functionality itself is implemented
42- in the standard and extra libraries, which are still under development
42+ in the standard and sync libraries, which are still under development
4343and do not always present a consistent or complete interface.
4444
4545For your reference, these are the standard modules involved in Rust
4646concurrency at this writing:
4747
4848* [ ` std::task ` ] - All code relating to tasks and task scheduling,
4949* [ ` std::comm ` ] - The message passing interface,
50- * [ ` extra::comm ` ] - Additional messaging types based on ` std::comm ` ,
51- * [ ` extra::sync ` ] - More exotic synchronization tools, including locks,
52- * [ ` extra::arc ` ] - The Arc (atomically reference counted) type,
53- for safely sharing immutable data,
54- * [ ` extra::future ` ] - A type representing values that may be computed concurrently and retrieved at a later time.
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,
53+ * [ ` sync::rendezvous ` ] - Creates a stream whose channel, upon sending a message, blocks until the
54+ message is received.
55+ * [ ` sync::Arc ` ] - The Arc (atomically reference counted) type, for safely sharing immutable data,
56+ * [ ` sync::RWArc ` ] - A dual-mode Arc protected by a reader-writer lock,
57+ * [ ` sync::MutexArc ` ] - An Arc with mutable data protected by a blocking mutex,
58+ * [ ` sync::Semaphore ` ] - A counting, blocking, bounded-waiting semaphore,
59+ * [ ` sync::Mutex ` ] - A blocking, bounded-waiting, mutual exclusion lock with an associated
60+ FIFO condition variable,
61+ * [ ` sync::RWLock ` ] - A blocking, no-starvation, reader-writer lock with an associated condvar,
62+ * [ ` sync::Barrier ` ] - A barrier enables multiple tasks to synchronize the beginning
63+ of some computation,
64+ * [ ` sync::TaskPool ` ] - A task pool abstraction,
65+ * [ ` sync::Future ` ] - A type encapsulating the result of a computation which may not be complete,
66+ * [ ` sync::one ` ] - A "once initialization" primitive
67+ * [ ` sync::mutex ` ] - A proper mutex implementation regardless of the "flavor of task" which is
68+ acquiring the lock.
5569
5670[ `std::task` ] : std/task/index.html
5771[ `std::comm` ] : std/comm/index.html
58- [ `extra::comm` ] : extra/comm/index.html
59- [ `extra::sync` ] : extra/sync/index.html
60- [ `extra::arc` ] : extra/arc/index.html
61- [ `extra::future` ] : extra/future/index.html
72+ [ `sync::DuplexStream` ] : sync/struct.DuplexStream.html
73+ [ `sync::SyncChan` ] : sync/struct.SyncChan.html
74+ [ `sync::SyncPort` ] : sync/struct.SyncPort.html
75+ [ `sync::rendezvous` ] : sync/fn.rendezvous.html
76+ [ `sync::Arc` ] : sync/struct.Arc.html
77+ [ `sync::RWArc` ] : sync/struct.RWArc.html
78+ [ `sync::MutexArc` ] : sync/struct.MutexArc.html
79+ [ `sync::Semaphore` ] : sync/struct.Semaphore.html
80+ [ `sync::Mutex` ] : sync/struct.Mutex.html
81+ [ `sync::RWLock` ] : sync/struct.RWLock.html
82+ [ `sync::Barrier` ] : sync/struct.Barrier.html
83+ [ `sync::TaskPool` ] : sync/struct.TaskPool.html
84+ [ `sync::Future` ] : sync/struct.Future.html
85+ [ `sync::one` ] : sync/one/index.html
86+ [ `sync::mutex` ] : sync/mutex/index.html
6287
6388# Basics
6489
@@ -254,21 +279,25 @@ let result = ports.iter().fold(0, |accum, port| accum + port.recv() );
254279~~~
255280
256281## Backgrounding computations: Futures
257- With ` extra::future ` , rust has a mechanism for requesting a computation and getting the result
282+ With ` sync::Future ` , rust has a mechanism for requesting a computation and getting the result
258283later.
259284
260285The basic example below illustrates this.
261286
262287~~~
288+ # extern mod sync;
289+
290+ # fn main() {
263291# fn make_a_sandwich() {};
264292fn fib(n: u64) -> u64 {
265293 // lengthy computation returning an uint
266294 12586269025
267295}
268296
269- let mut delayed_fib = extra::future ::Future::spawn(proc() fib(50));
297+ let mut delayed_fib = sync ::Future::spawn(proc() fib(50));
270298make_a_sandwich();
271299println!("fib(50) = {:?}", delayed_fib.get())
300+ # }
272301~~~
273302
274303The call to ` future::spawn ` returns immediately a ` future ` object regardless of how long it
@@ -281,6 +310,7 @@ Here is another example showing how futures allow you to background computations
281310be distributed on the available cores.
282311
283312~~~
313+ # extern mod sync;
284314# use std::vec;
285315fn partial_sum(start: uint) -> f64 {
286316 let mut local_sum = 0f64;
@@ -291,7 +321,7 @@ fn partial_sum(start: uint) -> f64 {
291321}
292322
293323fn main() {
294- let mut futures = vec::from_fn(1000, |ind| extra::future ::Future::spawn( proc() { partial_sum(ind) }));
324+ let mut futures = vec::from_fn(1000, |ind| sync ::Future::spawn( proc() { partial_sum(ind) }));
295325
296326 let mut final_res = 0f64;
297327 for ft in futures.mut_iter() {
@@ -309,16 +339,17 @@ add up to a significant amount of wasted memory and would require copying the sa
309339necessary.
310340
311341To tackle this issue, one can use an Atomically Reference Counted wrapper (` Arc ` ) as implemented in
312- the ` extra ` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
342+ the ` sync ` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
313343acts as a reference to the shared data and only this reference is shared and cloned.
314344
315345Here is a small example showing how to use Arcs. We wish to run concurrently several computations on
316346a single large vector of floats. Each task needs the full vector to perform its duty.
317347
318348~~~
349+ # extern mod sync;
319350# use std::vec;
320351# use std::rand;
321- use extra::arc ::Arc;
352+ use sync ::Arc;
322353
323354fn pnorm(nums: &~[f64], p: uint) -> f64 {
324355 nums.iter().fold(0.0, |a,b| a+(*b).powf(&(p as f64)) ).powf(&(1.0 / (p as f64)))
@@ -348,39 +379,48 @@ at the power given as argument and takes the inverse power of this value). The A
348379created by the line
349380
350381~~~
351- # use extra::arc::Arc;
382+ # extern mod sync;
383+ # use sync::Arc;
352384# use std::vec;
353385# use std::rand;
386+ # fn main() {
354387# let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
355388let numbers_arc=Arc::new(numbers);
389+ # }
356390~~~
357391
358392and a clone of it is sent to each task
359393
360394~~~
361- # use extra::arc::Arc;
395+ # extern mod sync;
396+ # use sync::Arc;
362397# use std::vec;
363398# use std::rand;
399+ # fn main() {
364400# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
365401# let numbers_arc = Arc::new(numbers);
366402# let (port, chan) = Chan::new();
367403chan.send(numbers_arc.clone());
404+ # }
368405~~~
369406
370407copying only the wrapper and not its contents.
371408
372409Each task recovers the underlying data by
373410
374411~~~
375- # use extra::arc::Arc;
412+ # extern mod sync;
413+ # use sync::Arc;
376414# use std::vec;
377415# use std::rand;
416+ # fn main() {
378417# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
379418# let numbers_arc=Arc::new(numbers);
380419# let (port, chan) = Chan::new();
381420# chan.send(numbers_arc.clone());
382421# let local_arc : Arc<~[f64]> = port.recv();
383422let task_numbers = local_arc.get();
423+ # }
384424~~~
385425
386426and can use it as if it were local.
@@ -450,25 +490,27 @@ proceed).
450490
451491A very common thing to do is to spawn a child task where the parent
452492and child both need to exchange messages with each other. The
453- function ` extra ::comm::DuplexStream()` supports this pattern. We'll
493+ function ` sync ::comm::DuplexStream()` supports this pattern. We'll
454494look briefly at how to use it.
455495
456496To see how ` DuplexStream() ` works, we will create a child task
457497that repeatedly receives a ` uint ` message, converts it to a string, and sends
458498the string in response. The child terminates when it receives ` 0 ` .
459499Here is the function that implements the child task:
460500
461- ~~~ {.ignore .linked-failure}
462- # use extra::comm::DuplexStream;
463- # use std::uint;
464- fn stringifier(channel: &DuplexStream<~str, uint>) {
465- let mut value: uint;
466- loop {
467- value = channel.recv();
468- channel.send(uint::to_str(value));
469- if value == 0 { break; }
501+ ~~~
502+ # extern mod sync;
503+ # fn main() {
504+ # use sync::DuplexStream;
505+ fn stringifier(channel: &DuplexStream<~str, uint>) {
506+ let mut value: uint;
507+ loop {
508+ value = channel.recv();
509+ channel.send(value.to_str());
510+ if value == 0 { break; }
511+ }
470512 }
471- }
513+ # }
472514~~~~
473515
474516The implementation of `DuplexStream` supports both sending and
@@ -481,15 +523,15 @@ response itself is simply the stringified version of the received value,
481523
482524Here is the code for the parent task:
483525
484- ~~~{.ignore .linked-failure}
526+ ~~~
527+ # extern mod sync;
485528# use std::task::spawn;
486- # use std::uint;
487- # use extra::comm::DuplexStream;
529+ # use sync::DuplexStream;
488530# fn stringifier(channel: &DuplexStream<~ str, uint>) {
489531# let mut value: uint;
490532# loop {
491533# value = channel.recv();
492- # channel.send(uint:: to_str(value ));
534+ # channel.send(value. to_str());
493535# if value == 0u { break; }
494536# }
495537# }
0 commit comments