Skip to content

Commit dd21a51

Browse files
committed
move concurrent stuff from libextra to libsync
1 parent ed885e3 commit dd21a51

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+224
-145
lines changed

mk/crates.mk

+5-4
Original file line numberDiff line numberDiff line change
@@ -49,25 +49,26 @@
4949
# automatically generated for all stage/host/target combinations.
5050
################################################################################
5151

52-
TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid
52+
TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid sync
5353
HOST_CRATES := syntax rustc rustdoc
5454
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
5555
TOOLS := compiletest rustdoc rustc
5656

5757
DEPS_std := native:rustrt
58-
DEPS_extra := std term
58+
DEPS_extra := std term sync
5959
DEPS_green := std
6060
DEPS_rustuv := std native:uv native:uv_support
6161
DEPS_native := std
6262
DEPS_syntax := std extra term
63-
DEPS_rustc := syntax native:rustllvm flate arena
64-
DEPS_rustdoc := rustc native:sundown
63+
DEPS_rustc := syntax native:rustllvm flate arena sync
64+
DEPS_rustdoc := rustc native:sundown sync
6565
DEPS_flate := std native:miniz
6666
DEPS_arena := std extra
6767
DEPS_glob := std
6868
DEPS_term := std
6969
DEPS_semver := std
7070
DEPS_uuid := std extra
71+
DEPS_sync := std
7172

7273
TOOL_DEPS_compiletest := extra green rustuv
7374
TOOL_DEPS_rustdoc := rustdoc green rustuv

src/doc/guide-tasks.md

+75-33
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,51 @@ data through the global _exchange heap_.
3939

4040
While Rust's type system provides the building blocks needed for safe
4141
and 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
4343
and do not always present a consistent or complete interface.
4444

4545
For your reference, these are the standard modules involved in Rust
4646
concurrency 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
258283
later.
259284

260285
The basic example below illustrates this.
261286

262287
~~~
288+
# extern mod sync;
289+
290+
# fn main() {
263291
# fn make_a_sandwich() {};
264292
fn 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));
270298
make_a_sandwich();
271299
println!("fib(50) = {:?}", delayed_fib.get())
300+
# }
272301
~~~
273302

274303
The 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
281310
be distributed on the available cores.
282311

283312
~~~
313+
# extern mod sync;
284314
# use std::vec;
285315
fn partial_sum(start: uint) -> f64 {
286316
let mut local_sum = 0f64;
@@ -291,7 +321,7 @@ fn partial_sum(start: uint) -> f64 {
291321
}
292322
293323
fn 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
309339
necessary.
310340

311341
To 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
313343
acts as a reference to the shared data and only this reference is shared and cloned.
314344

315345
Here is a small example showing how to use Arcs. We wish to run concurrently several computations on
316346
a 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
323354
fn 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
348379
created 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>());
355388
let numbers_arc=Arc::new(numbers);
389+
# }
356390
~~~
357391

358392
and 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();
367403
chan.send(numbers_arc.clone());
404+
# }
368405
~~~
369406

370407
copying only the wrapper and not its contents.
371408

372409
Each 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();
383422
let task_numbers = local_arc.get();
423+
# }
384424
~~~
385425

386426
and can use it as if it were local.
@@ -450,25 +490,27 @@ proceed).
450490

451491
A very common thing to do is to spawn a child task where the parent
452492
and 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
454494
look briefly at how to use it.
455495

456496
To see how `DuplexStream()` works, we will create a child task
457497
that repeatedly receives a `uint` message, converts it to a string, and sends
458498
the string in response. The child terminates when it receives `0`.
459499
Here 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
474516
The implementation of `DuplexStream` supports both sending and
@@ -481,15 +523,15 @@ response itself is simply the stringified version of the received value,
481523
482524
Here 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
# }

src/doc/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ li {list-style-type: none; }
4343
* [The `semver` version collation library](semver/index.html)
4444
* [The `term` terminal-handling library](term/index.html)
4545
* [The UUID library](uuid/index.html)
46+
* [The `sync` library for concurrency-enabled mechanisms and primitives](sync/index.html)
4647

4748
# Tooling
4849

