Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed prelude::* from libstd files. #12006

Closed
wants to merge 10 commits into from
14 changes: 8 additions & 6 deletions mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,27 @@
# automatically generated for all stage/host/target combinations.
################################################################################

TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid
TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid serialize sync
HOST_CRATES := syntax rustc rustdoc
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc

DEPS_std := native:rustrt
DEPS_extra := std term
DEPS_extra := std serialize sync term
DEPS_green := std
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
DEPS_syntax := std extra term
DEPS_rustc := syntax native:rustllvm flate arena
DEPS_rustdoc := rustc native:sundown
DEPS_syntax := std extra term serialize
DEPS_rustc := syntax native:rustllvm flate arena serialize sync
DEPS_rustdoc := rustc native:sundown serialize sync
DEPS_flate := std native:miniz
DEPS_arena := std extra
DEPS_glob := std
DEPS_serialize := std
DEPS_term := std
DEPS_semver := std
DEPS_uuid := std extra
DEPS_uuid := std serialize
DEPS_sync := std

TOOL_DEPS_compiletest := extra green rustuv
TOOL_DEPS_rustdoc := rustdoc green rustuv
Expand Down
108 changes: 75 additions & 33 deletions src/doc/guide-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,51 @@ data through the global _exchange heap_.

While Rust's type system provides the building blocks needed for safe
and efficient tasks, all of the task functionality itself is implemented
in the standard and extra libraries, which are still under development
in the standard and sync libraries, which are still under development
and do not always present a consistent or complete interface.

For your reference, these are the standard modules involved in Rust
concurrency at this writing:

* [`std::task`] - All code relating to tasks and task scheduling,
* [`std::comm`] - The message passing interface,
* [`extra::comm`] - Additional messaging types based on `std::comm`,
* [`extra::sync`] - More exotic synchronization tools, including locks,
* [`extra::arc`] - The Arc (atomically reference counted) type,
for safely sharing immutable data,
* [`extra::future`] - A type representing values that may be computed concurrently and retrieved at a later time.
* [`sync::DuplexStream`] - An extension of `pipes::stream` that allows both sending and receiving,
* [`sync::SyncChan`] - An extension of `pipes::stream` that provides synchronous message sending,
* [`sync::SyncPort`] - An extension of `pipes::stream` that acknowledges each message received,
* [`sync::rendezvous`] - Creates a stream whose channel, upon sending a message, blocks until the
message is received.
* [`sync::Arc`] - The Arc (atomically reference counted) type, for safely sharing immutable data,
* [`sync::RWArc`] - A dual-mode Arc protected by a reader-writer lock,
* [`sync::MutexArc`] - An Arc with mutable data protected by a blocking mutex,
* [`sync::Semaphore`] - A counting, blocking, bounded-waiting semaphore,
* [`sync::Mutex`] - A blocking, bounded-waiting, mutual exclusion lock with an associated
FIFO condition variable,
* [`sync::RWLock`] - A blocking, no-starvation, reader-writer lock with an associated condvar,
* [`sync::Barrier`] - A barrier enables multiple tasks to synchronize the beginning
of some computation,
* [`sync::TaskPool`] - A task pool abstraction,
* [`sync::Future`] - A type encapsulating the result of a computation which may not be complete,
* [`sync::one`] - A "once initialization" primitive
* [`sync::mutex`] - A proper mutex implementation regardless of the "flavor of task" which is
acquiring the lock.

[`std::task`]: std/task/index.html
[`std::comm`]: std/comm/index.html
[`extra::comm`]: extra/comm/index.html
[`extra::sync`]: extra/sync/index.html
[`extra::arc`]: extra/arc/index.html
[`extra::future`]: extra/future/index.html
[`sync::DuplexStream`]: sync/struct.DuplexStream.html
[`sync::SyncChan`]: sync/struct.SyncChan.html
[`sync::SyncPort`]: sync/struct.SyncPort.html
[`sync::rendezvous`]: sync/fn.rendezvous.html
[`sync::Arc`]: sync/struct.Arc.html
[`sync::RWArc`]: sync/struct.RWArc.html
[`sync::MutexArc`]: sync/struct.MutexArc.html
[`sync::Semaphore`]: sync/struct.Semaphore.html
[`sync::Mutex`]: sync/struct.Mutex.html
[`sync::RWLock`]: sync/struct.RWLock.html
[`sync::Barrier`]: sync/struct.Barrier.html
[`sync::TaskPool`]: sync/struct.TaskPool.html
[`sync::Future`]: sync/struct.Future.html
[`sync::one`]: sync/one/index.html
[`sync::mutex`]: sync/mutex/index.html