src/etc/licenseck.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"libstd/sync/mpsc_queue.rs", # BSD
4242
"libstd/sync/spsc_queue.rs", # BSD
4343
"libstd/sync/mpmc_bounded_queue.rs", # BSD
44-
"libextra/sync/mpsc_intrusive.rs", # BSD
44+
"libsync/sync/mpsc_intrusive.rs", # BSD
4545
]
4646

4747
def check_license(name, contents):

src/libextra/lib.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,16 @@ Rust extras are part of the standard Rust distribution.
3434
#[deny(non_camel_case_types)];
3535
#[deny(missing_doc)];
3636

37-
// Utility modules
37+
extern mod sync;
3838

39-
pub mod c_vec;
39+
#[cfg(stage0)]
40+
macro_rules! if_ok (
41+
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
42+
)
4043

41-
// Concurrency
44+
// Utility modules
4245

43-
pub mod sync;
44-
pub mod arc;
45-
pub mod comm;
46-
pub mod future;
47-
pub mod task_pool;
46+
pub mod c_vec;
4847

4948
// Collections
5049

src/libextra/workcache.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use json;
1414
use json::ToJson;
1515
use serialize::{Encoder, Encodable, Decoder, Decodable};
16-
use arc::{Arc,RWArc};
16+
use sync::{Arc,RWArc};
1717
use treemap::TreeMap;
1818
use std::str;
1919
use std::io;

src/librustc/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ pub mod write {
331331
}
332332

333333
unsafe fn configure_llvm(sess: Session) {
334-
use extra::sync::one::{Once, ONCE_INIT};
334+
use sync::one::{Once, ONCE_INIT};
335335
static mut INIT: Once = ONCE_INIT;
336336

337337
// Copy what clang does by turning on loop vectorization at O2 and

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern mod extra;
3535
extern mod flate;
3636
extern mod arena;
3737
extern mod syntax;
38+
extern mod sync;
3839

3940
use back::link;
4041
use driver::session;

src/librustc/middle/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2660,7 +2660,7 @@ pub fn trans_crate(sess: session::Session,
26602660
output: &Path) -> CrateTranslation {
26612661
// Before we touch LLVM, make sure that multithreading is enabled.
26622662
unsafe {
2663-
use extra::sync::one::{Once, ONCE_INIT};
2663+
use sync::one::{Once, ONCE_INIT};
26642664
static mut INIT: Once = ONCE_INIT;
26652665
static mut POISONED: bool = false;
26662666
INIT.doit(|| {

src/librustdoc/html/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use std::io::{fs, File, BufferedWriter};
4141
use std::str;
4242
use std::vec;
4343

44-
use extra::arc::Arc;
44+
use sync::Arc;
4545
use extra::json::ToJson;
4646
use syntax::ast;
4747
use syntax::attr;

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
extern mod syntax;
1919
extern mod rustc;
2020
extern mod extra;
21+
extern mod sync;
2122

2223
use std::local_data;
2324
use std::io;

src/libextra/arc.rs renamed to src/libsync/arc.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* With simple pipes, without Arc, a copy would have to be made for each task.
1919
*
2020
* ```rust
21-
* use extra::arc::Arc;
21+
* use sync::Arc;
2222
* use std::{rand, vec};
2323
*
2424
* let numbers = vec::from_fn(100, |i| (i as f32) * rand::random());
@@ -38,7 +38,7 @@
3838
* ```
3939
*/
4040

41-
#[allow(missing_doc)];
41+
#[allow(missing_doc, dead_code)];
4242

4343

4444
use sync;
@@ -424,7 +424,7 @@ impl<T:Freeze + Send> RWArc<T> {
424424
* # Example
425425
*
426426
* ```rust
427-
* use extra::arc::RWArc;
427+
* use sync::RWArc;
428428
*
429429
* let arc = RWArc::new(1);
430430
* arc.write_downgrade(|mut write_token| {
@@ -605,7 +605,7 @@ impl<T:Clone+Send+Freeze> Clone for CowArc<T> {
605605
#[cfg(test)]
606606
mod tests {
607607

608-
use arc::*;
608+
use super::{Arc, RWArc, MutexArc, CowArc};
609609

610610
use std::task;
611611

File renamed without changes.

0 commit comments

Comments
 (0)