# Basics

Expand Down Expand Up @@ -254,21 +279,25 @@ let result = ports.iter().fold(0, |accum, port| accum + port.recv() );
~~~

## Backgrounding computations: Futures
With `extra::future`, rust has a mechanism for requesting a computation and getting the result
With `sync::Future`, rust has a mechanism for requesting a computation and getting the result
later.

The basic example below illustrates this.

~~~
# extern mod sync;

# fn main() {
# fn make_a_sandwich() {};
fn fib(n: u64) -> u64 {
// lengthy computation returning an uint
12586269025
}

let mut delayed_fib = extra::future::Future::spawn(proc() fib(50));
let mut delayed_fib = sync::Future::spawn(proc() fib(50));
make_a_sandwich();
println!("fib(50) = {:?}", delayed_fib.get())
# }
~~~

The call to `future::spawn` returns immediately a `future` object regardless of how long it
Expand All @@ -281,6 +310,7 @@ Here is another example showing how futures allow you to background computations
be distributed on the available cores.

~~~
# extern mod sync;
# use std::vec;
fn partial_sum(start: uint) -> f64 {
let mut local_sum = 0f64;
Expand All @@ -291,7 +321,7 @@ fn partial_sum(start: uint) -> f64 {
}

fn main() {
let mut futures = vec::from_fn(1000, |ind| extra::future::Future::spawn( proc() { partial_sum(ind) }));
let mut futures = vec::from_fn(1000, |ind| sync::Future::spawn( proc() { partial_sum(ind) }));

let mut final_res = 0f64;
for ft in futures.mut_iter() {
Expand All @@ -309,16 +339,17 @@ add up to a significant amount of wasted memory and would require copying the sa
necessary.

To tackle this issue, one can use an Atomically Reference Counted wrapper (`Arc`) as implemented in
the `extra` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
the `sync` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc
acts as a reference to the shared data and only this reference is shared and cloned.

Here is a small example showing how to use Arcs. We wish to run concurrently several computations on
a single large vector of floats. Each task needs the full vector to perform its duty.

~~~
# extern mod sync;
# use std::vec;
# use std::rand;
use extra::arc::Arc;
use sync::Arc;

fn pnorm(nums: &~[f64], p: uint) -> f64 {
nums.iter().fold(0.0, |a,b| a+(*b).powf(&(p as f64)) ).powf(&(1.0 / (p as f64)))
Expand Down Expand Up @@ -348,39 +379,48 @@ at the power given as argument and takes the inverse power of this value). The A
created by the line

~~~
# use extra::arc::Arc;
# extern mod sync;
# use sync::Arc;
# use std::vec;
# use std::rand;
# fn main() {
# let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
let numbers_arc=Arc::new(numbers);
# }
~~~

and a clone of it is sent to each task

~~~
# use extra::arc::Arc;
# extern mod sync;
# use sync::Arc;
# use std::vec;
# use std::rand;
# fn main() {
# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
# let numbers_arc = Arc::new(numbers);
# let (port, chan) = Chan::new();
chan.send(numbers_arc.clone());
# }
~~~

copying only the wrapper and not its contents.

Each task recovers the underlying data by

~~~
# use extra::arc::Arc;
# extern mod sync;
# use sync::Arc;
# use std::vec;
# use std::rand;
# fn main() {
# let numbers=vec::from_fn(1000000, |_| rand::random::<f64>());
# let numbers_arc=Arc::new(numbers);
# let (port, chan) = Chan::new();
# chan.send(numbers_arc.clone());
# let local_arc : Arc<~[f64]> = port.recv();
let task_numbers = local_arc.get();
# }
~~~

and can use it as if it were local.
Expand Down Expand Up @@ -450,25 +490,27 @@ proceed).

A very common thing to do is to spawn a child task where the parent
and child both need to exchange messages with each other. The
function `extra::comm::DuplexStream()` supports this pattern. We'll
function `sync::comm::DuplexStream()` supports this pattern. We'll
look briefly at how to use it.

To see how `DuplexStream()` works, we will create a child task
that repeatedly receives a `uint` message, converts it to a string, and sends
the string in response. The child terminates when it receives `0`.
Here is the function that implements the child task:

~~~{.ignore .linked-failure}
# use extra::comm::DuplexStream;
# use std::uint;
fn stringifier(channel: &DuplexStream<~str, uint>) {
let mut value: uint;
loop {
value = channel.recv();
channel.send(uint::to_str(value));
if value == 0 { break; }
~~~
# extern mod sync;
# fn main() {
# use sync::DuplexStream;
fn stringifier(channel: &DuplexStream<~str, uint>) {
let mut value: uint;
loop {
value = channel.recv();
channel.send(value.to_str());
if value == 0 { break; }
}
}
}
# }
~~~~

The implementation of `DuplexStream` supports both sending and
Expand All @@ -481,15 +523,15 @@ response itself is simply the stringified version of the received value,

Here is the code for the parent task:

~~~{.ignore .linked-failure}
~~~
# extern mod sync;
# use std::task::spawn;
# use std::uint;
# use extra::comm::DuplexStream;
# use sync::DuplexStream;
# fn stringifier(channel: &DuplexStream<~str, uint>) {
# let mut value: uint;
# loop {
# value = channel.recv();
# channel.send(uint::to_str(value));
# channel.send(value.to_str());
# if value == 0u { break; }
# }
# }
Expand Down
4 changes: 3 additions & 1 deletion src/doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ li {list-style-type: none; }
* [The `flate` compression library](flate/index.html)
* [The `glob` file path matching library](glob/index.html)
* [The `semver` version collation library](semver/index.html)
* [The `serialize` value encoding/decoding library](serialize/index.html)
* [The `sync` library for concurrency-enabled mechanisms and primitives](sync/index.html)
* [The `term` terminal-handling library](term/index.html)
* [The UUID library](uuid/index.html)
* [The `uuid` 128-bit universally unique identifier library](uuid/index.html)

# Tooling

Expand Down
6 changes: 4 additions & 2 deletions src/doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ fn angle(vector: (f64, f64)) -> f64 {
let pi = f64::consts::PI;
match vector {
(0.0, y) if y < 0.0 => 1.5 * pi,
(0.0, y) => 0.5 * pi,
(0.0, _) => 0.5 * pi,
(x, y) => atan(y / x)
}
}
Expand All @@ -519,7 +519,9 @@ A variable name in a pattern matches any value, *and* binds that name
to the value of the matched value inside of the arm's action. Thus, `(0.0,
y)` matches any tuple whose first element is zero, and binds `y` to
the second element. `(x, y)` matches any two-element tuple, and binds both
elements to variables.
elements to variables. `(0.0,_)` matches any tuple whose first element is zero
and does not bind anything to the second element.

A subpattern can also be bound to a variable, using `variable @ pattern`. For
example:

Expand Down
2 changes: 1 addition & 1 deletion src/etc/licenseck.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"libstd/sync/mpsc_queue.rs", # BSD
"libstd/sync/spsc_queue.rs", # BSD
"libstd/sync/mpmc_bounded_queue.rs", # BSD
"libextra/sync/mpsc_intrusive.rs", # BSD
"libsync/sync/mpsc_intrusive.rs", # BSD
]

def check_license(name, contents):
Expand Down
27 changes: 27 additions & 0 deletions src/libextra/dlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use std::iter;

use container::Deque;

use serialize::{Encodable, Decodable, Encoder, Decoder};

/// A doubly-linked list.
pub struct DList<T> {
priv length: uint,
Expand Down Expand Up @@ -628,6 +630,31 @@ impl<A: Clone> Clone for DList<A> {
}
}

impl<
S: Encoder,
T: Encodable<S>
> Encodable<S> for DList<T> {
fn encode(&self, s: &mut S) {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s));
}
})
}
}

impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> {
fn decode(d: &mut D) -> DList<T> {
let mut list = DList::new();
d.read_seq(|d, len| {
for i in range(0u, len) {
list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
}
});
list
}
}

#[cfg(test)]
mod tests {
use container::Deque;
Expand Down
Loading