mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 20:53:37 +00:00
std: Rename Chan/Port types and constructor
* Chan<T> => Sender<T> * Port<T> => Receiver<T> * Chan::new() => channel() * constructor returns (Sender, Receiver) instead of (Receiver, Sender) * local variables named `port` renamed to `rx` * local variables named `chan` renamed to `tx` Closes #11765
This commit is contained in:
parent
e86e1d88b2
commit
7858065113
@ -48,8 +48,8 @@ concurrency at this writing:
|
||||
* [`std::task`] - All code relating to tasks and task scheduling,
|
||||
* [`std::comm`] - The message passing interface,
|
||||
* [`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::SyncSender`] - An extension of `pipes::stream` that provides synchronous message sending,
|
||||
* [`sync::SyncReceiver`] - 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,
|
||||
@ -70,8 +70,8 @@ concurrency at this writing:
|
||||
[`std::task`]: std/task/index.html
|
||||
[`std::comm`]: std/comm/index.html
|
||||
[`sync::DuplexStream`]: sync/struct.DuplexStream.html
|
||||
[`sync::SyncChan`]: sync/struct.SyncChan.html
|
||||
[`sync::SyncPort`]: sync/struct.SyncPort.html
|
||||
[`sync::SyncSender`]: sync/struct.SyncSender.html
|
||||
[`sync::SyncReceiver`]: sync/struct.SyncReceiver.html
|
||||
[`sync::rendezvous`]: sync/fn.rendezvous.html
|
||||
[`sync::Arc`]: sync/struct.Arc.html
|
||||
[`sync::RWArc`]: sync/struct.RWArc.html
|
||||
@ -141,118 +141,115 @@ receiving messages. Pipes are low-level communication building-blocks and so
|
||||
come in a variety of forms, each one appropriate for a different use case. In
|
||||
what follows, we cover the most commonly used varieties.
|
||||
|
||||
The simplest way to create a pipe is to use `Chan::new`
|
||||
function to create a `(Port, Chan)` pair. In Rust parlance, a *channel*
|
||||
is a sending endpoint of a pipe, and a *port* is the receiving
|
||||
The simplest way to create a pipe is to use the `channel`
|
||||
function to create a `(Sender, Receiver)` pair. In Rust parlance, a *sender*
|
||||
is a sending endpoint of a pipe, and a *receiver* is the receiving
|
||||
endpoint. Consider the following example of calculating two results
|
||||
concurrently:
|
||||
|
||||
~~~~
|
||||
# use std::task::spawn;
|
||||
|
||||
let (port, chan): (Port<int>, Chan<int>) = Chan::new();
|
||||
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let result = some_expensive_computation();
|
||||
chan.send(result);
|
||||
tx.send(result);
|
||||
});
|
||||
|
||||
some_other_expensive_computation();
|
||||
let result = port.recv();
|
||||
let result = rx.recv();
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# fn some_other_expensive_computation() {}
|
||||
~~~~
|
||||
|
||||
Let's examine this example in detail. First, the `let` statement creates a
|
||||
stream for sending and receiving integers (the left-hand side of the `let`,
|
||||
`(chan, port)`, is an example of a *destructuring let*: the pattern separates
|
||||
`(tx, rx)`, is an example of a *destructuring let*: the pattern separates
|
||||
a tuple into its component parts).
|
||||
|
||||
~~~~
|
||||
let (port, chan): (Port<int>, Chan<int>) = Chan::new();
|
||||
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
|
||||
~~~~
|
||||
|
||||
The child task will use the channel to send data to the parent task,
|
||||
which will wait to receive the data on the port. The next statement
|
||||
The child task will use the sender to send data to the parent task,
|
||||
which will wait to receive the data on the receiver. The next statement
|
||||
spawns the child task.
|
||||
|
||||
~~~~
|
||||
# use std::task::spawn;
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# let (port, chan) = Chan::new();
|
||||
# let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let result = some_expensive_computation();
|
||||
chan.send(result);
|
||||
tx.send(result);
|
||||
});
|
||||
~~~~
|
||||
|
||||
Notice that the creation of the task closure transfers `chan` to the child
|
||||
task implicitly: the closure captures `chan` in its environment. Both `Chan`
|
||||
and `Port` are sendable types and may be captured into tasks or otherwise
|
||||
Notice that the creation of the task closure transfers `tx` to the child
|
||||
task implicitly: the closure captures `tx` in its environment. Both `Sender`
|
||||
and `Receiver` are sendable types and may be captured into tasks or otherwise
|
||||
transferred between them. In the example, the child task runs an expensive
|
||||
computation, then sends the result over the captured channel.
|
||||
|
||||
Finally, the parent continues with some other expensive
|
||||
computation, then waits for the child's result to arrive on the
|
||||
port:
|
||||
receiver:
|
||||
|
||||
~~~~
|
||||
# fn some_other_expensive_computation() {}
|
||||
# let (port, chan) = Chan::<int>::new();
|
||||
# chan.send(0);
|
||||
# let (tx, rx) = channel::<int>();
|
||||
# tx.send(0);
|
||||
some_other_expensive_computation();
|
||||
let result = port.recv();
|
||||
let result = rx.recv();
|
||||
~~~~
|
||||
|
||||
The `Port` and `Chan` pair created by `Chan::new` enables efficient
|
||||
The `Sender` and `Receiver` pair created by `channel` enables efficient
|
||||
communication between a single sender and a single receiver, but multiple
|
||||
senders cannot use a single `Chan`, and multiple receivers cannot use a single
|
||||
`Port`. What if our example needed to compute multiple results across a number
|
||||
of tasks? The following program is ill-typed:
|
||||
senders cannot use a single `Sender` value, and multiple receivers cannot use a
|
||||
single `Receiver` value. What if our example needed to compute multiple
|
||||
results across a number of tasks? The following program is ill-typed:
|
||||
|
||||
~~~ {.ignore}
|
||||
# use std::task::{spawn};
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
chan.send(some_expensive_computation());
|
||||
tx.send(some_expensive_computation());
|
||||
});
|
||||
|
||||
// ERROR! The previous spawn statement already owns the channel,
|
||||
// ERROR! The previous spawn statement already owns the sender,
|
||||
// so the compiler will not allow it to be captured again
|
||||
spawn(proc() {
|
||||
chan.send(some_expensive_computation());
|
||||
tx.send(some_expensive_computation());
|
||||
});
|
||||
~~~
|
||||
|
||||
Instead we can clone the `chan`, which allows for multiple senders.
|
||||
Instead we can clone the `tx`, which allows for multiple senders.
|
||||
|
||||
~~~
|
||||
# use std::task::spawn;
|
||||
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
for init_val in range(0u, 3) {
|
||||
// Create a new channel handle to distribute to the child task
|
||||
let child_chan = chan.clone();
|
||||
let child_tx = tx.clone();
|
||||
spawn(proc() {
|
||||
child_chan.send(some_expensive_computation(init_val));
|
||||
child_tx.send(some_expensive_computation(init_val));
|
||||
});
|
||||
}
|
||||
|
||||
let result = port.recv() + port.recv() + port.recv();
|
||||
let result = rx.recv() + rx.recv() + rx.recv();
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
~~~
|
||||
|
||||
Cloning a `Chan` produces a new handle to the same channel, allowing multiple
|
||||
tasks to send data to a single port. It also upgrades the channel internally in
|
||||
Cloning a `Sender` produces a new handle to the same channel, allowing multiple
|
||||
tasks to send data to a single receiver. It upgrades the channel internally in
|
||||
order to allow this functionality, which means that channels that are not
|
||||
cloned can avoid the overhead required to handle multiple senders. But this
|
||||
fact has no bearing on the channel's usage: the upgrade is transparent.
|
||||
|
||||
Note that the above cloning example is somewhat contrived since
|
||||
you could also simply use three `Chan` pairs, but it serves to
|
||||
you could also simply use three `Sender` pairs, but it serves to
|
||||
illustrate the point. For reference, written with multiple streams, it
|
||||
might look like the example below.
|
||||
|
||||
@ -261,16 +258,16 @@ might look like the example below.
|
||||
# use std::vec;
|
||||
|
||||
// Create a vector of ports, one for each child task
|
||||
let ports = vec::from_fn(3, |init_val| {
|
||||
let (port, chan) = Chan::new();
|
||||
let rxs = vec::from_fn(3, |init_val| {
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
chan.send(some_expensive_computation(init_val));
|
||||
tx.send(some_expensive_computation(init_val));
|
||||
});
|
||||
port
|
||||
rx
|
||||
});
|
||||
|
||||
// Wait on each port, accumulating the results
|
||||
let result = ports.iter().fold(0, |accum, port| accum + port.recv() );
|
||||
let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
~~~
|
||||
|
||||
@ -281,7 +278,7 @@ later.
|
||||
The basic example below illustrates this.
|
||||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
extern crate sync;
|
||||
|
||||
# fn main() {
|
||||
# fn make_a_sandwich() {};
|
||||
@ -342,9 +339,10 @@ Here is a small example showing how to use Arcs. We wish to run concurrently sev
|
||||
a single large vector of floats. Each task needs the full vector to perform its duty.
|
||||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
extern crate rand;
|
||||
# use std::vec;
|
||||
extern crate rand;
|
||||
extern crate sync;
|
||||
|
||||
use std::vec;
|
||||
use sync::Arc;
|
||||
|
||||
fn pnorm(nums: &~[f64], p: uint) -> f64 {
|
||||
@ -358,11 +356,11 @@ fn main() {
|
||||
let numbers_arc = Arc::new(numbers);
|
||||
|
||||
for num in range(1u, 10) {
|
||||
let (port, chan) = Chan::new();
|
||||
chan.send(numbers_arc.clone());
|
||||
let (tx, rx) = channel();
|
||||
tx.send(numbers_arc.clone());
|
||||
|
||||
spawn(proc() {
|
||||
let local_arc : Arc<~[f64]> = port.recv();
|
||||
let local_arc : Arc<~[f64]> = rx.recv();
|
||||
let task_numbers = local_arc.get();
|
||||
println!("{}-norm = {}", num, pnorm(task_numbers, num));
|
||||
});
|
||||
@ -395,8 +393,8 @@ and a clone of it is sent to each task
|
||||
# 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 (tx, rx) = channel();
|
||||
tx.send(numbers_arc.clone());
|
||||
# }
|
||||
~~~
|
||||
|
||||
@ -412,9 +410,9 @@ Each task recovers the underlying data by
|
||||
# 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 (tx, rx) = channel();
|
||||
# tx.send(numbers_arc.clone());
|
||||
# let local_arc : Arc<~[f64]> = rx.recv();
|
||||
let task_numbers = local_arc.get();
|
||||
# }
|
||||
~~~
|
||||
@ -486,19 +484,18 @@ 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 `sync::comm::DuplexStream()` supports this pattern. We'll
|
||||
function `sync::comm::duplex` supports this pattern. We'll
|
||||
look briefly at how to use it.
|
||||
|
||||
To see how `DuplexStream()` works, we will create a child task
|
||||
To see how `duplex` 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:
|
||||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
extern crate sync;
|
||||
# fn main() {
|
||||
# use sync::DuplexStream;
|
||||
fn stringifier(channel: &DuplexStream<~str, uint>) {
|
||||
fn stringifier(channel: &sync::DuplexStream<~str, uint>) {
|
||||
let mut value: uint;
|
||||
loop {
|
||||
value = channel.recv();
|
||||
@ -520,10 +517,10 @@ response itself is simply the stringified version of the received value,
|
||||
Here is the code for the parent task:
|
||||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
extern crate sync;
|
||||
# use std::task::spawn;
|
||||
# use sync::DuplexStream;
|
||||
# fn stringifier(channel: &DuplexStream<~str, uint>) {
|
||||
# fn stringifier(channel: &sync::DuplexStream<~str, uint>) {
|
||||
# let mut value: uint;
|
||||
# loop {
|
||||
# value = channel.recv();
|
||||
@ -533,7 +530,7 @@ Here is the code for the parent task:
|
||||
# }
|
||||
# fn main() {
|
||||
|
||||
let (from_child, to_child) = DuplexStream::new();
|
||||
let (from_child, to_child) = sync::duplex();
|
||||
|
||||
spawn(proc() {
|
||||
stringifier(&to_child);
|
||||
|
@ -96,7 +96,7 @@ syn keyword rustTrait MutableVector MutableTotalOrdVector
|
||||
syn keyword rustTrait Vector VectorVector CloneableVector ImmutableVector
|
||||
|
||||
"syn keyword rustFunction stream
|
||||
syn keyword rustTrait Port Chan
|
||||
syn keyword rustTrait Sender Receiver
|
||||
"syn keyword rustFunction spawn
|
||||
|
||||
syn keyword rustSelf self
|
||||
|
@ -237,7 +237,7 @@ pub struct Exec {
|
||||
|
||||
enum Work<'a, T> {
|
||||
WorkValue(T),
|
||||
WorkFromTask(&'a Prep<'a>, Port<(Exec, T)>),
|
||||
WorkFromTask(&'a Prep<'a>, Receiver<(Exec, T)>),
|
||||
}
|
||||
|
||||
fn json_encode<'a, T:Encodable<json::Encoder<'a>>>(t: &T) -> ~str {
|
||||
@ -411,7 +411,7 @@ impl<'a> Prep<'a> {
|
||||
|
||||
_ => {
|
||||
debug!("Cache miss!");
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let blk = bo.take_unwrap();
|
||||
|
||||
// FIXME: What happens if the task fails?
|
||||
@ -421,9 +421,9 @@ impl<'a> Prep<'a> {
|
||||
discovered_outputs: WorkMap::new(),
|
||||
};
|
||||
let v = blk(&mut exe);
|
||||
chan.send((exe, v));
|
||||
tx.send((exe, v));
|
||||
});
|
||||
Work::from_task(self, port)
|
||||
Work::from_task(self, rx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,7 +437,7 @@ impl<'a, T:Send +
|
||||
pub fn from_value(elt: T) -> Work<'a, T> {
|
||||
WorkValue(elt)
|
||||
}
|
||||
pub fn from_task(prep: &'a Prep<'a>, port: Port<(Exec, T)>)
|
||||
pub fn from_task(prep: &'a Prep<'a>, port: Receiver<(Exec, T)>)
|
||||
-> Work<'a, T> {
|
||||
WorkFromTask(prep, port)
|
||||
}
|
||||
|
@ -255,11 +255,11 @@ mod test {
|
||||
#[test]
|
||||
fn some_channels() {
|
||||
run(proc() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
});
|
||||
}
|
||||
|
||||
@ -272,11 +272,11 @@ mod test {
|
||||
|
||||
for _ in range(0, 20) {
|
||||
pool.spawn(TaskOpts::new(), proc() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -258,15 +258,15 @@ pub fn run(main: proc()) -> int {
|
||||
// Create a scheduler pool and spawn the main task into this pool. We will
|
||||
// get notified over a channel when the main task exits.
|
||||
let mut pool = SchedPool::new(PoolConfig::new());
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let mut opts = TaskOpts::new();
|
||||
opts.notify_chan = Some(chan);
|
||||
opts.notify_chan = Some(tx);
|
||||
opts.name = Some("<main>".into_maybe_owned());
|
||||
pool.spawn(opts, main);
|
||||
|
||||
// Wait for the main task to return, and set the process error code
|
||||
// appropriately.
|
||||
if port.recv().is_err() {
|
||||
if rx.recv().is_err() {
|
||||
os::set_exit_status(rt::DEFAULT_ERROR_CODE);
|
||||
}
|
||||
|
||||
@ -309,7 +309,7 @@ pub struct SchedPool {
|
||||
priv sleepers: SleeperList,
|
||||
priv factory: fn() -> ~rtio::EventLoop,
|
||||
priv task_state: TaskState,
|
||||
priv tasks_done: Port<()>,
|
||||
priv tasks_done: Receiver<()>,
|
||||
}
|
||||
|
||||
/// This is an internal state shared among a pool of schedulers. This is used to
|
||||
@ -318,7 +318,7 @@ pub struct SchedPool {
|
||||
#[deriving(Clone)]
|
||||
struct TaskState {
|
||||
cnt: UnsafeArc<AtomicUint>,
|
||||
done: Chan<()>,
|
||||
done: Sender<()>,
|
||||
}
|
||||
|
||||
impl SchedPool {
|
||||
@ -471,11 +471,11 @@ impl SchedPool {
|
||||
}
|
||||
|
||||
impl TaskState {
|
||||
fn new() -> (Port<()>, TaskState) {
|
||||
let (p, c) = Chan::new();
|
||||
(p, TaskState {
|
||||
fn new() -> (Receiver<()>, TaskState) {
|
||||
let (tx, rx) = channel();
|
||||
(rx, TaskState {
|
||||
cnt: UnsafeArc::new(AtomicUint::new(0)),
|
||||
done: c,
|
||||
done: tx,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1091,25 +1091,25 @@ mod test {
|
||||
fn test_home_sched() {
|
||||
let mut pool = pool();
|
||||
|
||||
let (dport, dchan) = Chan::new();
|
||||
let (dtx, drx) = channel();
|
||||
{
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let mut handle1 = pool.spawn_sched();
|
||||
let mut handle2 = pool.spawn_sched();
|
||||
|
||||
handle1.send(TaskFromFriend(pool.task(TaskOpts::new(), proc() {
|
||||
chan.send(sched_id());
|
||||
tx.send(sched_id());
|
||||
})));
|
||||
let sched1_id = port.recv();
|
||||
let sched1_id = rx.recv();
|
||||
|
||||
let mut task = pool.task(TaskOpts::new(), proc() {
|
||||
assert_eq!(sched_id(), sched1_id);
|
||||
dchan.send(());
|
||||
dtx.send(());
|
||||
});
|
||||
task.give_home(HomeSched(handle1));
|
||||
handle2.send(TaskFromFriend(task));
|
||||
}
|
||||
dport.recv();
|
||||
drx.recv();
|
||||
|
||||
pool.shutdown();
|
||||
}
|
||||
@ -1210,7 +1210,7 @@ mod test {
|
||||
});
|
||||
|
||||
// Signal from the special task that we are done.
|
||||
let (port, chan) = Chan::<()>::new();
|
||||
let (tx, rx) = channel::<()>();
|
||||
|
||||
fn run(next: ~GreenTask) {
|
||||
let mut task = GreenTask::convert(Local::take());
|
||||
@ -1221,7 +1221,7 @@ mod test {
|
||||
let normal_task = GreenTask::new(&mut normal_sched.stack_pool, None, proc() {
|
||||
run(task2);
|
||||
run(task4);
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut nh = normal_handle;
|
||||
nh.send(Shutdown);
|
||||
let mut sh = special_handle;
|
||||
@ -1232,7 +1232,7 @@ mod test {
|
||||
let special_task = GreenTask::new(&mut special_sched.stack_pool, None, proc() {
|
||||
run(task1);
|
||||
run(task3);
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
special_sched.enqueue_task(special_task);
|
||||
|
||||
@ -1280,24 +1280,24 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn wakeup_across_scheds() {
|
||||
let (port1, chan1) = Chan::new();
|
||||
let (port2, chan2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
|
||||
let mut pool1 = pool();
|
||||
let mut pool2 = pool();
|
||||
|
||||
pool1.spawn(TaskOpts::new(), proc() {
|
||||
let id = sched_id();
|
||||
chan1.send(());
|
||||
port2.recv();
|
||||
tx1.send(());
|
||||
rx2.recv();
|
||||
assert_eq!(id, sched_id());
|
||||
});
|
||||
|
||||
pool2.spawn(TaskOpts::new(), proc() {
|
||||
let id = sched_id();
|
||||
port1.recv();
|
||||
rx1.recv();
|
||||
assert_eq!(id, sched_id());
|
||||
chan2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
pool1.shutdown();
|
||||
@ -1319,18 +1319,18 @@ mod test {
|
||||
#[test]
|
||||
fn multithreading() {
|
||||
run(proc() {
|
||||
let mut ports = ~[];
|
||||
let mut rxs = ~[];
|
||||
for _ in range(0, 10) {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
ports.push(port);
|
||||
rxs.push(rx);
|
||||
}
|
||||
|
||||
loop {
|
||||
match ports.pop() {
|
||||
Some(port) => port.recv(),
|
||||
match rxs.pop() {
|
||||
Some(rx) => rx.recv(),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
@ -1340,45 +1340,45 @@ mod test {
|
||||
#[test]
|
||||
fn thread_ring() {
|
||||
run(proc() {
|
||||
let (end_port, end_chan) = Chan::new();
|
||||
let (end_tx, end_rx) = channel();
|
||||
|
||||
let n_tasks = 10;
|
||||
let token = 2000;
|
||||
|
||||
let (mut p, ch1) = Chan::new();
|
||||
ch1.send((token, end_chan));
|
||||
let (tx1, mut rx) = channel();
|
||||
tx1.send((token, end_tx));
|
||||
let mut i = 2;
|
||||
while i <= n_tasks {
|
||||
let (next_p, ch) = Chan::new();
|
||||
let (tx, next_rx) = channel();
|
||||
let imm_i = i;
|
||||
let imm_p = p;
|
||||
let imm_rx = rx;
|
||||
spawn(proc() {
|
||||
roundtrip(imm_i, n_tasks, &imm_p, &ch);
|
||||
roundtrip(imm_i, n_tasks, &imm_rx, &tx);
|
||||
});
|
||||
p = next_p;
|
||||
rx = next_rx;
|
||||
i += 1;
|
||||
}
|
||||
let p = p;
|
||||
let rx = rx;
|
||||
spawn(proc() {
|
||||
roundtrip(1, n_tasks, &p, &ch1);
|
||||
roundtrip(1, n_tasks, &rx, &tx1);
|
||||
});
|
||||
|
||||
end_port.recv();
|
||||
end_rx.recv();
|
||||
});
|
||||
|
||||
fn roundtrip(id: int, n_tasks: int,
|
||||
p: &Port<(int, Chan<()>)>,
|
||||
ch: &Chan<(int, Chan<()>)>) {
|
||||
rx: &Receiver<(int, Sender<()>)>,
|
||||
tx: &Sender<(int, Sender<()>)>) {
|
||||
loop {
|
||||
match p.recv() {
|
||||
(1, end_chan) => {
|
||||
match rx.recv() {
|
||||
(1, end_tx) => {
|
||||
debug!("{}\n", id);
|
||||
end_chan.send(());
|
||||
end_tx.send(());
|
||||
return;
|
||||
}
|
||||
(token, end_chan) => {
|
||||
(token, end_tx) => {
|
||||
debug!("thread: {} got token: {}", id, token);
|
||||
ch.send((token - 1, end_chan));
|
||||
tx.send((token - 1, end_tx));
|
||||
if token <= n_tasks {
|
||||
return;
|
||||
}
|
||||
@ -1416,15 +1416,15 @@ mod test {
|
||||
event_loop_factory: Some(basic::event_loop),
|
||||
});
|
||||
pool.spawn(TaskOpts::new(), proc() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// This task should not be able to starve the sender;
|
||||
// The sender should get stolen to another thread.
|
||||
spawn(proc() {
|
||||
while port.try_recv() != comm::Data(()) { }
|
||||
while rx.try_recv() != comm::Data(()) { }
|
||||
});
|
||||
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
pool.shutdown();
|
||||
}
|
||||
@ -1432,18 +1432,18 @@ mod test {
|
||||
#[test]
|
||||
fn dont_starve_2() {
|
||||
run(proc() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (_port2, chan2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, _rx2) = channel();
|
||||
|
||||
// This task should not be able to starve the other task.
|
||||
// The sends should eventually yield.
|
||||
spawn(proc() {
|
||||
while port.try_recv() != comm::Data(()) {
|
||||
chan2.send(());
|
||||
while rx1.try_recv() != comm::Data(()) {
|
||||
tx2.send(());
|
||||
}
|
||||
});
|
||||
|
||||
chan.send(());
|
||||
tx1.send(());
|
||||
});
|
||||
}
|
||||
|
||||
@ -1466,29 +1466,29 @@ mod test {
|
||||
// without affecting other schedulers
|
||||
for _ in range(0, 20) {
|
||||
let mut pool = pool();
|
||||
let (start_po, start_ch) = Chan::new();
|
||||
let (fin_po, fin_ch) = Chan::new();
|
||||
let (start_tx, start_rx) = channel();
|
||||
let (fin_tx, fin_rx) = channel();
|
||||
|
||||
let mut handle = pool.spawn_sched();
|
||||
handle.send(PinnedTask(pool.task(TaskOpts::new(), proc() {
|
||||
unsafe {
|
||||
let mut guard = LOCK.lock();
|
||||
|
||||
start_ch.send(());
|
||||
start_tx.send(());
|
||||
guard.wait(); // block the scheduler thread
|
||||
guard.signal(); // let them know we have the lock
|
||||
}
|
||||
|
||||
fin_ch.send(());
|
||||
fin_tx.send(());
|
||||
})));
|
||||
drop(handle);
|
||||
|
||||
let mut handle = pool.spawn_sched();
|
||||
handle.send(PinnedTask(pool.task(TaskOpts::new(), proc() {
|
||||
// Wait until the other task has its lock
|
||||
start_po.recv();
|
||||
start_rx.recv();
|
||||
|
||||
fn pingpong(po: &Port<int>, ch: &Chan<int>) {
|
||||
fn pingpong(po: &Receiver<int>, ch: &Sender<int>) {
|
||||
let mut val = 20;
|
||||
while val > 0 {
|
||||
val = po.recv();
|
||||
@ -1496,17 +1496,17 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
let (setup_po, setup_ch) = Chan::new();
|
||||
let (parent_po, parent_ch) = Chan::new();
|
||||
let (setup_tx, setup_rx) = channel();
|
||||
let (parent_tx, parent_rx) = channel();
|
||||
spawn(proc() {
|
||||
let (child_po, child_ch) = Chan::new();
|
||||
setup_ch.send(child_ch);
|
||||
pingpong(&child_po, &parent_ch);
|
||||
let (child_tx, child_rx) = channel();
|
||||
setup_tx.send(child_tx);
|
||||
pingpong(&child_rx, &parent_tx);
|
||||
});
|
||||
|
||||
let child_ch = setup_po.recv();
|
||||
child_ch.send(20);
|
||||
pingpong(&parent_po, &child_ch);
|
||||
let child_tx = setup_rx.recv();
|
||||
child_tx.send(20);
|
||||
pingpong(&parent_rx, &child_tx);
|
||||
unsafe {
|
||||
let mut guard = LOCK.lock();
|
||||
guard.signal(); // wakeup waiting scheduler
|
||||
@ -1515,7 +1515,7 @@ mod test {
|
||||
})));
|
||||
drop(handle);
|
||||
|
||||
fin_po.recv();
|
||||
fin_rx.recv();
|
||||
pool.shutdown();
|
||||
}
|
||||
unsafe { LOCK.destroy(); }
|
||||
|
@ -500,21 +500,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn_opts(TaskOpts::new(), proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_fail() {
|
||||
let (p, c) = Chan::<()>::new();
|
||||
let (tx, rx) = channel::<int>();
|
||||
spawn_opts(TaskOpts::new(), proc() {
|
||||
let _c = c;
|
||||
let _tx = tx;
|
||||
fail!()
|
||||
});
|
||||
assert_eq!(p.recv_opt(), None);
|
||||
assert_eq!(rx.recv_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -522,55 +522,54 @@ mod tests {
|
||||
let mut opts = TaskOpts::new();
|
||||
opts.name = Some("test".into_maybe_owned());
|
||||
opts.stack_size = Some(20 * 4096);
|
||||
let (p, c) = Chan::new();
|
||||
opts.notify_chan = Some(c);
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
spawn_opts(opts, proc() {});
|
||||
assert!(p.recv().is_ok());
|
||||
assert!(rx.recv().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_opts_fail() {
|
||||
let mut opts = TaskOpts::new();
|
||||
let (p, c) = Chan::new();
|
||||
opts.notify_chan = Some(c);
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
spawn_opts(opts, proc() { fail!() });
|
||||
assert!(p.recv().is_err());
|
||||
assert!(rx.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_test() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn_opts(TaskOpts::new(), proc() {
|
||||
for _ in range(0, 10) { task::deschedule(); }
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_children() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx1, rx) = channel();
|
||||
spawn_opts(TaskOpts::new(), proc() {
|
||||
let (p, c2) = Chan::new();
|
||||
let (tx2, rx) = channel();
|
||||
spawn(proc() {
|
||||
let (p, c3) = Chan::new();
|
||||
let (tx3, rx) = channel();
|
||||
spawn(proc() {
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
});
|
||||
p.recv();
|
||||
c2.send(());
|
||||
rx.recv();
|
||||
tx2.send(());
|
||||
});
|
||||
p.recv();
|
||||
c.send(());
|
||||
rx.recv();
|
||||
tx1.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_inherits() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn_opts(TaskOpts::new(), proc() {
|
||||
let c = c;
|
||||
spawn(proc() {
|
||||
let mut task: ~Task = Local::take();
|
||||
match task.maybe_take_runtime::<GreenTask>() {
|
||||
@ -580,9 +579,9 @@ mod tests {
|
||||
None => fail!(),
|
||||
}
|
||||
Local::put(task);
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
|
@ -532,26 +532,24 @@ mod tests {
|
||||
fn test_file_desc() {
|
||||
// Run this test with some pipes so we don't have to mess around with
|
||||
// opening or closing files.
|
||||
unsafe {
|
||||
let os::Pipe { input, out } = os::pipe();
|
||||
let mut reader = FileDesc::new(input, true);
|
||||
let mut writer = FileDesc::new(out, true);
|
||||
let os::Pipe { input, out } = os::pipe();
|
||||
let mut reader = FileDesc::new(input, true);
|
||||
let mut writer = FileDesc::new(out, true);
|
||||
|
||||
writer.inner_write(bytes!("test")).unwrap();
|
||||
let mut buf = [0u8, ..4];
|
||||
match reader.inner_read(buf) {
|
||||
Ok(4) => {
|
||||
assert_eq!(buf[0], 't' as u8);
|
||||
assert_eq!(buf[1], 'e' as u8);
|
||||
assert_eq!(buf[2], 's' as u8);
|
||||
assert_eq!(buf[3], 't' as u8);
|
||||
}
|
||||
r => fail!("invalid read: {:?}", r)
|
||||
writer.inner_write(bytes!("test")).unwrap();
|
||||
let mut buf = [0u8, ..4];
|
||||
match reader.inner_read(buf) {
|
||||
Ok(4) => {
|
||||
assert_eq!(buf[0], 't' as u8);
|
||||
assert_eq!(buf[1], 'e' as u8);
|
||||
assert_eq!(buf[2], 's' as u8);
|
||||
assert_eq!(buf[3], 't' as u8);
|
||||
}
|
||||
|
||||
assert!(writer.inner_read(buf).is_err());
|
||||
assert!(reader.inner_write(buf).is_err());
|
||||
r => fail!("invalid read: {:?}", r)
|
||||
}
|
||||
|
||||
assert!(writer.inner_read(buf).is_err());
|
||||
assert!(reader.inner_write(buf).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -336,7 +336,7 @@ impl rtio::IoFactory for IoFactory {
|
||||
})
|
||||
}
|
||||
}
|
||||
fn signal(&mut self, _signal: Signum, _channel: Chan<Signum>)
|
||||
fn signal(&mut self, _signal: Signum, _channel: Sender<Signum>)
|
||||
-> IoResult<~RtioSignal> {
|
||||
Err(unimpl())
|
||||
}
|
||||
|
@ -33,28 +33,28 @@ use task;
|
||||
// only torn down after everything else has exited. This means that these
|
||||
// variables are read-only during use (after initialization) and both of which
|
||||
// are safe to use concurrently.
|
||||
static mut HELPER_CHAN: *mut Chan<Req> = 0 as *mut Chan<Req>;
|
||||
static mut HELPER_CHAN: *mut Sender<Req> = 0 as *mut Sender<Req>;
|
||||
static mut HELPER_SIGNAL: imp::signal = 0 as imp::signal;
|
||||
|
||||
static mut TIMER_HELPER_EXIT: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
|
||||
pub fn boot(helper: fn(imp::signal, Port<Req>)) {
|
||||
pub fn boot(helper: fn(imp::signal, Receiver<Req>)) {
|
||||
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
static mut INITIALIZED: bool = false;
|
||||
|
||||
unsafe {
|
||||
let mut _guard = LOCK.lock();
|
||||
if !INITIALIZED {
|
||||
let (msgp, msgc) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
// promote this to a shared channel
|
||||
drop(msgc.clone());
|
||||
HELPER_CHAN = cast::transmute(~msgc);
|
||||
drop(tx.clone());
|
||||
HELPER_CHAN = cast::transmute(~tx);
|
||||
let (receive, send) = imp::new();
|
||||
HELPER_SIGNAL = send;
|
||||
|
||||
task::spawn(proc() {
|
||||
bookkeeping::decrement();
|
||||
helper(receive, msgp);
|
||||
helper(receive, rx);
|
||||
TIMER_HELPER_EXIT.lock().signal()
|
||||
});
|
||||
|
||||
@ -86,8 +86,8 @@ fn shutdown() {
|
||||
// Clean up after ther helper thread
|
||||
unsafe {
|
||||
imp::close(HELPER_SIGNAL);
|
||||
let _chan: ~Chan<Req> = cast::transmute(HELPER_CHAN);
|
||||
HELPER_CHAN = 0 as *mut Chan<Req>;
|
||||
let _chan: ~Sender<Req> = cast::transmute(HELPER_CHAN);
|
||||
HELPER_CHAN = 0 as *mut Sender<Req>;
|
||||
HELPER_SIGNAL = 0 as imp::signal;
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ pub struct Timer {
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
chan: Option<Chan<()>>,
|
||||
tx: Option<Sender<()>>,
|
||||
interval: u64,
|
||||
repeat: bool,
|
||||
target: u64,
|
||||
@ -78,7 +78,7 @@ pub enum Req {
|
||||
|
||||
// Remove a timer based on its id and then send it back on the channel
|
||||
// provided
|
||||
RemoveTimer(uint, Chan<~Inner>),
|
||||
RemoveTimer(uint, Sender<~Inner>),
|
||||
|
||||
// Shut down the loop and then ACK this channel once it's shut down
|
||||
Shutdown,
|
||||
@ -93,7 +93,7 @@ fn now() -> u64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn helper(input: libc::c_int, messages: Port<Req>) {
|
||||
fn helper(input: libc::c_int, messages: Receiver<Req>) {
|
||||
let mut set: imp::fd_set = unsafe { mem::init() };
|
||||
|
||||
let mut fd = FileDesc::new(input, true);
|
||||
@ -118,13 +118,13 @@ fn helper(input: libc::c_int, messages: Port<Req>) {
|
||||
let mut timer = match active.shift() {
|
||||
Some(timer) => timer, None => return
|
||||
};
|
||||
let chan = timer.chan.take_unwrap();
|
||||
if chan.try_send(()) && timer.repeat {
|
||||
timer.chan = Some(chan);
|
||||
let tx = timer.tx.take_unwrap();
|
||||
if tx.try_send(()) && timer.repeat {
|
||||
timer.tx = Some(tx);
|
||||
timer.target += timer.interval;
|
||||
insert(timer, active);
|
||||
} else {
|
||||
drop(chan);
|
||||
drop(tx);
|
||||
dead.push((timer.id, timer));
|
||||
}
|
||||
}
|
||||
@ -208,7 +208,7 @@ impl Timer {
|
||||
Ok(Timer {
|
||||
id: id,
|
||||
inner: Some(~Inner {
|
||||
chan: None,
|
||||
tx: None,
|
||||
interval: 0,
|
||||
target: 0,
|
||||
repeat: false,
|
||||
@ -233,9 +233,9 @@ impl Timer {
|
||||
match self.inner.take() {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
let (p, c) = Chan::new();
|
||||
timer_helper::send(RemoveTimer(self.id, c));
|
||||
p.recv()
|
||||
let (tx, rx) = channel();
|
||||
timer_helper::send(RemoveTimer(self.id, tx));
|
||||
rx.recv()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,38 +244,38 @@ impl Timer {
|
||||
impl rtio::RtioTimer for Timer {
|
||||
fn sleep(&mut self, msecs: u64) {
|
||||
let mut inner = self.inner();
|
||||
inner.chan = None; // cancel any previous request
|
||||
inner.tx = None; // cancel any previous request
|
||||
self.inner = Some(inner);
|
||||
|
||||
Timer::sleep(msecs);
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64) -> Port<()> {
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
inner.repeat = false;
|
||||
inner.chan = Some(c);
|
||||
inner.tx = Some(tx);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
timer_helper::send(NewTimer(inner));
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64) -> Port<()> {
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
inner.repeat = true;
|
||||
inner.chan = Some(c);
|
||||
inner.tx = Some(tx);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
timer_helper::send(NewTimer(inner));
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,12 @@ pub struct Timer {
|
||||
|
||||
#[allow(visible_private_types)]
|
||||
pub enum Req {
|
||||
NewTimer(libc::c_int, Chan<()>, bool, imp::itimerspec),
|
||||
RemoveTimer(libc::c_int, Chan<()>),
|
||||
NewTimer(libc::c_int, Sender<()>, bool, imp::itimerspec),
|
||||
RemoveTimer(libc::c_int, Sender<()>),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
fn helper(input: libc::c_int, messages: Port<Req>) {
|
||||
fn helper(input: libc::c_int, messages: Receiver<Req>) {
|
||||
let efd = unsafe { imp::epoll_create(10) };
|
||||
let _fd1 = FileDesc::new(input, true);
|
||||
let _fd2 = FileDesc::new(efd, true);
|
||||
@ -76,7 +76,7 @@ fn helper(input: libc::c_int, messages: Port<Req>) {
|
||||
|
||||
add(efd, input);
|
||||
let events: [imp::epoll_event, ..16] = unsafe { mem::init() };
|
||||
let mut list: ~[(libc::c_int, Chan<()>, bool)] = ~[];
|
||||
let mut list: ~[(libc::c_int, Sender<()>, bool)] = ~[];
|
||||
'outer: loop {
|
||||
let n = match unsafe {
|
||||
imp::epoll_wait(efd, events.as_ptr(),
|
||||
@ -197,9 +197,9 @@ impl Timer {
|
||||
fn remove(&mut self) {
|
||||
if !self.on_worker { return }
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
timer_helper::send(RemoveTimer(self.fd.fd(), c));
|
||||
p.recv();
|
||||
let (tx, rx) = channel();
|
||||
timer_helper::send(RemoveTimer(self.fd.fd(), tx));
|
||||
rx.recv();
|
||||
self.on_worker = false;
|
||||
}
|
||||
}
|
||||
@ -224,8 +224,8 @@ impl rtio::RtioTimer for Timer {
|
||||
// before returning to guarantee the invariant that when oneshot() and
|
||||
// period() return that the old port will never receive any more messages.
|
||||
|
||||
fn oneshot(&mut self, msecs: u64) -> Port<()> {
|
||||
let (p, c) = Chan::new();
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let new_value = imp::itimerspec {
|
||||
it_interval: imp::timespec { tv_sec: 0, tv_nsec: 0 },
|
||||
@ -234,26 +234,26 @@ impl rtio::RtioTimer for Timer {
|
||||
tv_nsec: ((msecs % 1000) * 1000000) as libc::c_long,
|
||||
}
|
||||
};
|
||||
timer_helper::send(NewTimer(self.fd.fd(), c, true, new_value));
|
||||
p.recv();
|
||||
timer_helper::send(NewTimer(self.fd.fd(), tx, true, new_value));
|
||||
rx.recv();
|
||||
self.on_worker = true;
|
||||
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64) -> Port<()> {
|
||||
let (p, c) = Chan::new();
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let spec = imp::timespec {
|
||||
tv_sec: (msecs / 1000) as libc::time_t,
|
||||
tv_nsec: ((msecs % 1000) * 1000000) as libc::c_long,
|
||||
};
|
||||
let new_value = imp::itimerspec { it_interval: spec, it_value: spec, };
|
||||
timer_helper::send(NewTimer(self.fd.fd(), c, false, new_value));
|
||||
p.recv();
|
||||
timer_helper::send(NewTimer(self.fd.fd(), tx, false, new_value));
|
||||
rx.recv();
|
||||
self.on_worker = true;
|
||||
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,12 @@ pub struct Timer {
|
||||
}
|
||||
|
||||
pub enum Req {
|
||||
NewTimer(libc::HANDLE, Chan<()>, bool),
|
||||
RemoveTimer(libc::HANDLE, Chan<()>),
|
||||
NewTimer(libc::HANDLE, Sender<()>, bool),
|
||||
RemoveTimer(libc::HANDLE, Sender<()>),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
fn helper(input: libc::HANDLE, messages: Port<Req>) {
|
||||
fn helper(input: libc::HANDLE, messages: Receiver<Req>) {
|
||||
let mut objs = ~[input];
|
||||
let mut chans = ~[];
|
||||
|
||||
@ -113,9 +113,9 @@ impl Timer {
|
||||
fn remove(&mut self) {
|
||||
if !self.on_worker { return }
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
timer_helper::send(RemoveTimer(self.obj, c));
|
||||
p.recv();
|
||||
let (tx, rx) = channel();
|
||||
timer_helper::send(RemoveTimer(self.obj, tx));
|
||||
rx.recv();
|
||||
|
||||
self.on_worker = false;
|
||||
}
|
||||
@ -136,9 +136,9 @@ impl rtio::RtioTimer for Timer {
|
||||
let _ = unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE) };
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64) -> Port<()> {
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
self.remove();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// see above for the calculation
|
||||
let due = -(msecs * 10000) as libc::LARGE_INTEGER;
|
||||
@ -147,14 +147,14 @@ impl rtio::RtioTimer for Timer {
|
||||
ptr::mut_null(), 0)
|
||||
}, 1);
|
||||
|
||||
timer_helper::send(NewTimer(self.obj, c, true));
|
||||
timer_helper::send(NewTimer(self.obj, tx, true));
|
||||
self.on_worker = true;
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64) -> Port<()> {
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()> {
|
||||
self.remove();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// see above for the calculation
|
||||
let due = -(msecs * 10000) as libc::LARGE_INTEGER;
|
||||
@ -163,10 +163,10 @@ impl rtio::RtioTimer for Timer {
|
||||
ptr::null(), ptr::mut_null(), 0)
|
||||
}, 1);
|
||||
|
||||
timer_helper::send(NewTimer(self.obj, c, false));
|
||||
timer_helper::send(NewTimer(self.obj, tx, false));
|
||||
self.on_worker = true;
|
||||
|
||||
return p;
|
||||
return rx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,21 +262,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_fail() {
|
||||
let (p, c) = Chan::<()>::new();
|
||||
let (tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let _c = c;
|
||||
let _tx = tx;
|
||||
fail!()
|
||||
});
|
||||
assert_eq!(p.recv_opt(), None);
|
||||
assert_eq!(rx.recv_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -284,55 +284,54 @@ mod tests {
|
||||
let mut opts = TaskOpts::new();
|
||||
opts.name = Some("test".into_maybe_owned());
|
||||
opts.stack_size = Some(20 * 4096);
|
||||
let (p, c) = Chan::new();
|
||||
opts.notify_chan = Some(c);
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
spawn_opts(opts, proc() {});
|
||||
assert!(p.recv().is_ok());
|
||||
assert!(rx.recv().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_opts_fail() {
|
||||
let mut opts = TaskOpts::new();
|
||||
let (p, c) = Chan::new();
|
||||
opts.notify_chan = Some(c);
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
spawn_opts(opts, proc() { fail!() });
|
||||
assert!(p.recv().is_err());
|
||||
assert!(rx.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_test() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
for _ in range(0, 10) { task::deschedule(); }
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_children() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx1, rx) = channel();
|
||||
spawn(proc() {
|
||||
let (p, c2) = Chan::new();
|
||||
let (tx2, rx) = channel();
|
||||
spawn(proc() {
|
||||
let (p, c3) = Chan::new();
|
||||
let (tx3, rx) = channel();
|
||||
spawn(proc() {
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
});
|
||||
p.recv();
|
||||
c2.send(());
|
||||
rx.recv();
|
||||
tx2.send(());
|
||||
});
|
||||
p.recv();
|
||||
c.send(());
|
||||
rx.recv();
|
||||
tx1.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_inherits() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let c = c;
|
||||
spawn(proc() {
|
||||
let mut task: ~Task = Local::take();
|
||||
match task.maybe_take_runtime::<Ops>() {
|
||||
@ -342,9 +341,9 @@ mod tests {
|
||||
None => fail!(),
|
||||
}
|
||||
Local::put(task);
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
|
@ -149,13 +149,13 @@ mod test {
|
||||
#[test]
|
||||
fn test_os_rng_tasks() {
|
||||
|
||||
let mut chans = ~[];
|
||||
let mut txs = ~[];
|
||||
for _ in range(0, 20) {
|
||||
let (p, c) = Chan::new();
|
||||
chans.push(c);
|
||||
let (tx, rx) = channel();
|
||||
txs.push(tx);
|
||||
task::spawn(proc() {
|
||||
// wait until all the tasks are ready to go.
|
||||
p.recv();
|
||||
rx.recv();
|
||||
|
||||
// deschedule to attempt to interleave things as much
|
||||
// as possible (XXX: is this a good test?)
|
||||
@ -175,8 +175,8 @@ mod test {
|
||||
}
|
||||
|
||||
// start all the tasks
|
||||
for c in chans.iter() {
|
||||
c.send(())
|
||||
for tx in txs.iter() {
|
||||
tx.send(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,9 +379,9 @@ pub fn monitor(f: proc()) {
|
||||
task_builder.opts.stack_size = Some(STACK_SIZE);
|
||||
}
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let w = io::ChanWriter::new(c);
|
||||
let mut r = io::PortReader::new(p);
|
||||
let (tx, rx) = channel();
|
||||
let w = io::ChanWriter::new(tx);
|
||||
let mut r = io::ChanReader::new(rx);
|
||||
|
||||
match task_builder.try(proc() {
|
||||
io::stdio::set_stderr(~w as ~io::Writer);
|
||||
|
@ -116,12 +116,12 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||
//
|
||||
// The basic idea is to not use a default_handler() for rustc, and then also
|
||||
// not print things by default to the actual stderr.
|
||||
let (p, c) = Chan::new();
|
||||
let w1 = io::ChanWriter::new(c);
|
||||
let (tx, rx) = channel();
|
||||
let w1 = io::ChanWriter::new(tx);
|
||||
let w2 = w1.clone();
|
||||
let old = io::stdio::set_stderr(~w1);
|
||||
spawn(proc() {
|
||||
let mut p = io::PortReader::new(p);
|
||||
let mut p = io::ChanReader::new(rx);
|
||||
let mut err = old.unwrap_or(~io::stderr() as ~Writer);
|
||||
io::util::copy(&mut p, &mut err).unwrap();
|
||||
});
|
||||
|
@ -135,7 +135,7 @@ mod test_remote {
|
||||
// actually trigger what they say they will.
|
||||
#[test]
|
||||
fn smoke_test() {
|
||||
struct MyCallback(Option<Chan<int>>);
|
||||
struct MyCallback(Option<Sender<int>>);
|
||||
impl Callback for MyCallback {
|
||||
fn call(&mut self) {
|
||||
// this can get called more than once, but we only want to send
|
||||
@ -147,8 +147,8 @@ mod test_remote {
|
||||
}
|
||||
}
|
||||
|
||||
let (port, chan) = Chan::new();
|
||||
let cb = ~MyCallback(Some(chan));
|
||||
let (tx, rx) = channel();
|
||||
let cb = ~MyCallback(Some(tx));
|
||||
let watcher = AsyncWatcher::new(&mut local_loop().loop_,
|
||||
cb as ~Callback);
|
||||
|
||||
@ -157,7 +157,7 @@ mod test_remote {
|
||||
watcher.fire();
|
||||
});
|
||||
|
||||
assert_eq!(port.recv(), 1);
|
||||
assert_eq!(rx.recv(), 1);
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ mod test {
|
||||
// thread, close itself, and then come back to the last thread.
|
||||
#[test]
|
||||
fn test_homing_closes_correctly() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let mut pool = SchedPool::new(PoolConfig {
|
||||
threads: 1,
|
||||
event_loop_factory: None,
|
||||
@ -172,11 +172,11 @@ mod test {
|
||||
|
||||
pool.spawn(TaskOpts::new(), proc() {
|
||||
let listener = UdpWatcher::bind(local_loop(), next_test_ip4());
|
||||
chan.send(listener.unwrap());
|
||||
tx.send(listener.unwrap());
|
||||
});
|
||||
|
||||
let task = pool.task(TaskOpts::new(), proc() {
|
||||
drop(port.recv());
|
||||
drop(rx.recv());
|
||||
});
|
||||
pool.spawn_sched().send(sched::TaskFromFriend(task));
|
||||
|
||||
@ -185,7 +185,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_homing_read() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let mut pool = SchedPool::new(PoolConfig {
|
||||
threads: 1,
|
||||
event_loop_factory: None,
|
||||
@ -195,13 +195,13 @@ mod test {
|
||||
let addr1 = next_test_ip4();
|
||||
let addr2 = next_test_ip4();
|
||||
let listener = UdpWatcher::bind(local_loop(), addr2);
|
||||
chan.send((listener.unwrap(), addr1));
|
||||
tx.send((listener.unwrap(), addr1));
|
||||
let mut listener = UdpWatcher::bind(local_loop(), addr1).unwrap();
|
||||
listener.sendto([1, 2, 3, 4], addr2).unwrap();
|
||||
});
|
||||
|
||||
let task = pool.task(TaskOpts::new(), proc() {
|
||||
let (mut watcher, addr) = port.recv();
|
||||
let (mut watcher, addr) = rx.recv();
|
||||
let mut buf = [0, ..10];
|
||||
assert_eq!(watcher.recvfrom(buf).unwrap(), (4, addr));
|
||||
});
|
||||
|
@ -167,8 +167,8 @@ pub struct TcpListener {
|
||||
home: HomeHandle,
|
||||
handle: *uvll::uv_pipe_t,
|
||||
priv closing_task: Option<BlockedTask>,
|
||||
priv outgoing: Chan<Result<~rtio::RtioTcpStream, IoError>>,
|
||||
priv incoming: Port<Result<~rtio::RtioTcpStream, IoError>>,
|
||||
priv outgoing: Sender<Result<~rtio::RtioTcpStream, IoError>>,
|
||||
priv incoming: Receiver<Result<~rtio::RtioTcpStream, IoError>>,
|
||||
}
|
||||
|
||||
pub struct TcpAcceptor {
|
||||
@ -329,13 +329,13 @@ impl TcpListener {
|
||||
assert_eq!(unsafe {
|
||||
uvll::uv_tcp_init(io.uv_loop(), handle)
|
||||
}, 0);
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let l = ~TcpListener {
|
||||
home: io.make_handle(),
|
||||
handle: handle,
|
||||
closing_task: None,
|
||||
outgoing: chan,
|
||||
incoming: port,
|
||||
outgoing: tx,
|
||||
incoming: rx,
|
||||
};
|
||||
let (addr, _len) = addr_to_sockaddr(address);
|
||||
let res = unsafe {
|
||||
@ -741,7 +741,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn listen_ip4() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let addr = next_test_ip4();
|
||||
|
||||
spawn(proc() {
|
||||
@ -751,7 +751,7 @@ mod test {
|
||||
let mut w = match w.listen() {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e),
|
||||
};
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
match w.accept() {
|
||||
Ok(mut stream) => {
|
||||
let mut buf = [0u8, ..10];
|
||||
@ -766,7 +766,7 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut w = match TcpWatcher::connect(local_loop(), addr) {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
||||
};
|
||||
@ -777,7 +777,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn listen_ip6() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let addr = next_test_ip6();
|
||||
|
||||
spawn(proc() {
|
||||
@ -787,7 +787,7 @@ mod test {
|
||||
let mut w = match w.listen() {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e),
|
||||
};
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
match w.accept() {
|
||||
Ok(mut stream) => {
|
||||
let mut buf = [0u8, ..10];
|
||||
@ -802,7 +802,7 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut w = match TcpWatcher::connect(local_loop(), addr) {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
||||
};
|
||||
@ -813,14 +813,14 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn udp_recv_ip4() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let client = next_test_ip4();
|
||||
let server = next_test_ip4();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpWatcher::bind(local_loop(), server) {
|
||||
Ok(mut w) => {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut buf = [0u8, ..10];
|
||||
match w.recvfrom(buf) {
|
||||
Ok((10, addr)) => assert_eq!(addr, client),
|
||||
@ -834,7 +834,7 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut w = match UdpWatcher::bind(local_loop(), client) {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
||||
};
|
||||
@ -845,14 +845,14 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn udp_recv_ip6() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let client = next_test_ip6();
|
||||
let server = next_test_ip6();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpWatcher::bind(local_loop(), server) {
|
||||
Ok(mut w) => {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut buf = [0u8, ..10];
|
||||
match w.recvfrom(buf) {
|
||||
Ok((10, addr)) => assert_eq!(addr, client),
|
||||
@ -866,7 +866,7 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut w = match UdpWatcher::bind(local_loop(), client) {
|
||||
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
||||
};
|
||||
@ -879,12 +879,12 @@ mod test {
|
||||
fn test_read_read_read() {
|
||||
let addr = next_test_ip4();
|
||||
static MAX: uint = 5000;
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let listener = TcpListener::bind(local_loop(), addr).unwrap();
|
||||
let mut acceptor = listener.listen().unwrap();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut stream = acceptor.accept().unwrap();
|
||||
let buf = [1, .. 2048];
|
||||
let mut total_bytes_written = 0;
|
||||
@ -895,7 +895,7 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut stream = TcpWatcher::connect(local_loop(), addr).unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
let mut total_bytes_read = 0;
|
||||
@ -914,17 +914,17 @@ mod test {
|
||||
fn test_udp_twice() {
|
||||
let server_addr = next_test_ip4();
|
||||
let client_addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let mut client = UdpWatcher::bind(local_loop(), client_addr).unwrap();
|
||||
port.recv();
|
||||
rx.recv();
|
||||
assert!(client.sendto([1], server_addr).is_ok());
|
||||
assert!(client.sendto([2], server_addr).is_ok());
|
||||
});
|
||||
|
||||
let mut server = UdpWatcher::bind(local_loop(), server_addr).unwrap();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut buf1 = [0];
|
||||
let mut buf2 = [0];
|
||||
let (nread1, src1) = server.recvfrom(buf1).unwrap();
|
||||
@ -945,16 +945,16 @@ mod test {
|
||||
let client_in_addr = next_test_ip4();
|
||||
static MAX: uint = 500_000;
|
||||
|
||||
let (p1, c1) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel::<()>();
|
||||
let (tx2, rx2) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
let l = local_loop();
|
||||
let mut server_out = UdpWatcher::bind(l, server_out_addr).unwrap();
|
||||
let mut server_in = UdpWatcher::bind(l, server_in_addr).unwrap();
|
||||
let (port, chan) = (p1, c2);
|
||||
chan.send(());
|
||||
port.recv();
|
||||
let (tx, rx) = (tx2, rx1);
|
||||
tx.send(());
|
||||
rx.recv();
|
||||
let msg = [1, .. 2048];
|
||||
let mut total_bytes_sent = 0;
|
||||
let mut buf = [1];
|
||||
@ -975,9 +975,9 @@ mod test {
|
||||
let l = local_loop();
|
||||
let mut client_out = UdpWatcher::bind(l, client_out_addr).unwrap();
|
||||
let mut client_in = UdpWatcher::bind(l, client_in_addr).unwrap();
|
||||
let (port, chan) = (p2, c1);
|
||||
port.recv();
|
||||
chan.send(());
|
||||
let (tx, rx) = (tx1, rx2);
|
||||
rx.recv();
|
||||
tx.send(());
|
||||
let mut total_bytes_recv = 0;
|
||||
let mut buf = [0, .. 2048];
|
||||
while total_bytes_recv < MAX {
|
||||
@ -1000,23 +1000,23 @@ mod test {
|
||||
#[test]
|
||||
fn test_read_and_block() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::<Port<()>>::new();
|
||||
let (tx, rx) = channel::<Receiver<()>>();
|
||||
|
||||
spawn(proc() {
|
||||
let port2 = port.recv();
|
||||
let rx = rx.recv();
|
||||
let mut stream = TcpWatcher::connect(local_loop(), addr).unwrap();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||
port2.recv();
|
||||
rx.recv();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||
port2.recv();
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
let listener = TcpListener::bind(local_loop(), addr).unwrap();
|
||||
let mut acceptor = listener.listen().unwrap();
|
||||
let (port2, chan2) = Chan::new();
|
||||
chan.send(port2);
|
||||
let (tx2, rx2) = channel();
|
||||
tx.send(rx2);
|
||||
let mut stream = acceptor.accept().unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
|
||||
@ -1033,7 +1033,7 @@ mod test {
|
||||
}
|
||||
reads += 1;
|
||||
|
||||
chan2.try_send(());
|
||||
tx2.try_send(());
|
||||
}
|
||||
|
||||
// Make sure we had multiple reads
|
||||
@ -1073,16 +1073,16 @@ mod test {
|
||||
|
||||
#[should_fail] #[test]
|
||||
fn tcp_stream_fail_cleanup() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let addr = next_test_ip4();
|
||||
|
||||
spawn(proc() {
|
||||
let w = TcpListener::bind(local_loop(), addr).unwrap();
|
||||
let mut w = w.listen().unwrap();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
drop(w.accept().unwrap());
|
||||
});
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let _w = TcpWatcher::connect(local_loop(), addr).unwrap();
|
||||
fail!();
|
||||
}
|
||||
@ -1097,17 +1097,17 @@ mod test {
|
||||
#[should_fail] #[test]
|
||||
fn udp_fail_other_task() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// force the handle to be created on a different scheduler, failure in
|
||||
// the original task will force a homing operation back to this
|
||||
// scheduler.
|
||||
spawn(proc() {
|
||||
let w = UdpWatcher::bind(local_loop(), addr).unwrap();
|
||||
chan.send(w);
|
||||
tx.send(w);
|
||||
});
|
||||
|
||||
let _w = port.recv();
|
||||
let _w = rx.recv();
|
||||
fail!();
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ pub struct PipeWatcher {
|
||||
pub struct PipeListener {
|
||||
home: HomeHandle,
|
||||
pipe: *uvll::uv_pipe_t,
|
||||
priv outgoing: Chan<Result<~RtioPipe, IoError>>,
|
||||
priv incoming: Port<Result<~RtioPipe, IoError>>,
|
||||
priv outgoing: Sender<Result<~RtioPipe, IoError>>,
|
||||
priv incoming: Receiver<Result<~RtioPipe, IoError>>,
|
||||
}
|
||||
|
||||
pub struct PipeAcceptor {
|
||||
@ -182,12 +182,12 @@ impl PipeListener {
|
||||
// If successful, unwrap the PipeWatcher because we control how
|
||||
// we close the pipe differently. We can't rely on
|
||||
// StreamWatcher's default close method.
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let p = ~PipeListener {
|
||||
home: io.make_handle(),
|
||||
pipe: pipe.unwrap(),
|
||||
incoming: port,
|
||||
outgoing: chan,
|
||||
incoming: rx,
|
||||
outgoing: tx,
|
||||
};
|
||||
Ok(p.install())
|
||||
}
|
||||
@ -299,19 +299,19 @@ mod tests {
|
||||
fn connect() {
|
||||
let path = next_test_unix();
|
||||
let path2 = path.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let p = PipeListener::bind(local_loop(), &path2.to_c_str()).unwrap();
|
||||
let mut p = p.listen().unwrap();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut client = p.accept().unwrap();
|
||||
let mut buf = [0];
|
||||
assert!(client.read(buf).unwrap() == 1);
|
||||
assert_eq!(buf[0], 1);
|
||||
assert!(client.write([2]).is_ok());
|
||||
});
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let mut c = PipeWatcher::connect(local_loop(), &path.to_c_str()).unwrap();
|
||||
assert!(c.write([1]).is_ok());
|
||||
let mut buf = [0];
|
||||
@ -323,15 +323,15 @@ mod tests {
|
||||
fn connect_fail() {
|
||||
let path = next_test_unix();
|
||||
let path2 = path.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let p = PipeListener::bind(local_loop(), &path2.to_c_str()).unwrap();
|
||||
let mut p = p.listen().unwrap();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
drop(p.accept().unwrap());
|
||||
});
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let _c = PipeWatcher::connect(local_loop(), &path.to_c_str()).unwrap();
|
||||
fail!()
|
||||
|
||||
|
@ -21,13 +21,13 @@ pub struct SignalWatcher {
|
||||
handle: *uvll::uv_signal_t,
|
||||
home: HomeHandle,
|
||||
|
||||
channel: Chan<Signum>,
|
||||
channel: Sender<Signum>,
|
||||
signal: Signum,
|
||||
}
|
||||
|
||||
impl SignalWatcher {
|
||||
pub fn new(io: &mut UvIoFactory, signum: Signum,
|
||||
channel: Chan<Signum>) -> Result<~SignalWatcher, UvError> {
|
||||
channel: Sender<Signum>) -> Result<~SignalWatcher, UvError> {
|
||||
let s = ~SignalWatcher {
|
||||
handle: UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL),
|
||||
home: io.make_handle(),
|
||||
@ -80,12 +80,12 @@ mod test {
|
||||
#[test]
|
||||
fn closing_channel_during_drop_doesnt_kill_everything() {
|
||||
// see issue #10375, relates to timers as well.
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let _signal = SignalWatcher::new(local_loop(), signal::Interrupt,
|
||||
chan);
|
||||
tx);
|
||||
|
||||
spawn(proc() {
|
||||
let _ = port.recv_opt();
|
||||
let _ = rx.recv_opt();
|
||||
});
|
||||
|
||||
// when we drop the SignalWatcher we're going to destroy the channel,
|
||||
|
@ -28,8 +28,8 @@ pub struct TimerWatcher {
|
||||
|
||||
pub enum NextAction {
|
||||
WakeTask,
|
||||
SendOnce(Chan<()>),
|
||||
SendMany(Chan<()>, uint),
|
||||
SendOnce(Sender<()>),
|
||||
SendMany(Sender<()>, uint),
|
||||
}
|
||||
|
||||
impl TimerWatcher {
|
||||
@ -97,8 +97,8 @@ impl RtioTimer for TimerWatcher {
|
||||
self.stop();
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64) -> Port<()> {
|
||||
let (port, chan) = Chan::new();
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// similarly to the destructor, we must drop the previous action outside
|
||||
// of the homing missile
|
||||
@ -107,14 +107,14 @@ impl RtioTimer for TimerWatcher {
|
||||
self.id += 1;
|
||||
self.stop();
|
||||
self.start(msecs, 0);
|
||||
mem::replace(&mut self.action, Some(SendOnce(chan)))
|
||||
mem::replace(&mut self.action, Some(SendOnce(tx)))
|
||||
};
|
||||
|
||||
return port;
|
||||
return rx;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64) -> Port<()> {
|
||||
let (port, chan) = Chan::new();
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()> {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// similarly to the destructor, we must drop the previous action outside
|
||||
// of the homing missile
|
||||
@ -123,10 +123,10 @@ impl RtioTimer for TimerWatcher {
|
||||
self.id += 1;
|
||||
self.stop();
|
||||
self.start(msecs, msecs);
|
||||
mem::replace(&mut self.action, Some(SendMany(chan, self.id)))
|
||||
mem::replace(&mut self.action, Some(SendMany(tx, self.id)))
|
||||
};
|
||||
|
||||
return port;
|
||||
return rx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ impl IoFactory for UvIoFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fn signal(&mut self, signum: Signum, channel: Chan<Signum>)
|
||||
fn signal(&mut self, signum: Signum, channel: Sender<Signum>)
|
||||
-> Result<~rtio::RtioSignal, IoError> {
|
||||
match SignalWatcher::new(self, signum, channel) {
|
||||
Ok(s) => Ok(s as ~rtio::RtioSignal),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@
|
||||
/// The one caveat to consider is that when a port sees a disconnected channel
|
||||
/// it must check for data because there is no "data plus upgrade" state.
|
||||
|
||||
use comm::Port;
|
||||
use comm::Receiver;
|
||||
use kinds::Send;
|
||||
use mem;
|
||||
use ops::Drop;
|
||||
@ -60,7 +60,7 @@ pub struct Packet<T> {
|
||||
pub enum Failure<T> {
|
||||
Empty,
|
||||
Disconnected,
|
||||
Upgraded(Port<T>),
|
||||
Upgraded(Receiver<T>),
|
||||
}
|
||||
|
||||
pub enum UpgradeResult {
|
||||
@ -71,14 +71,14 @@ pub enum UpgradeResult {
|
||||
|
||||
pub enum SelectionResult<T> {
|
||||
SelCanceled(BlockedTask),
|
||||
SelUpgraded(BlockedTask, Port<T>),
|
||||
SelUpgraded(BlockedTask, Receiver<T>),
|
||||
SelSuccess,
|
||||
}
|
||||
|
||||
enum MyUpgrade<T> {
|
||||
NothingSent,
|
||||
SendUsed,
|
||||
GoUp(Port<T>),
|
||||
GoUp(Receiver<T>),
|
||||
}
|
||||
|
||||
impl<T: Send> Packet<T> {
|
||||
@ -201,7 +201,7 @@ impl<T: Send> Packet<T> {
|
||||
// Returns whether the upgrade was completed. If the upgrade wasn't
|
||||
// completed, then the port couldn't get sent to the other half (it will
|
||||
// never receive it).
|
||||
pub fn upgrade(&mut self, up: Port<T>) -> UpgradeResult {
|
||||
pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
|
||||
let prev = match self.upgrade {
|
||||
NothingSent => NothingSent,
|
||||
SendUsed => SendUsed,
|
||||
@ -259,7 +259,7 @@ impl<T: Send> Packet<T> {
|
||||
|
||||
// If Ok, the value is whether this port has data, if Err, then the upgraded
|
||||
// port needs to be checked instead of this one.
|
||||
pub fn can_recv(&mut self) -> Result<bool, Port<T>> {
|
||||
pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
|
||||
match self.state.load(atomics::SeqCst) {
|
||||
EMPTY => Ok(false), // Welp, we tried
|
||||
DATA => Ok(true), // we have some un-acquired data
|
||||
@ -318,7 +318,7 @@ impl<T: Send> Packet<T> {
|
||||
// blocked task will no longer be visible to any other threads.
|
||||
//
|
||||
// The return value indicates whether there's data on this port.
|
||||
pub fn abort_selection(&mut self) -> Result<bool, Port<T>> {
|
||||
pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
|
||||
let state = match self.state.load(atomics::SeqCst) {
|
||||
// Each of these states means that no further activity will happen
|
||||
// with regard to abortion selection
|
||||
|
@ -8,38 +8,39 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Selection over an array of ports
|
||||
//! Selection over an array of receivers
|
||||
//!
|
||||
//! This module contains the implementation machinery necessary for selecting
|
||||
//! over a number of ports. One large goal of this module is to provide an
|
||||
//! efficient interface to selecting over any port of any type.
|
||||
//! over a number of receivers. One large goal of this module is to provide an
|
||||
//! efficient interface to selecting over any receiver of any type.
|
||||
//!
|
||||
//! This is achieved through an architecture of a "port set" in which ports are
|
||||
//! added to a set and then the entire set is waited on at once. The set can be
|
||||
//! waited on multiple times to prevent re-adding each port to the set.
|
||||
//! This is achieved through an architecture of a "receiver set" in which
|
||||
//! receivers are added to a set and then the entire set is waited on at once.
|
||||
//! The set can be waited on multiple times to prevent re-adding each receiver
|
||||
//! to the set.
|
||||
//!
|
||||
//! Usage of this module is currently encouraged to go through the use of the
|
||||
//! `select!` macro. This macro allows naturally binding of variables to the
|
||||
//! received values of ports in a much more natural syntax then usage of the
|
||||
//! received values of receivers in a much more natural syntax then usage of the
|
||||
//! `Select` structure directly.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! let (mut p1, c1) = Chan::new();
|
||||
//! let (mut p2, c2) = Chan::new();
|
||||
//! ```rust
|
||||
//! let (tx1, rx1) = channel();
|
||||
//! let (tx2, rx2) = channel();
|
||||
//!
|
||||
//! c1.send(1);
|
||||
//! c2.send(2);
|
||||
//! tx1.send(1);
|
||||
//! tx2.send(2);
|
||||
//!
|
||||
//! select! (
|
||||
//! val = p1.recv() => {
|
||||
//! select! {
|
||||
//! val = rx1.recv() => {
|
||||
//! assert_eq!(val, 1);
|
||||
//! }
|
||||
//! val = p2.recv() => {
|
||||
//! },
|
||||
//! val = rx2.recv() => {
|
||||
//! assert_eq!(val, 2);
|
||||
//! }
|
||||
//! )
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#[allow(dead_code)];
|
||||
@ -55,11 +56,11 @@ use ptr::RawPtr;
|
||||
use result::{Ok, Err, Result};
|
||||
use rt::local::Local;
|
||||
use rt::task::{Task, BlockedTask};
|
||||
use super::Port;
|
||||
use super::Receiver;
|
||||
use uint;
|
||||
|
||||
/// The "port set" of the select interface. This structure is used to manage a
|
||||
/// set of ports which are being selected over.
|
||||
/// The "receiver set" of the select interface. This structure is used to manage
|
||||
/// a set of receivers which are being selected over.
|
||||
pub struct Select {
|
||||
priv head: *mut Handle<'static, ()>,
|
||||
priv tail: *mut Handle<'static, ()>,
|
||||
@ -68,22 +69,22 @@ pub struct Select {
|
||||
priv marker2: marker::NoFreeze,
|
||||
}
|
||||
|
||||
/// A handle to a port which is currently a member of a `Select` set of ports.
|
||||
/// This handle is used to keep the port in the set as well as interact with the
|
||||
/// underlying port.
|
||||
pub struct Handle<'port, T> {
|
||||
/// A handle to a receiver which is currently a member of a `Select` set of
|
||||
/// receivers. This handle is used to keep the receiver in the set as well as
|
||||
/// interact with the underlying receiver.
|
||||
pub struct Handle<'rx, T> {
|
||||
/// The ID of this handle, used to compare against the return value of
|
||||
/// `Select::wait()`
|
||||
priv id: uint,
|
||||
priv selector: &'port Select,
|
||||
priv selector: &'rx Select,
|
||||
priv next: *mut Handle<'static, ()>,
|
||||
priv prev: *mut Handle<'static, ()>,
|
||||
priv added: bool,
|
||||
priv packet: &'port Packet,
|
||||
priv packet: &'rx Packet,
|
||||
|
||||
// due to our fun transmutes, we be sure to place this at the end. (nothing
|
||||
// previous relies on T)
|
||||
priv port: &'port Port<T>,
|
||||
priv rx: &'rx Receiver<T>,
|
||||
}
|
||||
|
||||
struct Packets { cur: *mut Handle<'static, ()> }
|
||||
@ -111,10 +112,10 @@ impl Select {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new handle into this port set for a new port. Note that this
|
||||
/// does *not* add the port to the port set, for that you must call the
|
||||
/// `add` method on the handle itself.
|
||||
pub fn handle<'a, T: Send>(&'a self, port: &'a Port<T>) -> Handle<'a, T> {
|
||||
/// Creates a new handle into this receiver set for a new receiver. Note
|
||||
/// that this does *not* add the receiver to the receiver set, for that you
|
||||
/// must call the `add` method on the handle itself.
|
||||
pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
|
||||
let id = self.next_id.get();
|
||||
self.next_id.set(id + 1);
|
||||
Handle {
|
||||
@ -123,12 +124,12 @@ impl Select {
|
||||
next: 0 as *mut Handle<'static, ()>,
|
||||
prev: 0 as *mut Handle<'static, ()>,
|
||||
added: false,
|
||||
port: port,
|
||||
packet: port,
|
||||
rx: rx,
|
||||
packet: rx,
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits for an event on this port set. The returned value is *not* an
|
||||
/// Waits for an event on this receiver set. The returned value is *not* an
|
||||
/// index, but rather an id. This id can be queried against any active
|
||||
/// `Handle` structures (each one has an `id` method). The handle with
|
||||
/// the matching `id` will have some sort of event available on it. The
|
||||
@ -141,24 +142,24 @@ impl Select {
|
||||
/// Helper method for skipping the preflight checks during testing
|
||||
fn wait2(&self, do_preflight_checks: bool) -> uint {
|
||||
// Note that this is currently an inefficient implementation. We in
|
||||
// theory have knowledge about all ports in the set ahead of time, so
|
||||
// this method shouldn't really have to iterate over all of them yet
|
||||
// again. The idea with this "port set" interface is to get the
|
||||
// theory have knowledge about all receivers in the set ahead of time,
|
||||
// so this method shouldn't really have to iterate over all of them yet
|
||||
// again. The idea with this "receiver set" interface is to get the
|
||||
// interface right this time around, and later this implementation can
|
||||
// be optimized.
|
||||
//
|
||||
// This implementation can be summarized by:
|
||||
//
|
||||
// fn select(ports) {
|
||||
// if any port ready { return ready index }
|
||||
// fn select(receivers) {
|
||||
// if any receiver ready { return ready index }
|
||||
// deschedule {
|
||||
// block on all ports
|
||||
// block on all receivers
|
||||
// }
|
||||
// unblock on all ports
|
||||
// unblock on all receivers
|
||||
// return ready index
|
||||
// }
|
||||
//
|
||||
// Most notably, the iterations over all of the ports shouldn't be
|
||||
// Most notably, the iterations over all of the receivers shouldn't be
|
||||
// necessary.
|
||||
unsafe {
|
||||
let mut amt = 0;
|
||||
@ -176,7 +177,7 @@ impl Select {
|
||||
|
||||
// Acquire a number of blocking contexts, and block on each one
|
||||
// sequentially until one fails. If one fails, then abort
|
||||
// immediately so we can go unblock on all the other ports.
|
||||
// immediately so we can go unblock on all the other receivers.
|
||||
let task: ~Task = Local::take();
|
||||
task.deschedule(amt, |task| {
|
||||
// Prepare for the block
|
||||
@ -191,18 +192,18 @@ impl Select {
|
||||
}
|
||||
});
|
||||
|
||||
// Abort the selection process on each port. If the abort process
|
||||
// returns `true`, then that means that the port is ready to receive
|
||||
// some data. Note that this also means that the port may have yet
|
||||
// to have fully read the `to_wake` field and woken us up (although
|
||||
// the wakeup is guaranteed to fail).
|
||||
// Abort the selection process on each receiver. If the abort
|
||||
// process returns `true`, then that means that the receiver is
|
||||
// ready to receive some data. Note that this also means that the
|
||||
// receiver may have yet to have fully read the `to_wake` field and
|
||||
// woken us up (although the wakeup is guaranteed to fail).
|
||||
//
|
||||
// This situation happens in the window of where a sender invokes
|
||||
// increment(), sees -1, and then decides to wake up the task. After
|
||||
// all this is done, the sending thread will set `selecting` to
|
||||
// `false`. Until this is done, we cannot return. If we were to
|
||||
// return, then a sender could wake up a port which has gone back to
|
||||
// sleep after this call to `select`.
|
||||
// return, then a sender could wake up a receiver which has gone
|
||||
// back to sleep after this call to `select`.
|
||||
//
|
||||
// Note that it is a "fairly small window" in which an increment()
|
||||
// views that it should wake a thread up until the `selecting` bit
|
||||
@ -226,20 +227,20 @@ impl Select {
|
||||
fn iter(&self) -> Packets { Packets { cur: self.head } }
|
||||
}
|
||||
|
||||
impl<'port, T: Send> Handle<'port, T> {
|
||||
impl<'rx, T: Send> Handle<'rx, T> {
|
||||
/// Retrieve the id of this handle.
|
||||
#[inline]
|
||||
pub fn id(&self) -> uint { self.id }
|
||||
|
||||
/// Receive a value on the underlying port. Has the same semantics as
|
||||
/// `Port.recv`
|
||||
pub fn recv(&mut self) -> T { self.port.recv() }
|
||||
/// Block to receive a value on the underlying port, returning `Some` on
|
||||
/// Receive a value on the underlying receiver. Has the same semantics as
|
||||
/// `Receiver.recv`
|
||||
pub fn recv(&mut self) -> T { self.rx.recv() }
|
||||
/// Block to receive a value on the underlying receiver, returning `Some` on
|
||||
/// success or `None` if the channel disconnects. This function has the same
|
||||
/// semantics as `Port.recv_opt`
|
||||
pub fn recv_opt(&mut self) -> Option<T> { self.port.recv_opt() }
|
||||
/// semantics as `Receiver.recv_opt`
|
||||
pub fn recv_opt(&mut self) -> Option<T> { self.rx.recv_opt() }
|
||||
|
||||
/// Adds this handle to the port set that the handle was created from. This
|
||||
/// Adds this handle to the receiver set that the handle was created from. This
|
||||
/// method can be called multiple times, but it has no effect if `add` was
|
||||
/// called previously.
|
||||
///
|
||||
@ -300,7 +301,7 @@ impl Drop for Select {
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<'port, T: Send> Drop for Handle<'port, T> {
|
||||
impl<'rx, T: Send> Drop for Handle<'rx, T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.remove() }
|
||||
}
|
||||
@ -325,328 +326,328 @@ mod test {
|
||||
use prelude::*;
|
||||
|
||||
test!(fn smoke() {
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, c2) = Chan::<int>::new();
|
||||
c1.send(1);
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (tx2, rx2) = channel::<int>();
|
||||
tx1.send(1);
|
||||
select! (
|
||||
foo = p1.recv() => { assert_eq!(foo, 1); },
|
||||
_bar = p2.recv() => { fail!() }
|
||||
foo = rx1.recv() => { assert_eq!(foo, 1); },
|
||||
_bar = rx2.recv() => { fail!() }
|
||||
)
|
||||
c2.send(2);
|
||||
tx2.send(2);
|
||||
select! (
|
||||
_foo = p1.recv() => { fail!() },
|
||||
bar = p2.recv() => { assert_eq!(bar, 2) }
|
||||
_foo = rx1.recv() => { fail!() },
|
||||
bar = rx2.recv() => { assert_eq!(bar, 2) }
|
||||
)
|
||||
drop(c1);
|
||||
drop(tx1);
|
||||
select! (
|
||||
foo = p1.recv_opt() => { assert_eq!(foo, None); },
|
||||
_bar = p2.recv() => { fail!() }
|
||||
foo = rx1.recv_opt() => { assert_eq!(foo, None); },
|
||||
_bar = rx2.recv() => { fail!() }
|
||||
)
|
||||
drop(c2);
|
||||
drop(tx2);
|
||||
select! (
|
||||
bar = p2.recv_opt() => { assert_eq!(bar, None); }
|
||||
bar = rx2.recv_opt() => { assert_eq!(bar, None); }
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn smoke2() {
|
||||
let (p1, _c1) = Chan::<int>::new();
|
||||
let (p2, _c2) = Chan::<int>::new();
|
||||
let (p3, _c3) = Chan::<int>::new();
|
||||
let (p4, _c4) = Chan::<int>::new();
|
||||
let (p5, c5) = Chan::<int>::new();
|
||||
c5.send(4);
|
||||
let (_tx1, rx1) = channel::<int>();
|
||||
let (_tx2, rx2) = channel::<int>();
|
||||
let (_tx3, rx3) = channel::<int>();
|
||||
let (_tx4, rx4) = channel::<int>();
|
||||
let (tx5, rx5) = channel::<int>();
|
||||
tx5.send(4);
|
||||
select! (
|
||||
_foo = p1.recv() => { fail!("1") },
|
||||
_foo = p2.recv() => { fail!("2") },
|
||||
_foo = p3.recv() => { fail!("3") },
|
||||
_foo = p4.recv() => { fail!("4") },
|
||||
foo = p5.recv() => { assert_eq!(foo, 4); }
|
||||
_foo = rx1.recv() => { fail!("1") },
|
||||
_foo = rx2.recv() => { fail!("2") },
|
||||
_foo = rx3.recv() => { fail!("3") },
|
||||
_foo = rx4.recv() => { fail!("4") },
|
||||
foo = rx5.recv() => { assert_eq!(foo, 4); }
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn closed() {
|
||||
let (p1, _c1) = Chan::<int>::new();
|
||||
let (p2, c2) = Chan::<int>::new();
|
||||
drop(c2);
|
||||
let (_tx1, rx1) = channel::<int>();
|
||||
let (tx2, rx2) = channel::<int>();
|
||||
drop(tx2);
|
||||
|
||||
select! (
|
||||
_a1 = p1.recv_opt() => { fail!() },
|
||||
a2 = p2.recv_opt() => { assert_eq!(a2, None); }
|
||||
_a1 = rx1.recv_opt() => { fail!() },
|
||||
a2 = rx2.recv_opt() => { assert_eq!(a2, None); }
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn unblocks() {
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, _c2) = Chan::<int>::new();
|
||||
let (p3, c3) = Chan::<int>::new();
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (_tx2, rx2) = channel::<int>();
|
||||
let (tx3, rx3) = channel::<int>();
|
||||
|
||||
spawn(proc() {
|
||||
for _ in range(0, 20) { task::deschedule(); }
|
||||
c1.send(1);
|
||||
p3.recv();
|
||||
tx1.send(1);
|
||||
rx3.recv();
|
||||
for _ in range(0, 20) { task::deschedule(); }
|
||||
});
|
||||
|
||||
select! (
|
||||
a = p1.recv() => { assert_eq!(a, 1); },
|
||||
_b = p2.recv() => { fail!() }
|
||||
a = rx1.recv() => { assert_eq!(a, 1); },
|
||||
_b = rx2.recv() => { fail!() }
|
||||
)
|
||||
c3.send(1);
|
||||
tx3.send(1);
|
||||
select! (
|
||||
a = p1.recv_opt() => { assert_eq!(a, None); },
|
||||
_b = p2.recv() => { fail!() }
|
||||
a = rx1.recv_opt() => { assert_eq!(a, None); },
|
||||
_b = rx2.recv() => { fail!() }
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn both_ready() {
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, c2) = Chan::<int>::new();
|
||||
let (p3, c3) = Chan::<()>::new();
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (tx2, rx2) = channel::<int>();
|
||||
let (tx3, rx3) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
for _ in range(0, 20) { task::deschedule(); }
|
||||
c1.send(1);
|
||||
c2.send(2);
|
||||
p3.recv();
|
||||
tx1.send(1);
|
||||
tx2.send(2);
|
||||
rx3.recv();
|
||||
});
|
||||
|
||||
select! (
|
||||
a = p1.recv() => { assert_eq!(a, 1); },
|
||||
a = p2.recv() => { assert_eq!(a, 2); }
|
||||
a = rx1.recv() => { assert_eq!(a, 1); },
|
||||
a = rx2.recv() => { assert_eq!(a, 2); }
|
||||
)
|
||||
select! (
|
||||
a = p1.recv() => { assert_eq!(a, 1); },
|
||||
a = p2.recv() => { assert_eq!(a, 2); }
|
||||
a = rx1.recv() => { assert_eq!(a, 1); },
|
||||
a = rx2.recv() => { assert_eq!(a, 2); }
|
||||
)
|
||||
assert_eq!(p1.try_recv(), Empty);
|
||||
assert_eq!(p2.try_recv(), Empty);
|
||||
c3.send(());
|
||||
assert_eq!(rx1.try_recv(), Empty);
|
||||
assert_eq!(rx2.try_recv(), Empty);
|
||||
tx3.send(());
|
||||
})
|
||||
|
||||
test!(fn stress() {
|
||||
static AMT: int = 10000;
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, c2) = Chan::<int>::new();
|
||||
let (p3, c3) = Chan::<()>::new();
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (tx2, rx2) = channel::<int>();
|
||||
let (tx3, rx3) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
for i in range(0, AMT) {
|
||||
if i % 2 == 0 {
|
||||
c1.send(i);
|
||||
tx1.send(i);
|
||||
} else {
|
||||
c2.send(i);
|
||||
tx2.send(i);
|
||||
}
|
||||
p3.recv();
|
||||
rx3.recv();
|
||||
}
|
||||
});
|
||||
|
||||
for i in range(0, AMT) {
|
||||
select! (
|
||||
i1 = p1.recv() => { assert!(i % 2 == 0 && i == i1); },
|
||||
i2 = p2.recv() => { assert!(i % 2 == 1 && i == i2); }
|
||||
i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1); },
|
||||
i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2); }
|
||||
)
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
}
|
||||
})
|
||||
|
||||
test!(fn cloning() {
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, _c2) = Chan::<int>::new();
|
||||
let (p3, c3) = Chan::<()>::new();
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (_tx2, rx2) = channel::<int>();
|
||||
let (tx3, rx3) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
p3.recv();
|
||||
c1.clone();
|
||||
assert_eq!(p3.try_recv(), Empty);
|
||||
c1.send(2);
|
||||
p3.recv();
|
||||
rx3.recv();
|
||||
tx1.clone();
|
||||
assert_eq!(rx3.try_recv(), Empty);
|
||||
tx1.send(2);
|
||||
rx3.recv();
|
||||
});
|
||||
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
select!(
|
||||
_i1 = p1.recv() => {},
|
||||
_i2 = p2.recv() => fail!()
|
||||
_i1 = rx1.recv() => {},
|
||||
_i2 = rx2.recv() => fail!()
|
||||
)
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
})
|
||||
|
||||
test!(fn cloning2() {
|
||||
let (p1, c1) = Chan::<int>::new();
|
||||
let (p2, _c2) = Chan::<int>::new();
|
||||
let (p3, c3) = Chan::<()>::new();
|
||||
let (tx1, rx1) = channel::<int>();
|
||||
let (_tx2, rx2) = channel::<int>();
|
||||
let (tx3, rx3) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
p3.recv();
|
||||
c1.clone();
|
||||
assert_eq!(p3.try_recv(), Empty);
|
||||
c1.send(2);
|
||||
p3.recv();
|
||||
rx3.recv();
|
||||
tx1.clone();
|
||||
assert_eq!(rx3.try_recv(), Empty);
|
||||
tx1.send(2);
|
||||
rx3.recv();
|
||||
});
|
||||
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
select!(
|
||||
_i1 = p1.recv() => {},
|
||||
_i2 = p2.recv() => fail!()
|
||||
_i1 = rx1.recv() => {},
|
||||
_i2 = rx2.recv() => fail!()
|
||||
)
|
||||
c3.send(());
|
||||
tx3.send(());
|
||||
})
|
||||
|
||||
test!(fn cloning3() {
|
||||
let (p1, c1) = Chan::<()>::new();
|
||||
let (p2, c2) = Chan::<()>::new();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx1, rx1) = channel::<()>();
|
||||
let (tx2, rx2) = channel::<()>();
|
||||
let (tx3, rx3) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let s = Select::new();
|
||||
let mut h1 = s.handle(&p1);
|
||||
let mut h2 = s.handle(&p2);
|
||||
let mut h1 = s.handle(&rx1);
|
||||
let mut h2 = s.handle(&rx2);
|
||||
unsafe { h2.add(); }
|
||||
unsafe { h1.add(); }
|
||||
assert_eq!(s.wait(), h2.id);
|
||||
c.send(());
|
||||
tx3.send(());
|
||||
});
|
||||
|
||||
for _ in range(0, 1000) { task::deschedule(); }
|
||||
drop(c1.clone());
|
||||
c2.send(());
|
||||
p.recv();
|
||||
drop(tx1.clone());
|
||||
tx2.send(());
|
||||
rx3.recv();
|
||||
})
|
||||
|
||||
test!(fn preflight1() {
|
||||
let (p, c) = Chan::new();
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
tx.send(());
|
||||
select!(
|
||||
() = p.recv() => {}
|
||||
() = rx.recv() => {}
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn preflight2() {
|
||||
let (p, c) = Chan::new();
|
||||
c.send(());
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
tx.send(());
|
||||
tx.send(());
|
||||
select!(
|
||||
() = p.recv() => {}
|
||||
() = rx.recv() => {}
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn preflight3() {
|
||||
let (p, c) = Chan::new();
|
||||
drop(c.clone());
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
drop(tx.clone());
|
||||
tx.send(());
|
||||
select!(
|
||||
() = p.recv() => {}
|
||||
() = rx.recv() => {}
|
||||
)
|
||||
})
|
||||
|
||||
test!(fn preflight4() {
|
||||
let (p, c) = Chan::new();
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
tx.send(());
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn preflight5() {
|
||||
let (p, c) = Chan::new();
|
||||
c.send(());
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
tx.send(());
|
||||
tx.send(());
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn preflight6() {
|
||||
let (p, c) = Chan::new();
|
||||
drop(c.clone());
|
||||
c.send(());
|
||||
let (tx, rx) = channel();
|
||||
drop(tx.clone());
|
||||
tx.send(());
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn preflight7() {
|
||||
let (p, c) = Chan::<()>::new();
|
||||
drop(c);
|
||||
let (tx, rx) = channel::<()>();
|
||||
drop(tx);
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn preflight8() {
|
||||
let (p, c) = Chan::new();
|
||||
c.send(());
|
||||
drop(c);
|
||||
p.recv();
|
||||
let (tx, rx) = channel();
|
||||
tx.send(());
|
||||
drop(tx);
|
||||
rx.recv();
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn preflight9() {
|
||||
let (p, c) = Chan::new();
|
||||
drop(c.clone());
|
||||
c.send(());
|
||||
drop(c);
|
||||
p.recv();
|
||||
let (tx, rx) = channel();
|
||||
drop(tx.clone());
|
||||
tx.send(());
|
||||
drop(tx);
|
||||
rx.recv();
|
||||
let s = Select::new();
|
||||
let mut h = s.handle(&p);
|
||||
let mut h = s.handle(&rx);
|
||||
unsafe { h.add(); }
|
||||
assert_eq!(s.wait2(false), h.id);
|
||||
})
|
||||
|
||||
test!(fn oneshot_data_waiting() {
|
||||
let (p, c) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
spawn(proc() {
|
||||
select! {
|
||||
() = p.recv() => {}
|
||||
() = rx1.recv() => {}
|
||||
}
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
for _ in range(0, 100) { task::deschedule() }
|
||||
c.send(());
|
||||
p2.recv();
|
||||
tx1.send(());
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
test!(fn stream_data_waiting() {
|
||||
let (p, c) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
c.send(());
|
||||
c.send(());
|
||||
p.recv();
|
||||
p.recv();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
tx1.send(());
|
||||
tx1.send(());
|
||||
rx1.recv();
|
||||
rx1.recv();
|
||||
spawn(proc() {
|
||||
select! {
|
||||
() = p.recv() => {}
|
||||
() = rx1.recv() => {}
|
||||
}
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
for _ in range(0, 100) { task::deschedule() }
|
||||
c.send(());
|
||||
p2.recv();
|
||||
tx1.send(());
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
test!(fn shared_data_waiting() {
|
||||
let (p, c) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
drop(c.clone());
|
||||
c.send(());
|
||||
p.recv();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
drop(tx1.clone());
|
||||
tx1.send(());
|
||||
rx1.recv();
|
||||
spawn(proc() {
|
||||
select! {
|
||||
() = p.recv() => {}
|
||||
() = rx1.recv() => {}
|
||||
}
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
for _ in range(0, 100) { task::deschedule() }
|
||||
c.send(());
|
||||
p2.recv();
|
||||
tx1.send(());
|
||||
rx2.recv();
|
||||
})
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
/// module.
|
||||
|
||||
use cmp;
|
||||
use comm::Port;
|
||||
use comm::Receiver;
|
||||
use int;
|
||||
use iter::Iterator;
|
||||
use kinds::Send;
|
||||
@ -51,7 +51,7 @@ pub struct Packet<T> {
|
||||
pub enum Failure<T> {
|
||||
Empty,
|
||||
Disconnected,
|
||||
Upgraded(Port<T>),
|
||||
Upgraded(Receiver<T>),
|
||||
}
|
||||
|
||||
pub enum UpgradeResult {
|
||||
@ -63,14 +63,14 @@ pub enum UpgradeResult {
|
||||
pub enum SelectionResult<T> {
|
||||
SelSuccess,
|
||||
SelCanceled(BlockedTask),
|
||||
SelUpgraded(BlockedTask, Port<T>),
|
||||
SelUpgraded(BlockedTask, Receiver<T>),
|
||||
}
|
||||
|
||||
// Any message could contain an "upgrade request" to a new shared port, so the
|
||||
// internal queue it's a queue of T, but rather Message<T>
|
||||
enum Message<T> {
|
||||
Data(T),
|
||||
GoUp(Port<T>),
|
||||
GoUp(Receiver<T>),
|
||||
}
|
||||
|
||||
impl<T: Send> Packet<T> {
|
||||
@ -97,7 +97,7 @@ impl<T: Send> Packet<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn upgrade(&mut self, up: Port<T>) -> UpgradeResult {
|
||||
pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
|
||||
self.do_send(GoUp(up))
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@ impl<T: Send> Packet<T> {
|
||||
// Tests to see whether this port can receive without blocking. If Ok is
|
||||
// returned, then that's the answer. If Err is returned, then the returned
|
||||
// port needs to be queried instead (an upgrade happened)
|
||||
pub fn can_recv(&mut self) -> Result<bool, Port<T>> {
|
||||
pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
|
||||
// We peek at the queue to see if there's anything on it, and we use
|
||||
// this return value to determine if we should pop from the queue and
|
||||
// upgrade this channel immediately. If it looks like we've got an
|
||||
@ -384,7 +384,7 @@ impl<T: Send> Packet<T> {
|
||||
|
||||
// Removes a previous task from being blocked in this port
|
||||
pub fn abort_selection(&mut self,
|
||||
was_upgrade: bool) -> Result<bool, Port<T>> {
|
||||
was_upgrade: bool) -> Result<bool, Receiver<T>> {
|
||||
// If we're aborting selection after upgrading from a oneshot, then
|
||||
// we're guarantee that no one is waiting. The only way that we could
|
||||
// have seen the upgrade is if data was actually sent on the channel
|
||||
|
@ -8,25 +8,26 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use comm::{Port, Chan};
|
||||
use clone::Clone;
|
||||
use cmp;
|
||||
use container::Container;
|
||||
use comm::{Sender, Receiver};
|
||||
use io;
|
||||
use option::{None, Option, Some};
|
||||
use result::{Ok, Err};
|
||||
use super::{Reader, Writer, IoResult};
|
||||
use vec::{bytes, CloneableVector, MutableVector, ImmutableVector};
|
||||
|
||||
/// Allows reading from a port.
|
||||
/// Allows reading from a rx.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::PortReader;
|
||||
/// use std::io::ChanReader;
|
||||
///
|
||||
/// let (port, chan) = Chan::new();
|
||||
/// # drop(chan);
|
||||
/// let mut reader = PortReader::new(port);
|
||||
/// let (tx, rx) = channel();
|
||||
/// # drop(tx);
|
||||
/// let mut reader = ChanReader::new(rx);
|
||||
///
|
||||
/// let mut buf = ~[0u8, ..100];
|
||||
/// match reader.read(buf) {
|
||||
@ -34,26 +35,26 @@ use vec::{bytes, CloneableVector, MutableVector, ImmutableVector};
|
||||
/// Err(e) => println!("read error: {}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub struct PortReader {
|
||||
pub struct ChanReader {
|
||||
priv buf: Option<~[u8]>, // A buffer of bytes received but not consumed.
|
||||
priv pos: uint, // How many of the buffered bytes have already be consumed.
|
||||
priv port: Port<~[u8]>, // The port to pull data from.
|
||||
priv closed: bool, // Whether the pipe this port connects to has been closed.
|
||||
priv rx: Receiver<~[u8]>, // The rx to pull data from.
|
||||
priv closed: bool, // Whether the pipe this rx connects to has been closed.
|
||||
}
|
||||
|
||||
impl PortReader {
|
||||
/// Wraps a `Port` in a `PortReader` structure
|
||||
pub fn new(port: Port<~[u8]>) -> PortReader {
|
||||
PortReader {
|
||||
impl ChanReader {
|
||||
/// Wraps a `Port` in a `ChanReader` structure
|
||||
pub fn new(rx: Receiver<~[u8]>) -> ChanReader {
|
||||
ChanReader {
|
||||
buf: None,
|
||||
pos: 0,
|
||||
port: port,
|
||||
rx: rx,
|
||||
closed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reader for PortReader {
|
||||
impl Reader for ChanReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
let mut num_read = 0;
|
||||
loop {
|
||||
@ -72,7 +73,7 @@ impl Reader for PortReader {
|
||||
break;
|
||||
}
|
||||
self.pos = 0;
|
||||
self.buf = self.port.recv_opt();
|
||||
self.buf = self.rx.recv_opt();
|
||||
self.closed = self.buf.is_none();
|
||||
}
|
||||
if self.closed && num_read == 0 {
|
||||
@ -83,7 +84,7 @@ impl Reader for PortReader {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows writing to a chan.
|
||||
/// Allows writing to a tx.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -91,31 +92,31 @@ impl Reader for PortReader {
|
||||
/// # #[allow(unused_must_use)];
|
||||
/// use std::io::ChanWriter;
|
||||
///
|
||||
/// let (port, chan) = Chan::new();
|
||||
/// # drop(port);
|
||||
/// let mut writer = ChanWriter::new(chan);
|
||||
/// let (tx, rx) = channel();
|
||||
/// # drop(rx);
|
||||
/// let mut writer = ChanWriter::new(tx);
|
||||
/// writer.write("hello, world".as_bytes());
|
||||
/// ```
|
||||
pub struct ChanWriter {
|
||||
priv chan: Chan<~[u8]>,
|
||||
priv tx: Sender<~[u8]>,
|
||||
}
|
||||
|
||||
impl ChanWriter {
|
||||
/// Wraps a channel in a `ChanWriter` structure
|
||||
pub fn new(chan: Chan<~[u8]>) -> ChanWriter {
|
||||
ChanWriter { chan: chan }
|
||||
pub fn new(tx: Sender<~[u8]>) -> ChanWriter {
|
||||
ChanWriter { tx: tx }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ChanWriter {
|
||||
fn clone(&self) -> ChanWriter {
|
||||
ChanWriter { chan: self.chan.clone() }
|
||||
ChanWriter { tx: self.tx.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for ChanWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
if !self.chan.try_send(buf.to_owned()) {
|
||||
if !self.tx.try_send(buf.to_owned()) {
|
||||
Err(io::IoError {
|
||||
kind: io::BrokenPipe,
|
||||
desc: "Pipe closed",
|
||||
@ -136,17 +137,17 @@ mod test {
|
||||
use task;
|
||||
|
||||
#[test]
|
||||
fn test_port_reader() {
|
||||
let (port, chan) = Chan::new();
|
||||
fn test_rx_reader() {
|
||||
let (tx, rx) = channel();
|
||||
task::spawn(proc() {
|
||||
chan.send(~[1u8, 2u8]);
|
||||
chan.send(~[]);
|
||||
chan.send(~[3u8, 4u8]);
|
||||
chan.send(~[5u8, 6u8]);
|
||||
chan.send(~[7u8, 8u8]);
|
||||
tx.send(~[1u8, 2u8]);
|
||||
tx.send(~[]);
|
||||
tx.send(~[3u8, 4u8]);
|
||||
tx.send(~[5u8, 6u8]);
|
||||
tx.send(~[7u8, 8u8]);
|
||||
});
|
||||
|
||||
let mut reader = PortReader::new(port);
|
||||
let mut reader = ChanReader::new(rx);
|
||||
let mut buf = ~[0u8, ..3];
|
||||
|
||||
|
||||
@ -177,12 +178,12 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_chan_writer() {
|
||||
let (port, chan) = Chan::new();
|
||||
let mut writer = ChanWriter::new(chan);
|
||||
let (tx, rx) = channel();
|
||||
let mut writer = ChanWriter::new(tx);
|
||||
writer.write_be_u32(42).unwrap();
|
||||
|
||||
let wanted = ~[0u8, 0u8, 0u8, 42u8];
|
||||
let got = task::try(proc() { port.recv() }).unwrap();
|
||||
let got = task::try(proc() { rx.recv() }).unwrap();
|
||||
assert_eq!(wanted, got);
|
||||
|
||||
match writer.write_u8(1) {
|
||||
|
@ -245,7 +245,7 @@ pub use self::process::{Process, ProcessConfig};
|
||||
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
|
||||
pub use self::buffered::{BufferedReader, BufferedWriter, BufferedStream,
|
||||
LineBufferedWriter};
|
||||
pub use self::comm_adapters::{PortReader, ChanWriter};
|
||||
pub use self::comm_adapters::{ChanReader, ChanWriter};
|
||||
|
||||
pub mod test;
|
||||
|
||||
|
@ -195,16 +195,13 @@ mod test {
|
||||
|
||||
iotest!(fn smoke_test_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
stream.read(buf).unwrap();
|
||||
@ -213,16 +210,13 @@ mod test {
|
||||
|
||||
iotest!(fn smoke_test_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
stream.read(buf).unwrap();
|
||||
@ -231,16 +225,13 @@ mod test {
|
||||
|
||||
iotest!(fn read_eof_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
let nread = stream.read(buf);
|
||||
@ -249,16 +240,13 @@ mod test {
|
||||
|
||||
iotest!(fn read_eof_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
let nread = stream.read(buf);
|
||||
@ -267,16 +255,13 @@ mod test {
|
||||
|
||||
iotest!(fn read_eof_twice_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
let nread = stream.read(buf);
|
||||
@ -293,16 +278,13 @@ mod test {
|
||||
|
||||
iotest!(fn read_eof_twice_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
let nread = stream.read(buf);
|
||||
@ -319,16 +301,13 @@ mod test {
|
||||
|
||||
iotest!(fn write_close_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let buf = [0];
|
||||
loop {
|
||||
@ -347,16 +326,13 @@ mod test {
|
||||
|
||||
iotest!(fn write_close_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut stream = acceptor.accept();
|
||||
let buf = [0];
|
||||
loop {
|
||||
@ -376,18 +352,15 @@ mod test {
|
||||
iotest!(fn multiple_connect_serial_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let max = 10u;
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
for _ in range(0, max) {
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
for ref mut stream in acceptor.incoming().take(max) {
|
||||
let mut buf = [0];
|
||||
stream.read(buf).unwrap();
|
||||
@ -398,18 +371,15 @@ mod test {
|
||||
iotest!(fn multiple_connect_serial_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let max = 10u;
|
||||
let (port, chan) = Chan::new();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
for _ in range(0, max) {
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
for ref mut stream in acceptor.incoming().take(max) {
|
||||
let mut buf = [0];
|
||||
stream.read(buf).unwrap();
|
||||
@ -420,11 +390,10 @@ mod test {
|
||||
iotest!(fn multiple_connect_interleaved_greedy_schedule_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
static MAX: int = 10;
|
||||
let (port, chan) = Chan::new();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut acceptor = acceptor;
|
||||
for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
|
||||
// Start another task to handle the connection
|
||||
spawn(proc() {
|
||||
@ -437,7 +406,6 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
@ -457,11 +425,10 @@ mod test {
|
||||
iotest!(fn multiple_connect_interleaved_greedy_schedule_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
static MAX: int = 10;
|
||||
let (port, chan) = Chan::<()>::new();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut acceptor = acceptor;
|
||||
for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
|
||||
// Start another task to handle the connection
|
||||
spawn(proc() {
|
||||
@ -474,7 +441,6 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
@ -492,13 +458,12 @@ mod test {
|
||||
})
|
||||
|
||||
iotest!(fn multiple_connect_interleaved_lazy_schedule_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
static MAX: int = 10;
|
||||
let (port, chan) = Chan::new();
|
||||
let addr = next_test_ip4();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut acceptor = acceptor;
|
||||
for stream in acceptor.incoming().take(MAX as uint) {
|
||||
// Start another task to handle the connection
|
||||
spawn(proc() {
|
||||
@ -511,7 +476,6 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
@ -529,13 +493,12 @@ mod test {
|
||||
})
|
||||
|
||||
iotest!(fn multiple_connect_interleaved_lazy_schedule_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
static MAX: int = 10;
|
||||
let (port, chan) = Chan::new();
|
||||
let addr = next_test_ip6();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut acceptor = acceptor;
|
||||
for stream in acceptor.incoming().take(MAX as uint) {
|
||||
// Start another task to handle the connection
|
||||
spawn(proc() {
|
||||
@ -548,7 +511,6 @@ mod test {
|
||||
}
|
||||
});
|
||||
|
||||
port.recv();
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
@ -576,15 +538,12 @@ mod test {
|
||||
}
|
||||
|
||||
pub fn peer_name(addr: SocketAddr) {
|
||||
let (port, chan) = Chan::new();
|
||||
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
spawn(proc() {
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
let mut acceptor = acceptor;
|
||||
acceptor.accept().unwrap();
|
||||
});
|
||||
|
||||
port.recv();
|
||||
let stream = TcpStream::connect(addr);
|
||||
|
||||
assert!(stream.is_ok());
|
||||
@ -611,23 +570,23 @@ mod test {
|
||||
|
||||
iotest!(fn partial_read() {
|
||||
let addr = next_test_ip4();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut srv = TcpListener::bind(addr).listen().unwrap();
|
||||
c.send(());
|
||||
tx.send(());
|
||||
let mut cl = srv.accept().unwrap();
|
||||
cl.write([10]).unwrap();
|
||||
let mut b = [0];
|
||||
cl.read(b).unwrap();
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
let mut c = TcpStream::connect(addr).unwrap();
|
||||
let mut b = [0, ..10];
|
||||
assert_eq!(c.read(b), Ok(1));
|
||||
c.write([1]).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
|
||||
iotest!(fn double_bind() {
|
||||
@ -644,22 +603,22 @@ mod test {
|
||||
|
||||
iotest!(fn fast_rebind() {
|
||||
let addr = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
rx.recv();
|
||||
let _stream = TcpStream::connect(addr).unwrap();
|
||||
// Close
|
||||
port.recv();
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
{
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
{
|
||||
let _stream = acceptor.accept().unwrap();
|
||||
// Close client
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
}
|
||||
// Close listener
|
||||
}
|
||||
@ -681,50 +640,50 @@ mod test {
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p1, c1) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
p1.recv();
|
||||
rx1.recv();
|
||||
s2.write([1]).unwrap();
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
c1.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0, 0];
|
||||
assert_eq!(s1.read(buf), Ok(1));
|
||||
p2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn tcp_clone_two_read() {
|
||||
let addr = next_test_ip6();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
let (p, c) = Chan::new();
|
||||
let c2 = c.clone();
|
||||
let (tx1, rx) = channel();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(addr);
|
||||
s.write([1]).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
s.write([2]).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let (done, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
let mut buf = [0, 0];
|
||||
s2.read(buf).unwrap();
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
done.send(());
|
||||
});
|
||||
let mut buf = [0, 0];
|
||||
s1.read(buf).unwrap();
|
||||
c.send(());
|
||||
tx1.send(());
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
|
||||
iotest!(fn tcp_clone_two_write() {
|
||||
@ -741,7 +700,7 @@ mod test {
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let (done, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
s2.write([1]).unwrap();
|
||||
@ -749,7 +708,7 @@ mod test {
|
||||
});
|
||||
s1.write([2]).unwrap();
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -107,23 +107,23 @@ mod test {
|
||||
iotest!(fn socket_smoke_test_ip4() {
|
||||
let server_ip = next_test_ip4();
|
||||
let client_ip = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let (port2, chan2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpSocket::bind(client_ip) {
|
||||
Ok(ref mut client) => {
|
||||
port.recv();
|
||||
rx1.recv();
|
||||
client.sendto([99], server_ip).unwrap()
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
chan2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
match UdpSocket::bind(server_ip) {
|
||||
Ok(ref mut server) => {
|
||||
chan.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0];
|
||||
match server.recvfrom(buf) {
|
||||
Ok((nread, src)) => {
|
||||
@ -136,18 +136,18 @@ mod test {
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
port2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn socket_smoke_test_ip6() {
|
||||
let server_ip = next_test_ip6();
|
||||
let client_ip = next_test_ip6();
|
||||
let (port, chan) = Chan::<()>::new();
|
||||
let (tx, rx) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpSocket::bind(client_ip) {
|
||||
Ok(ref mut client) => {
|
||||
port.recv();
|
||||
rx.recv();
|
||||
client.sendto([99], server_ip).unwrap()
|
||||
}
|
||||
Err(..) => fail!()
|
||||
@ -156,7 +156,7 @@ mod test {
|
||||
|
||||
match UdpSocket::bind(server_ip) {
|
||||
Ok(ref mut server) => {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
let mut buf = [0];
|
||||
match server.recvfrom(buf) {
|
||||
Ok((nread, src)) => {
|
||||
@ -174,27 +174,27 @@ mod test {
|
||||
iotest!(fn stream_smoke_test_ip4() {
|
||||
let server_ip = next_test_ip4();
|
||||
let client_ip = next_test_ip4();
|
||||
let (port, chan) = Chan::new();
|
||||
let (port2, chan2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpSocket::bind(client_ip) {
|
||||
Ok(client) => {
|
||||
let client = ~client;
|
||||
let mut stream = client.connect(server_ip);
|
||||
port.recv();
|
||||
rx1.recv();
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
chan2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
match UdpSocket::bind(server_ip) {
|
||||
Ok(server) => {
|
||||
let server = ~server;
|
||||
let mut stream = server.connect(client_ip);
|
||||
chan.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0];
|
||||
match stream.read(buf) {
|
||||
Ok(nread) => {
|
||||
@ -206,33 +206,33 @@ mod test {
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
port2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn stream_smoke_test_ip6() {
|
||||
let server_ip = next_test_ip6();
|
||||
let client_ip = next_test_ip6();
|
||||
let (port, chan) = Chan::new();
|
||||
let (port2, chan2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
match UdpSocket::bind(client_ip) {
|
||||
Ok(client) => {
|
||||
let client = ~client;
|
||||
let mut stream = client.connect(server_ip);
|
||||
port.recv();
|
||||
rx1.recv();
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
chan2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
match UdpSocket::bind(server_ip) {
|
||||
Ok(server) => {
|
||||
let server = ~server;
|
||||
let mut stream = server.connect(client_ip);
|
||||
chan.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0];
|
||||
match stream.read(buf) {
|
||||
Ok(nread) => {
|
||||
@ -244,7 +244,7 @@ mod test {
|
||||
}
|
||||
Err(..) => fail!()
|
||||
}
|
||||
port2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
pub fn socket_name(addr: SocketAddr) {
|
||||
@ -284,18 +284,18 @@ mod test {
|
||||
|
||||
let sock3 = sock1.clone();
|
||||
|
||||
let (p1, c1) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
spawn(proc() {
|
||||
let mut sock3 = sock3;
|
||||
p1.recv();
|
||||
rx1.recv();
|
||||
sock3.sendto([1], addr2).unwrap();
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
c1.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0, 0];
|
||||
assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
|
||||
p2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn udp_clone_two_read() {
|
||||
@ -303,32 +303,32 @@ mod test {
|
||||
let addr2 = next_test_ip4();
|
||||
let mut sock1 = UdpSocket::bind(addr1).unwrap();
|
||||
let sock2 = UdpSocket::bind(addr2).unwrap();
|
||||
let (p, c) = Chan::new();
|
||||
let c2 = c.clone();
|
||||
let (tx1, rx) = channel();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let mut sock2 = sock2;
|
||||
sock2.sendto([1], addr1).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
sock2.sendto([2], addr1).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
let sock3 = sock1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let (done, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut sock3 = sock3;
|
||||
let mut buf = [0, 0];
|
||||
sock3.recvfrom(buf).unwrap();
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
done.send(());
|
||||
});
|
||||
let mut buf = [0, 0];
|
||||
sock1.recvfrom(buf).unwrap();
|
||||
c.send(());
|
||||
tx1.send(());
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
|
||||
iotest!(fn udp_clone_two_write() {
|
||||
@ -337,40 +337,40 @@ mod test {
|
||||
let mut sock1 = UdpSocket::bind(addr1).unwrap();
|
||||
let sock2 = UdpSocket::bind(addr2).unwrap();
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (serv_port, serv_chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let (serv_tx, serv_rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let mut sock2 = sock2;
|
||||
let mut buf = [0, 1];
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
match sock2.recvfrom(buf) {
|
||||
Ok(..) => {}
|
||||
Err(e) => fail!("failed receive: {}", e),
|
||||
}
|
||||
serv_chan.send(());
|
||||
serv_tx.send(());
|
||||
});
|
||||
|
||||
let sock3 = sock1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let c2 = c.clone();
|
||||
let (done, rx) = channel();
|
||||
let tx2 = tx.clone();
|
||||
spawn(proc() {
|
||||
let mut sock3 = sock3;
|
||||
match sock3.sendto([1], addr2) {
|
||||
Ok(..) => { let _ = c2.try_send(()); }
|
||||
Ok(..) => { let _ = tx2.try_send(()); }
|
||||
Err(..) => {}
|
||||
}
|
||||
done.send(());
|
||||
});
|
||||
match sock1.sendto([2], addr2) {
|
||||
Ok(..) => { let _ = c.try_send(()); }
|
||||
Ok(..) => { let _ = tx.try_send(()); }
|
||||
Err(..) => {}
|
||||
}
|
||||
drop(c);
|
||||
drop(tx);
|
||||
|
||||
p.recv();
|
||||
serv_port.recv();
|
||||
rx.recv();
|
||||
serv_rx.recv();
|
||||
})
|
||||
}
|
||||
|
@ -224,10 +224,13 @@ mod tests {
|
||||
let times = 10;
|
||||
let path1 = next_test_unix();
|
||||
let path2 = path1.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
|
||||
let mut acceptor = match UnixListener::bind(&path1).listen() {
|
||||
Ok(a) => a,
|
||||
Err(e) => fail!("failed listen: {}", e),
|
||||
};
|
||||
|
||||
spawn(proc() {
|
||||
port.recv();
|
||||
for _ in range(0, times) {
|
||||
let mut stream = UnixStream::connect(&path2);
|
||||
match stream.write([100]) {
|
||||
@ -237,11 +240,6 @@ mod tests {
|
||||
}
|
||||
});
|
||||
|
||||
let mut acceptor = match UnixListener::bind(&path1).listen() {
|
||||
Ok(a) => a,
|
||||
Err(e) => fail!("failed listen: {}", e),
|
||||
};
|
||||
chan.send(());
|
||||
for _ in range(0, times) {
|
||||
let mut client = acceptor.accept();
|
||||
let mut buf = [0];
|
||||
@ -278,54 +276,54 @@ mod tests {
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p1, c1) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
p1.recv();
|
||||
rx1.recv();
|
||||
debug!("writer writing");
|
||||
s2.write([1]).unwrap();
|
||||
debug!("writer done");
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
c1.send(());
|
||||
tx1.send(());
|
||||
let mut buf = [0, 0];
|
||||
debug!("reader reading");
|
||||
assert_eq!(s1.read(buf), Ok(1));
|
||||
debug!("reader done");
|
||||
p2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn unix_clone_two_read() {
|
||||
let addr = next_test_unix();
|
||||
let mut acceptor = UnixListener::bind(&addr).listen();
|
||||
let (p, c) = Chan::new();
|
||||
let c2 = c.clone();
|
||||
let (tx1, rx) = channel();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let mut s = UnixStream::connect(&addr);
|
||||
s.write([1]).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
s.write([2]).unwrap();
|
||||
p.recv();
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let (done, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
let mut buf = [0, 0];
|
||||
s2.read(buf).unwrap();
|
||||
c2.send(());
|
||||
tx2.send(());
|
||||
done.send(());
|
||||
});
|
||||
let mut buf = [0, 0];
|
||||
s1.read(buf).unwrap();
|
||||
c.send(());
|
||||
tx1.send(());
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
|
||||
iotest!(fn unix_clone_two_write() {
|
||||
@ -342,14 +340,14 @@ mod tests {
|
||||
let mut s1 = acceptor.accept().unwrap();
|
||||
let s2 = s1.clone();
|
||||
|
||||
let (p, done) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut s2 = s2;
|
||||
s2.write([1]).unwrap();
|
||||
done.send(());
|
||||
tx.send(());
|
||||
});
|
||||
s1.write([2]).unwrap();
|
||||
|
||||
p.recv();
|
||||
rx.recv();
|
||||
})
|
||||
}
|
||||
|
@ -77,15 +77,15 @@ mod test {
|
||||
let os::Pipe { input, out } = os::pipe();
|
||||
let out = PipeStream::open(out);
|
||||
let mut input = PipeStream::open(input);
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut out = out;
|
||||
out.write([10]).unwrap();
|
||||
p.recv(); // don't close the pipe until the other read has finished
|
||||
rx.recv(); // don't close the pipe until the other read has finished
|
||||
});
|
||||
|
||||
let mut buf = [0, ..10];
|
||||
input.read(buf).unwrap();
|
||||
c.send(());
|
||||
tx.send(());
|
||||
})
|
||||
}
|
||||
|
@ -379,16 +379,16 @@ impl Process {
|
||||
/// The stdin handle to the child is closed before waiting.
|
||||
pub fn wait_with_output(&mut self) -> ProcessOutput {
|
||||
drop(self.stdin.take());
|
||||
fn read(stream: Option<io::PipeStream>) -> Port<IoResult<~[u8]>> {
|
||||
let (p, c) = Chan::new();
|
||||
fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<~[u8]>> {
|
||||
let (tx, rx) = channel();
|
||||
match stream {
|
||||
Some(stream) => spawn(proc() {
|
||||
let mut stream = stream;
|
||||
c.send(stream.read_to_end())
|
||||
tx.send(stream.read_to_end())
|
||||
}),
|
||||
None => c.send(Ok(~[]))
|
||||
None => tx.send(Ok(~[]))
|
||||
}
|
||||
p
|
||||
rx
|
||||
}
|
||||
let stdout = read(self.stdout.take());
|
||||
let stderr = read(self.stderr.take());
|
||||
|
@ -20,7 +20,7 @@ definitions for a number of signals.
|
||||
*/
|
||||
|
||||
use clone::Clone;
|
||||
use comm::{Port, Chan};
|
||||
use comm::{Sender, Receiver, channel};
|
||||
use io;
|
||||
use iter::Iterator;
|
||||
use mem::drop;
|
||||
@ -56,7 +56,7 @@ pub enum Signum {
|
||||
WindowSizeChange = 28i,
|
||||
}
|
||||
|
||||
/// Listener provides a port to listen for registered signals.
|
||||
/// Listener provides a receiver to listen for registered signals.
|
||||
///
|
||||
/// Listener automatically unregisters its handles once it is out of scope.
|
||||
/// However, clients can still unregister signums manually.
|
||||
@ -71,7 +71,7 @@ pub enum Signum {
|
||||
///
|
||||
/// spawn({
|
||||
/// loop {
|
||||
/// match listener.port.recv() {
|
||||
/// match listener.rx.recv() {
|
||||
/// Interrupt => println!("Got Interrupt'ed"),
|
||||
/// _ => (),
|
||||
/// }
|
||||
@ -82,24 +82,24 @@ pub enum Signum {
|
||||
pub struct Listener {
|
||||
/// A map from signums to handles to keep the handles in memory
|
||||
priv handles: ~[(Signum, ~RtioSignal)],
|
||||
/// chan is where all the handles send signums, which are received by
|
||||
/// the clients from port.
|
||||
priv chan: Chan<Signum>,
|
||||
/// This is where all the handles send signums, which are received by
|
||||
/// the clients from the receiver.
|
||||
priv tx: Sender<Signum>,
|
||||
|
||||
/// Clients of Listener can `recv()` from this port. This is exposed to
|
||||
/// allow selection over this port as well as manipulation of the port
|
||||
/// Clients of Listener can `recv()` on this receiver. This is exposed to
|
||||
/// allow selection over it as well as manipulation of the receiver
|
||||
/// directly.
|
||||
port: Port<Signum>,
|
||||
rx: Receiver<Signum>,
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
/// Creates a new listener for signals. Once created, signals are bound via
|
||||
/// the `register` method (otherwise nothing will ever be received)
|
||||
pub fn new() -> Listener {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
Listener {
|
||||
chan: chan,
|
||||
port: port,
|
||||
tx: tx,
|
||||
rx: rx,
|
||||
handles: ~[],
|
||||
}
|
||||
}
|
||||
@ -125,7 +125,7 @@ impl Listener {
|
||||
return Ok(()); // self is already listening to signum, so succeed
|
||||
}
|
||||
match LocalIo::maybe_raise(|io| {
|
||||
io.signal(signum, self.chan.clone())
|
||||
io.signal(signum, self.tx.clone())
|
||||
}) {
|
||||
Ok(handle) => {
|
||||
self.handles.push((signum, handle));
|
||||
@ -166,7 +166,7 @@ mod test_unix {
|
||||
signal.register(Interrupt).unwrap();
|
||||
sigint();
|
||||
timer::sleep(10);
|
||||
match signal.port.recv() {
|
||||
match signal.rx.recv() {
|
||||
Interrupt => (),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
@ -180,11 +180,11 @@ mod test_unix {
|
||||
s2.register(Interrupt).unwrap();
|
||||
sigint();
|
||||
timer::sleep(10);
|
||||
match s1.port.recv() {
|
||||
match s1.rx.recv() {
|
||||
Interrupt => (),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
match s2.port.recv() {
|
||||
match s2.rx.recv() {
|
||||
Interrupt => (),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
@ -199,7 +199,7 @@ mod test_unix {
|
||||
s2.unregister(Interrupt);
|
||||
sigint();
|
||||
timer::sleep(10);
|
||||
assert_eq!(s2.port.try_recv(), Empty);
|
||||
assert_eq!(s2.rx.try_recv(), Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,10 +388,10 @@ mod tests {
|
||||
})
|
||||
|
||||
iotest!(fn capture_stdout() {
|
||||
use io::comm_adapters::{PortReader, ChanWriter};
|
||||
use io::{ChanReader, ChanWriter};
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (mut r, w) = (PortReader::new(p), ChanWriter::new(c));
|
||||
let (tx, rx) = channel();
|
||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
||||
spawn(proc() {
|
||||
set_stdout(~w as ~Writer);
|
||||
println!("hello!");
|
||||
@ -400,10 +400,10 @@ mod tests {
|
||||
})
|
||||
|
||||
iotest!(fn capture_stderr() {
|
||||
use io::comm_adapters::{PortReader, ChanWriter};
|
||||
use io::{ChanReader, ChanWriter};
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (mut r, w) = (PortReader::new(p), ChanWriter::new(c));
|
||||
let (tx, rx) = channel();
|
||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
||||
spawn(proc() {
|
||||
set_stderr(~w as ~Writer);
|
||||
fail!("my special message");
|
||||
|
@ -46,9 +46,9 @@ macro_rules! iotest (
|
||||
$($a)* #[test] fn green() { f() }
|
||||
$($a)* #[test] fn native() {
|
||||
use native;
|
||||
let (p, c) = Chan::new();
|
||||
native::task::spawn(proc() { c.send(f()) });
|
||||
p.recv();
|
||||
let (tx, rx) = channel();
|
||||
native::task::spawn(proc() { tx.send(f()) });
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -13,11 +13,11 @@
|
||||
Synchronous Timers
|
||||
|
||||
This module exposes the functionality to create timers, block the current task,
|
||||
and create ports which will receive notifications after a period of time.
|
||||
and create receivers which will receive notifications after a period of time.
|
||||
|
||||
*/
|
||||
|
||||
use comm::Port;
|
||||
use comm::Receiver;
|
||||
use rt::rtio::{IoFactory, LocalIo, RtioTimer};
|
||||
use io::IoResult;
|
||||
|
||||
@ -25,7 +25,7 @@ use io::IoResult;
|
||||
///
|
||||
/// Values of this type can be used to put the current task to sleep for a
|
||||
/// period of time. Handles to this timer can also be created in the form of
|
||||
/// ports which will receive notifications over time.
|
||||
/// receivers which will receive notifications over time.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -83,33 +83,33 @@ impl Timer {
|
||||
|
||||
/// Blocks the current task for `msecs` milliseconds.
|
||||
///
|
||||
/// Note that this function will cause any other ports for this timer to be
|
||||
/// invalidated (the other end will be closed).
|
||||
/// Note that this function will cause any other receivers for this timer to
|
||||
/// be invalidated (the other end will be closed).
|
||||
pub fn sleep(&mut self, msecs: u64) {
|
||||
self.obj.sleep(msecs);
|
||||
}
|
||||
|
||||
/// Creates a oneshot port which will have a notification sent when `msecs`
|
||||
/// milliseconds has elapsed. This does *not* block the current task, but
|
||||
/// instead returns immediately.
|
||||
/// Creates a oneshot receiver which will have a notification sent when
|
||||
/// `msecs` milliseconds has elapsed. This does *not* block the current
|
||||
/// task, but instead returns immediately.
|
||||
///
|
||||
/// Note that this invalidates any previous port which has been created by
|
||||
/// this timer, and that the returned port will be invalidated once the
|
||||
/// timer is destroyed (when it falls out of scope).
|
||||
pub fn oneshot(&mut self, msecs: u64) -> Port<()> {
|
||||
/// Note that this invalidates any previous receiver which has been created
|
||||
/// by this timer, and that the returned receiver will be invalidated once
|
||||
/// the timer is destroyed (when it falls out of scope).
|
||||
pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
self.obj.oneshot(msecs)
|
||||
}
|
||||
|
||||
/// Creates a port which will have a continuous stream of notifications
|
||||
/// Creates a receiver which will have a continuous stream of notifications
|
||||
/// being sent every `msecs` milliseconds. This does *not* block the
|
||||
/// current task, but instead returns immediately. The first notification
|
||||
/// will not be received immediately, but rather after `msec` milliseconds
|
||||
/// have passed.
|
||||
///
|
||||
/// Note that this invalidates any previous port which has been created by
|
||||
/// this timer, and that the returned port will be invalidated once the
|
||||
/// timer is destroyed (when it falls out of scope).
|
||||
pub fn periodic(&mut self, msecs: u64) -> Port<()> {
|
||||
/// Note that this invalidates any previous receiver which has been created
|
||||
/// by this timer, and that the returned receiver will be invalidated once
|
||||
/// the timer is destroyed (when it falls out of scope).
|
||||
pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
|
||||
self.obj.period(msecs)
|
||||
}
|
||||
}
|
||||
@ -133,26 +133,26 @@ mod test {
|
||||
|
||||
iotest!(fn oneshot_twice() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let port1 = timer.oneshot(10000);
|
||||
let port = timer.oneshot(1);
|
||||
port.recv();
|
||||
assert_eq!(port1.recv_opt(), None);
|
||||
let rx1 = timer.oneshot(10000);
|
||||
let rx = timer.oneshot(1);
|
||||
rx.recv();
|
||||
assert_eq!(rx1.recv_opt(), None);
|
||||
})
|
||||
|
||||
iotest!(fn test_io_timer_oneshot_then_sleep() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let port = timer.oneshot(100000000000);
|
||||
timer.sleep(1); // this should invalidate the port
|
||||
let rx = timer.oneshot(100000000000);
|
||||
timer.sleep(1); // this should inalidate rx
|
||||
|
||||
assert_eq!(port.recv_opt(), None);
|
||||
assert_eq!(rx.recv_opt(), None);
|
||||
})
|
||||
|
||||
iotest!(fn test_io_timer_sleep_periodic() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let port = timer.periodic(1);
|
||||
port.recv();
|
||||
port.recv();
|
||||
port.recv();
|
||||
let rx = timer.periodic(1);
|
||||
rx.recv();
|
||||
rx.recv();
|
||||
rx.recv();
|
||||
})
|
||||
|
||||
iotest!(fn test_io_timer_sleep_periodic_forget() {
|
||||
@ -167,33 +167,33 @@ mod test {
|
||||
iotest!(fn oneshot() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
|
||||
let port = timer.oneshot(1);
|
||||
port.recv();
|
||||
assert!(port.recv_opt().is_none());
|
||||
let rx = timer.oneshot(1);
|
||||
rx.recv();
|
||||
assert!(rx.recv_opt().is_none());
|
||||
|
||||
let port = timer.oneshot(1);
|
||||
port.recv();
|
||||
assert!(port.recv_opt().is_none());
|
||||
let rx = timer.oneshot(1);
|
||||
rx.recv();
|
||||
assert!(rx.recv_opt().is_none());
|
||||
})
|
||||
|
||||
iotest!(fn override() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let oport = timer.oneshot(100);
|
||||
let pport = timer.periodic(100);
|
||||
let orx = timer.oneshot(100);
|
||||
let prx = timer.periodic(100);
|
||||
timer.sleep(1);
|
||||
assert_eq!(oport.recv_opt(), None);
|
||||
assert_eq!(pport.recv_opt(), None);
|
||||
assert_eq!(orx.recv_opt(), None);
|
||||
assert_eq!(prx.recv_opt(), None);
|
||||
timer.oneshot(1).recv();
|
||||
})
|
||||
|
||||
iotest!(fn period() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let port = timer.periodic(1);
|
||||
port.recv();
|
||||
port.recv();
|
||||
let port2 = timer.periodic(1);
|
||||
port2.recv();
|
||||
port2.recv();
|
||||
let rx = timer.periodic(1);
|
||||
rx.recv();
|
||||
rx.recv();
|
||||
let rx2 = timer.periodic(1);
|
||||
rx2.recv();
|
||||
rx2.recv();
|
||||
})
|
||||
|
||||
iotest!(fn sleep() {
|
||||
@ -204,13 +204,13 @@ mod test {
|
||||
|
||||
iotest!(fn oneshot_fail() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let _port = timer.oneshot(1);
|
||||
let _rx = timer.oneshot(1);
|
||||
fail!();
|
||||
} #[should_fail])
|
||||
|
||||
iotest!(fn period_fail() {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let _port = timer.periodic(1);
|
||||
let _rx = timer.periodic(1);
|
||||
fail!();
|
||||
} #[should_fail])
|
||||
|
||||
@ -222,10 +222,10 @@ mod test {
|
||||
iotest!(fn closing_channel_during_drop_doesnt_kill_everything() {
|
||||
// see issue #10375
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let timer_port = timer.periodic(1000);
|
||||
let timer_rx = timer.periodic(1000);
|
||||
|
||||
spawn(proc() {
|
||||
timer_port.recv_opt();
|
||||
timer_rx.recv_opt();
|
||||
});
|
||||
|
||||
// when we drop the TimerWatcher we're going to destroy the channel,
|
||||
@ -235,10 +235,10 @@ mod test {
|
||||
iotest!(fn reset_doesnt_switch_tasks() {
|
||||
// similar test to the one above.
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let timer_port = timer.periodic(1000);
|
||||
let timer_rx = timer.periodic(1000);
|
||||
|
||||
spawn(proc() {
|
||||
timer_port.recv_opt();
|
||||
timer_rx.recv_opt();
|
||||
});
|
||||
|
||||
timer.oneshot(1);
|
||||
@ -247,29 +247,29 @@ mod test {
|
||||
iotest!(fn reset_doesnt_switch_tasks2() {
|
||||
// similar test to the one above.
|
||||
let mut timer = Timer::new().unwrap();
|
||||
let timer_port = timer.periodic(1000);
|
||||
let timer_rx = timer.periodic(1000);
|
||||
|
||||
spawn(proc() {
|
||||
timer_port.recv_opt();
|
||||
timer_rx.recv_opt();
|
||||
});
|
||||
|
||||
timer.sleep(1);
|
||||
})
|
||||
|
||||
iotest!(fn sender_goes_away_oneshot() {
|
||||
let port = {
|
||||
let rx = {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
timer.oneshot(1000)
|
||||
};
|
||||
assert_eq!(port.recv_opt(), None);
|
||||
assert_eq!(rx.recv_opt(), None);
|
||||
})
|
||||
|
||||
iotest!(fn sender_goes_away_period() {
|
||||
let port = {
|
||||
let rx = {
|
||||
let mut timer = Timer::new().unwrap();
|
||||
timer.periodic(1000)
|
||||
};
|
||||
assert_eq!(port.recv_opt(), None);
|
||||
assert_eq!(rx.recv_opt(), None);
|
||||
})
|
||||
|
||||
iotest!(fn receiver_goes_away_oneshot() {
|
||||
|
@ -387,17 +387,17 @@ macro_rules! vec(
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let (p1, c1) = Chan::new();
|
||||
/// let (p2, c2) = Chan::new();
|
||||
/// let (tx1, rx1) = channel();
|
||||
/// let (tx2, rx2) = channel();
|
||||
/// # fn long_running_task() {}
|
||||
/// # fn calculate_the_answer() -> int { 42 }
|
||||
///
|
||||
/// spawn(proc() { long_running_task(); c1.send(()) });
|
||||
/// spawn(proc() { c2.send(calculate_the_answer()) });
|
||||
/// spawn(proc() { long_running_task(); tx1.send(()) });
|
||||
/// spawn(proc() { tx2.send(calculate_the_answer()) });
|
||||
///
|
||||
/// select! (
|
||||
/// () = p1.recv() => println!("the long running task finished first"),
|
||||
/// answer = p2.recv() => {
|
||||
/// () = rx1.recv() => println!("the long running task finished first"),
|
||||
/// answer = rx2.recv() => {
|
||||
/// println!("the answer was: {}", answer);
|
||||
/// }
|
||||
/// )
|
||||
@ -408,16 +408,16 @@ macro_rules! vec(
|
||||
#[experimental]
|
||||
macro_rules! select {
|
||||
(
|
||||
$($name:pat = $port:ident.$meth:ident() => $code:expr),+
|
||||
$($name:pat = $rx:ident.$meth:ident() => $code:expr),+
|
||||
) => ({
|
||||
use std::comm::Select;
|
||||
let sel = Select::new();
|
||||
$( let mut $port = sel.handle(&$port); )+
|
||||
$( let mut $rx = sel.handle(&$rx); )+
|
||||
unsafe {
|
||||
$( $port.add(); )+
|
||||
$( $rx.add(); )+
|
||||
}
|
||||
let ret = sel.wait();
|
||||
$( if ret == $port.id() { let $name = $port.$meth(); $code } else )+
|
||||
$( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
|
||||
{ unreachable!() }
|
||||
})
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ pub use vec::{MutableVector, MutableTotalOrdVector};
|
||||
pub use vec::{Vector, VectorVector, CloneableVector, ImmutableVector};
|
||||
|
||||
// Reexported runtime types
|
||||
pub use comm::{Port, Chan};
|
||||
pub use comm::{channel, Sender, Receiver};
|
||||
pub use task::spawn;
|
||||
|
||||
// Reexported statics
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use c_str::CString;
|
||||
use cast;
|
||||
use comm::{Chan, Port};
|
||||
use comm::{Sender, Receiver};
|
||||
use libc::c_int;
|
||||
use libc;
|
||||
use ops::Drop;
|
||||
@ -183,7 +183,7 @@ pub trait IoFactory {
|
||||
fn pipe_open(&mut self, fd: c_int) -> Result<~RtioPipe, IoError>;
|
||||
fn tty_open(&mut self, fd: c_int, readable: bool)
|
||||
-> Result<~RtioTTY, IoError>;
|
||||
fn signal(&mut self, signal: Signum, channel: Chan<Signum>)
|
||||
fn signal(&mut self, signal: Signum, channel: Sender<Signum>)
|
||||
-> Result<~RtioSignal, IoError>;
|
||||
}
|
||||
|
||||
@ -233,8 +233,8 @@ pub trait RtioUdpSocket : RtioSocket {
|
||||
|
||||
pub trait RtioTimer {
|
||||
fn sleep(&mut self, msecs: u64);
|
||||
fn oneshot(&mut self, msecs: u64) -> Port<()>;
|
||||
fn period(&mut self, msecs: u64) -> Port<()>;
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()>;
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()>;
|
||||
}
|
||||
|
||||
pub trait RtioFileStream {
|
||||
|
@ -17,7 +17,7 @@ use any::AnyOwnExt;
|
||||
use cast;
|
||||
use cleanup;
|
||||
use clone::Clone;
|
||||
use comm::Chan;
|
||||
use comm::Sender;
|
||||
use io::Writer;
|
||||
use iter::{Iterator, Take};
|
||||
use local_data;
|
||||
@ -73,7 +73,7 @@ pub enum DeathAction {
|
||||
/// until all its watched children exit before collecting the status.
|
||||
Execute(proc(TaskResult)),
|
||||
/// A channel to send the result of the task on when the task exits
|
||||
SendMessage(Chan<TaskResult>),
|
||||
SendMessage(Sender<TaskResult>),
|
||||
}
|
||||
|
||||
/// Per-task state related to task death, killing, failure, etc.
|
||||
@ -450,16 +450,16 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn comm_stream() {
|
||||
let (port, chan) = Chan::new();
|
||||
chan.send(10);
|
||||
assert!(port.recv() == 10);
|
||||
let (tx, rx) = channel();
|
||||
tx.send(10);
|
||||
assert!(rx.recv() == 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comm_shared_chan() {
|
||||
let (port, chan) = Chan::new();
|
||||
chan.send(10);
|
||||
assert!(port.recv() == 10);
|
||||
let (tx, rx) = channel();
|
||||
tx.send(10);
|
||||
assert!(rx.recv() == 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -172,24 +172,24 @@ mod tests {
|
||||
let nmsgs = 1000u;
|
||||
let mut q = Queue::with_capacity(nthreads*nmsgs);
|
||||
assert_eq!(None, q.pop());
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
for _ in range(0, nthreads) {
|
||||
let q = q.clone();
|
||||
let chan = chan.clone();
|
||||
let tx = tx.clone();
|
||||
native::task::spawn(proc() {
|
||||
let mut q = q;
|
||||
for i in range(0, nmsgs) {
|
||||
assert!(q.push(i));
|
||||
}
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
}
|
||||
|
||||
let mut completion_ports = ~[];
|
||||
let mut completion_rxs = ~[];
|
||||
for _ in range(0, nthreads) {
|
||||
let (completion_port, completion_chan) = Chan::new();
|
||||
completion_ports.push(completion_port);
|
||||
let (tx, rx) = channel();
|
||||
completion_rxs.push(rx);
|
||||
let q = q.clone();
|
||||
native::task::spawn(proc() {
|
||||
let mut q = q;
|
||||
@ -203,15 +203,15 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
completion_chan.send(i);
|
||||
tx.send(i);
|
||||
});
|
||||
}
|
||||
|
||||
for completion_port in completion_ports.mut_iter() {
|
||||
assert_eq!(nmsgs, completion_port.recv());
|
||||
for rx in completion_rxs.mut_iter() {
|
||||
assert_eq!(nmsgs, rx.recv());
|
||||
}
|
||||
for _ in range(0, nthreads) {
|
||||
port.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,17 +176,17 @@ mod tests {
|
||||
Empty => {}
|
||||
Inconsistent | Data(..) => fail!()
|
||||
}
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let q = UnsafeArc::new(q);
|
||||
|
||||
for _ in range(0, nthreads) {
|
||||
let chan = chan.clone();
|
||||
let tx = tx.clone();
|
||||
let q = q.clone();
|
||||
native::task::spawn(proc() {
|
||||
for i in range(0, nmsgs) {
|
||||
unsafe { (*q.get()).push(i); }
|
||||
}
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
}
|
||||
|
||||
@ -197,9 +197,9 @@ mod tests {
|
||||
Data(_) => { i += 1 }
|
||||
}
|
||||
}
|
||||
drop(chan);
|
||||
drop(tx);
|
||||
for _ in range(0, nthreads) {
|
||||
port.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ mod test {
|
||||
|
||||
fn stress_bound(bound: uint) {
|
||||
let (a, b) = UnsafeArc::new2(Queue::new(bound));
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
native::task::spawn(proc() {
|
||||
for _ in range(0, 100000) {
|
||||
loop {
|
||||
@ -284,12 +284,12 @@ mod test {
|
||||
}
|
||||
}
|
||||
}
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
for _ in range(0, 100000) {
|
||||
unsafe { (*a.get()).push(1); }
|
||||
}
|
||||
port.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,26 +11,25 @@
|
||||
/*!
|
||||
* Utilities for managing and scheduling tasks
|
||||
*
|
||||
* An executing Rust program consists of a tree of tasks, each with their own
|
||||
* stack, and sole ownership of their allocated heap data. Tasks communicate
|
||||
* with each other using ports and channels (see std::comm for more info
|
||||
* about how communication works).
|
||||
* An executing Rust program consists of a collection of tasks, each with their
|
||||
* own stack, and sole ownership of their allocated heap data. Tasks communicate
|
||||
* with each other using channels (see `std::comm` for more info about how
|
||||
* communication works).
|
||||
*
|
||||
* Failure in one task does not propagate to any others (not to parent, not to child).
|
||||
* Failure propagation is instead handled by using Chan.send() and Port.recv(), which
|
||||
* will fail if the other end has hung up already.
|
||||
* Failure in one task does not propagate to any others (not to parent, not to
|
||||
* child). Failure propagation is instead handled by using the channel send()
|
||||
* and recv() methods which will fail if the other end has hung up already.
|
||||
*
|
||||
* Task Scheduling:
|
||||
*
|
||||
* By default, every task is created in the same scheduler as its parent, where it
|
||||
* is scheduled cooperatively with all other tasks in that scheduler. Some specialized
|
||||
* applications may want more control over their scheduling, in which case they can be
|
||||
* spawned into a new scheduler with the specific properties required. See TaskBuilder's
|
||||
* documentation bellow for more information.
|
||||
* By default, every task is created with the same "flavor" as the calling task.
|
||||
* This flavor refers to the scheduling mode, with two possibilities currently
|
||||
* being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and
|
||||
* native (1:1) tasks are scheduled by the OS kernel.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ```
|
||||
* ```rust
|
||||
* spawn(proc() {
|
||||
* println!("Hello, World!");
|
||||
* })
|
||||
@ -38,7 +37,7 @@
|
||||
*/
|
||||
|
||||
use any::Any;
|
||||
use comm::{Chan, Port};
|
||||
use comm::{Sender, Receiver, channel};
|
||||
use io::Writer;
|
||||
use kinds::{Send, marker};
|
||||
use logging::Logger;
|
||||
@ -62,7 +61,7 @@ pub type TaskResult = Result<(), ~Any>;
|
||||
/// Task configuration options
|
||||
pub struct TaskOpts {
|
||||
/// Enable lifecycle notifications on the given channel
|
||||
notify_chan: Option<Chan<TaskResult>>,
|
||||
notify_chan: Option<Sender<TaskResult>>,
|
||||
/// A name for the task-to-be, for identification in failure messages
|
||||
name: Option<SendStr>,
|
||||
/// The size of the stack for the spawned task
|
||||
@ -116,7 +115,7 @@ impl TaskBuilder {
|
||||
///
|
||||
/// # Failure
|
||||
/// Fails if a future_result was already set for this task.
|
||||
pub fn future_result(&mut self) -> Port<TaskResult> {
|
||||
pub fn future_result(&mut self) -> Receiver<TaskResult> {
|
||||
// FIXME (#3725): Once linked failure and notification are
|
||||
// handled in the library, I can imagine implementing this by just
|
||||
// registering an arbitrary number of task::on_exit handlers and
|
||||
@ -127,12 +126,12 @@ impl TaskBuilder {
|
||||
}
|
||||
|
||||
// Construct the future and give it to the caller.
|
||||
let (notify_pipe_po, notify_pipe_ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// Reconfigure self to use a notify channel.
|
||||
self.opts.notify_chan = Some(notify_pipe_ch);
|
||||
self.opts.notify_chan = Some(tx);
|
||||
|
||||
notify_pipe_po
|
||||
rx
|
||||
}
|
||||
|
||||
/// Name the task-to-be. Currently the name is used for identification
|
||||
@ -204,16 +203,16 @@ impl TaskBuilder {
|
||||
* Fails if a future_result was already set for this task.
|
||||
*/
|
||||
pub fn try<T:Send>(mut self, f: proc() -> T) -> Result<T, ~Any> {
|
||||
let (po, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let result = self.future_result();
|
||||
|
||||
self.spawn(proc() {
|
||||
ch.send(f());
|
||||
tx.send(f());
|
||||
});
|
||||
|
||||
match result.recv() {
|
||||
Ok(()) => Ok(po.recv()),
|
||||
Ok(()) => Ok(rx.recv()),
|
||||
Err(cause) => Err(cause)
|
||||
}
|
||||
}
|
||||
@ -340,25 +339,24 @@ fn test_send_named_task() {
|
||||
|
||||
#[test]
|
||||
fn test_run_basic() {
|
||||
let (po, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
task().spawn(proc() {
|
||||
ch.send(());
|
||||
tx.send(());
|
||||
});
|
||||
po.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_wrapper() {
|
||||
let (po, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
task().with_wrapper(proc(body) {
|
||||
let ch = ch;
|
||||
let result: proc() = proc() {
|
||||
body();
|
||||
ch.send(());
|
||||
tx.send(());
|
||||
};
|
||||
result
|
||||
}).spawn(proc() { });
|
||||
po.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -407,50 +405,49 @@ fn test_try_fail() {
|
||||
fn test_spawn_sched() {
|
||||
use clone::Clone;
|
||||
|
||||
let (po, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
fn f(i: int, ch: Chan<()>) {
|
||||
let ch = ch.clone();
|
||||
fn f(i: int, tx: Sender<()>) {
|
||||
let tx = tx.clone();
|
||||
spawn(proc() {
|
||||
if i == 0 {
|
||||
ch.send(());
|
||||
tx.send(());
|
||||
} else {
|
||||
f(i - 1, ch);
|
||||
f(i - 1, tx);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
f(10, ch);
|
||||
po.recv();
|
||||
f(10, tx);
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spawn_sched_childs_on_default_sched() {
|
||||
let (po, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let ch = ch;
|
||||
spawn(proc() {
|
||||
ch.send(());
|
||||
tx.send(());
|
||||
});
|
||||
});
|
||||
|
||||
po.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn avoid_copying_the_body(spawnfn: |v: proc()|) {
|
||||
let (p, ch) = Chan::<uint>::new();
|
||||
let (tx, rx) = channel::<uint>();
|
||||
|
||||
let x = ~1;
|
||||
let x_in_parent = (&*x) as *int as uint;
|
||||
|
||||
spawnfn(proc() {
|
||||
let x_in_child = (&*x) as *int as uint;
|
||||
ch.send(x_in_child);
|
||||
tx.send(x_in_child);
|
||||
});
|
||||
|
||||
let x_in_child = p.recv();
|
||||
let x_in_child = rx.recv();
|
||||
assert_eq!(x_in_parent, x_in_child);
|
||||
}
|
||||
|
||||
|
@ -124,14 +124,14 @@ mod tests {
|
||||
|
||||
for _ in range(0u, num_tasks) {
|
||||
let total = total.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
futures.push(port);
|
||||
let (tx, rx) = channel();
|
||||
futures.push(rx);
|
||||
|
||||
task::spawn(proc() {
|
||||
for _ in range(0u, count) {
|
||||
total.with(|count| **count += 1);
|
||||
}
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -20,19 +20,20 @@
|
||||
* ```rust
|
||||
* extern crate sync;
|
||||
* extern crate rand;
|
||||
* use sync::Arc;
|
||||
*
|
||||
* use std::vec;
|
||||
* use sync::Arc;
|
||||
*
|
||||
* fn main() {
|
||||
* let numbers = vec::from_fn(100, |i| (i as f32) * rand::random());
|
||||
* let shared_numbers = Arc::new(numbers);
|
||||
*
|
||||
* for _ in range(0, 10) {
|
||||
* let (port, chan) = Chan::new();
|
||||
* chan.send(shared_numbers.clone());
|
||||
* let (tx, rx) = channel();
|
||||
* tx.send(shared_numbers.clone());
|
||||
*
|
||||
* spawn(proc() {
|
||||
* let shared_numbers = port.recv();
|
||||
* let shared_numbers = rx.recv();
|
||||
* let local_numbers = shared_numbers.get();
|
||||
*
|
||||
* // Work with the local numbers
|
||||
@ -582,16 +583,16 @@ mod tests {
|
||||
let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let arc_v = Arc::new(v);
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
task::spawn(proc() {
|
||||
let arc_v: Arc<~[int]> = p.recv();
|
||||
let arc_v: Arc<~[int]> = rx.recv();
|
||||
|
||||
let v = arc_v.get().clone();
|
||||
assert_eq!(v[3], 4);
|
||||
});
|
||||
|
||||
c.send(arc_v.clone());
|
||||
tx.send(arc_v.clone());
|
||||
|
||||
assert_eq!(arc_v.get()[2], 3);
|
||||
assert_eq!(arc_v.get()[4], 5);
|
||||
@ -603,10 +604,10 @@ mod tests {
|
||||
fn test_mutex_arc_condvar() {
|
||||
let arc = ~MutexArc::new(false);
|
||||
let arc2 = ~arc.clone();
|
||||
let (p,c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
task::spawn(proc() {
|
||||
// wait until parent gets in
|
||||
p.recv();
|
||||
rx.recv();
|
||||
arc2.access_cond(|state, cond| {
|
||||
*state = true;
|
||||
cond.signal();
|
||||
@ -614,7 +615,7 @@ mod tests {
|
||||
});
|
||||
|
||||
arc.access_cond(|state, cond| {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
assert!(!*state);
|
||||
while !*state {
|
||||
cond.wait();
|
||||
@ -626,10 +627,10 @@ mod tests {
|
||||
fn test_arc_condvar_poison() {
|
||||
let arc = ~MutexArc::new(1);
|
||||
let arc2 = ~arc.clone();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let _ = p.recv();
|
||||
let _ = rx.recv();
|
||||
arc2.access_cond(|one, cond| {
|
||||
cond.signal();
|
||||
// Parent should fail when it wakes up.
|
||||
@ -638,7 +639,7 @@ mod tests {
|
||||
});
|
||||
|
||||
arc.access_cond(|one, cond| {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
while *one == 1 {
|
||||
cond.wait();
|
||||
}
|
||||
@ -781,7 +782,7 @@ mod tests {
|
||||
fn test_rw_arc() {
|
||||
let arc = RWArc::new(0);
|
||||
let arc2 = arc.clone();
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
task::spawn(proc() {
|
||||
arc2.write(|num| {
|
||||
@ -791,7 +792,7 @@ mod tests {
|
||||
task::deschedule();
|
||||
*num = tmp + 1;
|
||||
}
|
||||
c.send(());
|
||||
tx.send(());
|
||||
})
|
||||
});
|
||||
|
||||
@ -814,7 +815,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Wait for writer to finish
|
||||
p.recv();
|
||||
rx.recv();
|
||||
arc.read(|num| {
|
||||
assert_eq!(*num, 10);
|
||||
})
|
||||
@ -852,42 +853,42 @@ mod tests {
|
||||
// Reader tasks
|
||||
let mut reader_convos = ~[];
|
||||
for _ in range(0, 10) {
|
||||
let ((rp1, rc1), (rp2, rc2)) = (Chan::new(), Chan::new());
|
||||
reader_convos.push((rc1, rp2));
|
||||
let ((tx1, rx1), (tx2, rx2)) = (channel(), channel());
|
||||
reader_convos.push((tx1, rx2));
|
||||
let arcn = arc.clone();
|
||||
task::spawn(proc() {
|
||||
rp1.recv(); // wait for downgrader to give go-ahead
|
||||
rx1.recv(); // wait for downgrader to give go-ahead
|
||||
arcn.read(|state| {
|
||||
assert_eq!(*state, 31337);
|
||||
rc2.send(());
|
||||
tx2.send(());
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Writer task
|
||||
let arc2 = arc.clone();
|
||||
let ((wp1, wc1), (wp2, wc2)) = (Chan::new(), Chan::new());
|
||||
let ((tx1, rx1), (tx2, rx2)) = (channel(), channel());
|
||||
task::spawn(proc() {
|
||||
wp1.recv();
|
||||
rx1.recv();
|
||||
arc2.write_cond(|state, cond| {
|
||||
assert_eq!(*state, 0);
|
||||
*state = 42;
|
||||
cond.signal();
|
||||
});
|
||||
wp1.recv();
|
||||
rx1.recv();
|
||||
arc2.write(|state| {
|
||||
// This shouldn't happen until after the downgrade read
|
||||
// section, and all other readers, finish.
|
||||
assert_eq!(*state, 31337);
|
||||
*state = 42;
|
||||
});
|
||||
wc2.send(());
|
||||
tx2.send(());
|
||||
});
|
||||
|
||||
// Downgrader (us)
|
||||
arc.write_downgrade(|mut write_mode| {
|
||||
write_mode.write_cond(|state, cond| {
|
||||
wc1.send(()); // send to another writer who will wake us up
|
||||
tx1.send(()); // send to another writer who will wake us up
|
||||
while *state == 0 {
|
||||
cond.wait();
|
||||
}
|
||||
@ -904,12 +905,12 @@ mod tests {
|
||||
for &(_, ref mut rp) in reader_convos.mut_iter() {
|
||||
rp.recv()
|
||||
}
|
||||
wc1.send(()); // tell writer to try again
|
||||
tx1.send(()); // tell writer to try again
|
||||
assert_eq!(*state, 31337);
|
||||
});
|
||||
});
|
||||
|
||||
wp2.recv(); // complete handshake with writer
|
||||
rx2.recv(); // complete handshake with writer
|
||||
}
|
||||
#[cfg(test)]
|
||||
fn test_rw_write_cond_downgrade_read_race_helper() {
|
||||
@ -923,13 +924,13 @@ mod tests {
|
||||
// "blk(&ArcCondvar { order: opt_lock, ..*cond })"
|
||||
// with just "blk(cond)".
|
||||
let x = RWArc::new(true);
|
||||
let (wp, wc) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// writer task
|
||||
let xw = x.clone();
|
||||
task::spawn(proc() {
|
||||
xw.write_cond(|state, c| {
|
||||
wc.send(()); // tell downgrader it's ok to go
|
||||
tx.send(()); // tell downgrader it's ok to go
|
||||
c.wait();
|
||||
// The core of the test is here: the condvar reacquire path
|
||||
// must involve order_lock, so that it cannot race with a reader
|
||||
@ -938,7 +939,7 @@ mod tests {
|
||||
})
|
||||
});
|
||||
|
||||
wp.recv(); // wait for writer to get in
|
||||
rx.recv(); // wait for writer to get in
|
||||
|
||||
x.write_downgrade(|mut write_mode| {
|
||||
write_mode.write_cond(|state, c| {
|
||||
@ -948,12 +949,12 @@ mod tests {
|
||||
});
|
||||
// make a reader task to trigger the "reader cloud lock" handoff
|
||||
let xr = x.clone();
|
||||
let (rp, rc) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
task::spawn(proc() {
|
||||
rc.send(());
|
||||
tx.send(());
|
||||
xr.read(|_state| { })
|
||||
});
|
||||
rp.recv(); // wait for reader task to exist
|
||||
rx.recv(); // wait for reader task to exist
|
||||
|
||||
let read_mode = x.downgrade(write_mode);
|
||||
read_mode.read(|state| {
|
||||
|
@ -20,44 +20,45 @@ use std::comm;
|
||||
|
||||
/// An extension of `pipes::stream` that allows both sending and receiving.
|
||||
pub struct DuplexStream<T, U> {
|
||||
priv chan: Chan<T>,
|
||||
priv port: Port<U>,
|
||||
priv tx: Sender<T>,
|
||||
priv rx: Receiver<U>,
|
||||
}
|
||||
|
||||
/// Creates a bidirectional stream.
|
||||
pub fn duplex<T: Send, U: Send>() -> (DuplexStream<T, U>, DuplexStream<U, T>) {
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
(DuplexStream { tx: tx1, rx: rx2 },
|
||||
DuplexStream { tx: tx2, rx: rx1 })
|
||||
}
|
||||
|
||||
// Allow these methods to be used without import:
|
||||
impl<T:Send,U:Send> DuplexStream<T, U> {
|
||||
/// Creates a bidirectional stream.
|
||||
pub fn new() -> (DuplexStream<T, U>, DuplexStream<U, T>) {
|
||||
let (p1, c2) = Chan::new();
|
||||
let (p2, c1) = Chan::new();
|
||||
(DuplexStream { chan: c1, port: p1 },
|
||||
DuplexStream { chan: c2, port: p2 })
|
||||
}
|
||||
pub fn send(&self, x: T) {
|
||||
self.chan.send(x)
|
||||
self.tx.send(x)
|
||||
}
|
||||
pub fn try_send(&self, x: T) -> bool {
|
||||
self.chan.try_send(x)
|
||||
self.tx.try_send(x)
|
||||
}
|
||||
pub fn recv(&self) -> U {
|
||||
self.port.recv()
|
||||
self.rx.recv()
|
||||
}
|
||||
pub fn try_recv(&self) -> comm::TryRecvResult<U> {
|
||||
self.port.try_recv()
|
||||
self.rx.try_recv()
|
||||
}
|
||||
pub fn recv_opt(&self) -> Option<U> {
|
||||
self.port.recv_opt()
|
||||
self.rx.recv_opt()
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension of `pipes::stream` that provides synchronous message sending.
|
||||
pub struct SyncChan<T> { priv duplex_stream: DuplexStream<T, ()> }
|
||||
pub struct SyncSender<T> { priv duplex_stream: DuplexStream<T, ()> }
|
||||
/// An extension of `pipes::stream` that acknowledges each message received.
|
||||
pub struct SyncPort<T> { priv duplex_stream: DuplexStream<(), T> }
|
||||
pub struct SyncReceiver<T> { priv duplex_stream: DuplexStream<(), T> }
|
||||
|
||||
impl<T: Send> SyncChan<T> {
|
||||
impl<T: Send> SyncSender<T> {
|
||||
pub fn send(&self, val: T) {
|
||||
assert!(self.try_send(val), "SyncChan.send: receiving port closed");
|
||||
assert!(self.try_send(val), "SyncSender.send: receiving port closed");
|
||||
}
|
||||
|
||||
/// Sends a message, or report if the receiver has closed the connection
|
||||
@ -67,9 +68,9 @@ impl<T: Send> SyncChan<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send> SyncPort<T> {
|
||||
impl<T: Send> SyncReceiver<T> {
|
||||
pub fn recv(&self) -> T {
|
||||
self.recv_opt().expect("SyncPort.recv: sending channel closed")
|
||||
self.recv_opt().expect("SyncReceiver.recv: sending channel closed")
|
||||
}
|
||||
|
||||
pub fn recv_opt(&self) -> Option<T> {
|
||||
@ -89,20 +90,20 @@ impl<T: Send> SyncPort<T> {
|
||||
|
||||
/// Creates a stream whose channel, upon sending a message, blocks until the
|
||||
/// message is received.
|
||||
pub fn rendezvous<T: Send>() -> (SyncPort<T>, SyncChan<T>) {
|
||||
let (chan_stream, port_stream) = DuplexStream::new();
|
||||
(SyncPort { duplex_stream: port_stream },
|
||||
SyncChan { duplex_stream: chan_stream })
|
||||
pub fn rendezvous<T: Send>() -> (SyncReceiver<T>, SyncSender<T>) {
|
||||
let (chan_stream, port_stream) = duplex();
|
||||
(SyncReceiver { duplex_stream: port_stream },
|
||||
SyncSender { duplex_stream: chan_stream })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use comm::{DuplexStream, rendezvous};
|
||||
use comm::{duplex, rendezvous};
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn DuplexStream1() {
|
||||
let (left, right) = DuplexStream::new();
|
||||
let (left, right) = duplex();
|
||||
|
||||
left.send(~"abc");
|
||||
right.send(123);
|
||||
|
@ -104,7 +104,7 @@ impl<A> Future<A> {
|
||||
}
|
||||
|
||||
impl<A:Send> Future<A> {
|
||||
pub fn from_port(port: Port<A>) -> Future<A> {
|
||||
pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
|
||||
/*!
|
||||
* Create a future from a port
|
||||
*
|
||||
@ -113,7 +113,7 @@ impl<A:Send> Future<A> {
|
||||
*/
|
||||
|
||||
Future::from_fn(proc() {
|
||||
port.recv()
|
||||
rx.recv()
|
||||
})
|
||||
}
|
||||
|
||||
@ -125,13 +125,13 @@ impl<A:Send> Future<A> {
|
||||
* value of the future.
|
||||
*/
|
||||
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
chan.send(blk());
|
||||
tx.send(blk());
|
||||
});
|
||||
|
||||
Future::from_port(port)
|
||||
Future::from_receiver(rx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,10 +148,10 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_port() {
|
||||
let (po, ch) = Chan::new();
|
||||
ch.send(~"whale");
|
||||
let mut f = Future::from_port(po);
|
||||
fn test_from_receiver() {
|
||||
let (tx, rx) = channel();
|
||||
tx.send(~"whale");
|
||||
let mut f = Future::from_receiver(rx);
|
||||
assert_eq!(f.get(), ~"whale");
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
pub use arc::{Arc, MutexArc, RWArc, RWWriteMode, RWReadMode, ArcCondvar, CowArc};
|
||||
pub use sync::{Mutex, RWLock, Condvar, Semaphore, RWLockWriteMode,
|
||||
RWLockReadMode, Barrier, one, mutex};
|
||||
pub use comm::{DuplexStream, SyncChan, SyncPort, rendezvous};
|
||||
RWLockReadMode, Barrier, one, mutex};
|
||||
pub use comm::{DuplexStream, SyncSender, SyncReceiver, rendezvous, duplex};
|
||||
pub use task_pool::TaskPool;
|
||||
pub use future::Future;
|
||||
|
||||
|
@ -37,17 +37,17 @@ mod mpsc_intrusive;
|
||||
|
||||
// Each waiting task receives on one of these.
|
||||
#[doc(hidden)]
|
||||
type WaitEnd = Port<()>;
|
||||
type WaitEnd = Receiver<()>;
|
||||
#[doc(hidden)]
|
||||
type SignalEnd = Chan<()>;
|
||||
type SignalEnd = Sender<()>;
|
||||
// A doubly-ended queue of waiting tasks.
|
||||
#[doc(hidden)]
|
||||
struct WaitQueue { head: Port<SignalEnd>,
|
||||
tail: Chan<SignalEnd> }
|
||||
struct WaitQueue { head: Receiver<SignalEnd>,
|
||||
tail: Sender<SignalEnd> }
|
||||
|
||||
impl WaitQueue {
|
||||
fn new() -> WaitQueue {
|
||||
let (block_head, block_tail) = Chan::new();
|
||||
let (block_tail, block_head) = channel();
|
||||
WaitQueue { head: block_head, tail: block_tail }
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ impl WaitQueue {
|
||||
}
|
||||
|
||||
fn wait_end(&self) -> WaitEnd {
|
||||
let (wait_end, signal_end) = Chan::new();
|
||||
let (signal_end, wait_end) = channel();
|
||||
assert!(self.tail.try_send(signal_end));
|
||||
wait_end
|
||||
}
|
||||
@ -797,28 +797,28 @@ mod tests {
|
||||
#[test]
|
||||
fn test_sem_as_cvar() {
|
||||
/* Child waits and parent signals */
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let s = Semaphore::new(0);
|
||||
let s2 = s.clone();
|
||||
task::spawn(proc() {
|
||||
s2.acquire();
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
for _ in range(0, 5) { task::deschedule(); }
|
||||
s.release();
|
||||
let _ = p.recv();
|
||||
let _ = rx.recv();
|
||||
|
||||
/* Parent waits and child signals */
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let s = Semaphore::new(0);
|
||||
let s2 = s.clone();
|
||||
task::spawn(proc() {
|
||||
for _ in range(0, 5) { task::deschedule(); }
|
||||
s2.release();
|
||||
let _ = p.recv();
|
||||
let _ = rx.recv();
|
||||
});
|
||||
s.acquire();
|
||||
c.send(());
|
||||
tx.send(());
|
||||
}
|
||||
#[test]
|
||||
fn test_sem_multi_resource() {
|
||||
@ -826,17 +826,17 @@ mod tests {
|
||||
// time, and shake hands.
|
||||
let s = Semaphore::new(2);
|
||||
let s2 = s.clone();
|
||||
let (p1,c1) = Chan::new();
|
||||
let (p2,c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
task::spawn(proc() {
|
||||
s2.access(|| {
|
||||
let _ = p2.recv();
|
||||
c1.send(());
|
||||
let _ = rx2.recv();
|
||||
tx1.send(());
|
||||
})
|
||||
});
|
||||
s.access(|| {
|
||||
c2.send(());
|
||||
let _ = p1.recv();
|
||||
tx2.send(());
|
||||
let _ = rx1.recv();
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
@ -845,19 +845,19 @@ mod tests {
|
||||
// When one blocks, it should schedule the other one.
|
||||
let s = Semaphore::new(1);
|
||||
let s2 = s.clone();
|
||||
let (p, c) = Chan::new();
|
||||
let mut child_data = Some((s2, c));
|
||||
let (tx, rx) = channel();
|
||||
let mut child_data = Some((s2, tx));
|
||||
s.access(|| {
|
||||
let (s2, c) = child_data.take_unwrap();
|
||||
let (s2, tx) = child_data.take_unwrap();
|
||||
task::spawn(proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
s2.access(|| { });
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
let _ = p.recv(); // wait for child to come alive
|
||||
let _ = rx.recv(); // wait for child to come alive
|
||||
for _ in range(0, 5) { task::deschedule(); } // let the child contend
|
||||
});
|
||||
let _ = p.recv(); // wait for child to be done
|
||||
let _ = rx.recv(); // wait for child to be done
|
||||
}
|
||||
/************************************************************************
|
||||
* Mutex tests
|
||||
@ -866,7 +866,7 @@ mod tests {
|
||||
fn test_mutex_lock() {
|
||||
// Unsafely achieve shared state, and do the textbook
|
||||
// "load tmp = move ptr; inc tmp; store ptr <- tmp" dance.
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let m = Mutex::new();
|
||||
let m2 = m.clone();
|
||||
let mut sharedstate = ~0;
|
||||
@ -876,12 +876,12 @@ mod tests {
|
||||
let sharedstate: &mut int =
|
||||
unsafe { cast::transmute(ptr) };
|
||||
access_shared(sharedstate, &m2, 10);
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
}
|
||||
{
|
||||
access_shared(sharedstate, &m, 10);
|
||||
let _ = p.recv();
|
||||
let _ = rx.recv();
|
||||
|
||||
assert_eq!(*sharedstate, 20);
|
||||
}
|
||||
@ -912,48 +912,48 @@ mod tests {
|
||||
cond.wait();
|
||||
});
|
||||
// Parent wakes up child
|
||||
let (port,chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let m3 = m.clone();
|
||||
task::spawn(proc() {
|
||||
m3.lock_cond(|cond| {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
cond.wait();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
})
|
||||
});
|
||||
let _ = port.recv(); // Wait until child gets in the mutex
|
||||
let _ = rx.recv(); // Wait until child gets in the mutex
|
||||
m.lock_cond(|cond| {
|
||||
let woken = cond.signal();
|
||||
assert!(woken);
|
||||
});
|
||||
let _ = port.recv(); // Wait until child wakes up
|
||||
let _ = rx.recv(); // Wait until child wakes up
|
||||
}
|
||||
#[cfg(test)]
|
||||
fn test_mutex_cond_broadcast_helper(num_waiters: uint) {
|
||||
let m = Mutex::new();
|
||||
let mut ports = ~[];
|
||||
let mut rxs = ~[];
|
||||
|
||||
for _ in range(0, num_waiters) {
|
||||
let mi = m.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
ports.push(port);
|
||||
let (tx, rx) = channel();
|
||||
rxs.push(rx);
|
||||
task::spawn(proc() {
|
||||
mi.lock_cond(|cond| {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
cond.wait();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// wait until all children get in the mutex
|
||||
for port in ports.mut_iter() { let _ = port.recv(); }
|
||||
for rx in rxs.mut_iter() { let _ = rx.recv(); }
|
||||
m.lock_cond(|cond| {
|
||||
let num_woken = cond.broadcast();
|
||||
assert_eq!(num_woken, num_waiters);
|
||||
});
|
||||
// wait until all children wake up
|
||||
for port in ports.mut_iter() { let _ = port.recv(); }
|
||||
for rx in rxs.mut_iter() { let _ = rx.recv(); }
|
||||
}
|
||||
#[test]
|
||||
fn test_mutex_cond_broadcast() {
|
||||
@ -991,81 +991,6 @@ mod tests {
|
||||
// child task must have finished by the time try returns
|
||||
m.lock(|| { })
|
||||
}
|
||||
#[ignore(reason = "linked failure")]
|
||||
#[test]
|
||||
fn test_mutex_killed_cond() {
|
||||
use std::any::Any;
|
||||
|
||||
// Getting killed during cond wait must not corrupt the mutex while
|
||||
// unwinding (e.g. double unlock).
|
||||
let m = Mutex::new();
|
||||
let m2 = m.clone();
|
||||
|
||||
let result: result::Result<(), ~Any> = task::try(proc() {
|
||||
let (p, c) = Chan::new();
|
||||
task::spawn(proc() { // linked
|
||||
let _ = p.recv(); // wait for sibling to get in the mutex
|
||||
task::deschedule();
|
||||
fail!();
|
||||
});
|
||||
m2.lock_cond(|cond| {
|
||||
c.send(()); // tell sibling go ahead
|
||||
cond.wait(); // block forever
|
||||
})
|
||||
});
|
||||
assert!(result.is_err());
|
||||
// child task must have finished by the time try returns
|
||||
m.lock_cond(|cond| {
|
||||
let woken = cond.signal();
|
||||
assert!(!woken);
|
||||
})
|
||||
}
|
||||
#[ignore(reason = "linked failure")]
|
||||
#[test]
|
||||
fn test_mutex_killed_broadcast() {
|
||||
use std::any::Any;
|
||||
use std::unstable::finally::Finally;
|
||||
|
||||
let m = Mutex::new();
|
||||
let m2 = m.clone();
|
||||
let (p, c) = Chan::new();
|
||||
|
||||
let result: result::Result<(), ~Any> = task::try(proc() {
|
||||
let mut sibling_convos = ~[];
|
||||
for _ in range(0, 2) {
|
||||
let (p, c) = Chan::new();
|
||||
sibling_convos.push(p);
|
||||
let mi = m2.clone();
|
||||
// spawn sibling task
|
||||
task::spawn(proc() { // linked
|
||||
mi.lock_cond(|cond| {
|
||||
c.send(()); // tell sibling to go ahead
|
||||
(|| {
|
||||
cond.wait(); // block forever
|
||||
}).finally(|| {
|
||||
error!("task unwinding and sending");
|
||||
c.send(());
|
||||
error!("task unwinding and done sending");
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
for p in sibling_convos.mut_iter() {
|
||||
let _ = p.recv(); // wait for sibling to get in the mutex
|
||||
}
|
||||
m2.lock(|| { });
|
||||
c.send(sibling_convos); // let parent wait on all children
|
||||
fail!();
|
||||
});
|
||||
assert!(result.is_err());
|
||||
// child task must have finished by the time try returns
|
||||
let mut r = p.recv();
|
||||
for p in r.mut_iter() { p.recv(); } // wait on all its siblings
|
||||
m.lock_cond(|cond| {
|
||||
let woken = cond.broadcast();
|
||||
assert_eq!(woken, 0);
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
fn test_mutex_cond_signal_on_0() {
|
||||
// Tests that signal_on(0) is equivalent to signal().
|
||||
@ -1081,28 +1006,6 @@ mod tests {
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
#[ignore(reason = "linked failure?")]
|
||||
fn test_mutex_different_conds() {
|
||||
let result = task::try(proc() {
|
||||
let m = Mutex::new_with_condvars(2);
|
||||
let m2 = m.clone();
|
||||
let (p, c) = Chan::new();
|
||||
task::spawn(proc() {
|
||||
m2.lock_cond(|cond| {
|
||||
c.send(());
|
||||
cond.wait_on(1);
|
||||
})
|
||||
});
|
||||
let _ = p.recv();
|
||||
m.lock_cond(|cond| {
|
||||
if !cond.signal_on(0) {
|
||||
fail!(); // success; punt sibling awake.
|
||||
}
|
||||
})
|
||||
});
|
||||
assert!(result.is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_mutex_no_condvars() {
|
||||
let result = task::try(proc() {
|
||||
let m = Mutex::new_with_condvars(0);
|
||||
@ -1143,11 +1046,11 @@ mod tests {
|
||||
}
|
||||
#[cfg(test)]
|
||||
fn test_rwlock_exclusion(x: &RWLock,
|
||||
mode1: RWLockMode,
|
||||
mode2: RWLockMode) {
|
||||
mode1: RWLockMode,
|
||||
mode2: RWLockMode) {
|
||||
// Test mutual exclusion between readers and writers. Just like the
|
||||
// mutex mutual exclusion test, a ways above.
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let x2 = x.clone();
|
||||
let mut sharedstate = ~0;
|
||||
{
|
||||
@ -1156,12 +1059,12 @@ mod tests {
|
||||
let sharedstate: &mut int =
|
||||
unsafe { cast::transmute(ptr) };
|
||||
access_shared(sharedstate, &x2, mode1, 10);
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
}
|
||||
{
|
||||
access_shared(sharedstate, x, mode2, 10);
|
||||
let _ = p.recv();
|
||||
let _ = rx.recv();
|
||||
|
||||
assert_eq!(*sharedstate, 20);
|
||||
}
|
||||
@ -1198,29 +1101,29 @@ mod tests {
|
||||
make_mode2_go_first: bool) {
|
||||
// Much like sem_multi_resource.
|
||||
let x2 = x.clone();
|
||||
let (p1, c1) = Chan::new();
|
||||
let (p2, c2) = Chan::new();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
task::spawn(proc() {
|
||||
if !make_mode2_go_first {
|
||||
let _ = p2.recv(); // parent sends to us once it locks, or ...
|
||||
let _ = rx2.recv(); // parent sends to us once it locks, or ...
|
||||
}
|
||||
lock_rwlock_in_mode(&x2, mode2, || {
|
||||
if make_mode2_go_first {
|
||||
c1.send(()); // ... we send to it once we lock
|
||||
tx1.send(()); // ... we send to it once we lock
|
||||
}
|
||||
let _ = p2.recv();
|
||||
c1.send(());
|
||||
let _ = rx2.recv();
|
||||
tx1.send(());
|
||||
})
|
||||
});
|
||||
if make_mode2_go_first {
|
||||
let _ = p1.recv(); // child sends to us once it locks, or ...
|
||||
let _ = rx1.recv(); // child sends to us once it locks, or ...
|
||||
}
|
||||
lock_rwlock_in_mode(x, mode1, || {
|
||||
if !make_mode2_go_first {
|
||||
c2.send(()); // ... we send to it once we lock
|
||||
tx2.send(()); // ... we send to it once we lock
|
||||
}
|
||||
c2.send(());
|
||||
let _ = p1.recv();
|
||||
tx2.send(());
|
||||
let _ = rx1.recv();
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
@ -1264,22 +1167,22 @@ mod tests {
|
||||
cond.wait();
|
||||
});
|
||||
// Parent wakes up child
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let x3 = x.clone();
|
||||
task::spawn(proc() {
|
||||
x3.write_cond(|cond| {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
cond.wait();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
})
|
||||
});
|
||||
let _ = port.recv(); // Wait until child gets in the rwlock
|
||||
let _ = rx.recv(); // Wait until child gets in the rwlock
|
||||
x.read(|| { }); // Must be able to get in as a reader in the meantime
|
||||
x.write_cond(|cond| { // Or as another writer
|
||||
let woken = cond.signal();
|
||||
assert!(woken);
|
||||
});
|
||||
let _ = port.recv(); // Wait until child wakes up
|
||||
let _ = rx.recv(); // Wait until child wakes up
|
||||
x.read(|| { }); // Just for good measure
|
||||
}
|
||||
#[cfg(test)]
|
||||
@ -1297,29 +1200,29 @@ mod tests {
|
||||
}
|
||||
}
|
||||
let x = RWLock::new();
|
||||
let mut ports = ~[];
|
||||
let mut rxs = ~[];
|
||||
|
||||
for _ in range(0, num_waiters) {
|
||||
let xi = x.clone();
|
||||
let (port, chan) = Chan::new();
|
||||
ports.push(port);
|
||||
let (tx, rx) = channel();
|
||||
rxs.push(rx);
|
||||
task::spawn(proc() {
|
||||
lock_cond(&xi, dg1, |cond| {
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
cond.wait();
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// wait until all children get in the mutex
|
||||
for port in ports.mut_iter() { let _ = port.recv(); }
|
||||
for rx in rxs.mut_iter() { let _ = rx.recv(); }
|
||||
lock_cond(&x, dg2, |cond| {
|
||||
let num_woken = cond.broadcast();
|
||||
assert_eq!(num_woken, num_waiters);
|
||||
});
|
||||
// wait until all children wake up
|
||||
for port in ports.mut_iter() { let _ = port.recv(); }
|
||||
for rx in rxs.mut_iter() { let _ = rx.recv(); }
|
||||
}
|
||||
#[test]
|
||||
fn test_rwlock_cond_broadcast() {
|
||||
@ -1400,20 +1303,20 @@ mod tests {
|
||||
#[test]
|
||||
fn test_barrier() {
|
||||
let barrier = Barrier::new(10);
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
for _ in range(0, 9) {
|
||||
let c = barrier.clone();
|
||||
let chan = chan.clone();
|
||||
let tx = tx.clone();
|
||||
spawn(proc() {
|
||||
c.wait();
|
||||
chan.send(true);
|
||||
tx.send(true);
|
||||
});
|
||||
}
|
||||
|
||||
// At this point, all spawned tasks should be blocked,
|
||||
// so we shouldn't get anything from the port
|
||||
assert!(match port.try_recv() {
|
||||
assert!(match rx.try_recv() {
|
||||
Empty => true,
|
||||
_ => false,
|
||||
});
|
||||
@ -1421,7 +1324,7 @@ mod tests {
|
||||
barrier.wait();
|
||||
// Now, the barrier is cleared and we should get data.
|
||||
for _ in range(0, 9) {
|
||||
port.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -532,17 +532,17 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
for _ in range(0, N) {
|
||||
let c2 = c.clone();
|
||||
native::task::spawn(proc() { inc(); c2.send(()); });
|
||||
let c2 = c.clone();
|
||||
spawn(proc() { inc(); c2.send(()); });
|
||||
let tx2 = tx.clone();
|
||||
native::task::spawn(proc() { inc(); tx2.send(()); });
|
||||
let tx2 = tx.clone();
|
||||
spawn(proc() { inc(); tx2.send(()); });
|
||||
}
|
||||
|
||||
drop(c);
|
||||
drop(tx);
|
||||
for _ in range(0, 2 * N) {
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
assert_eq!(unsafe {CNT}, M * N * 2);
|
||||
unsafe {
|
||||
|
@ -137,9 +137,9 @@ mod test {
|
||||
static mut o: Once = ONCE_INIT;
|
||||
static mut run: bool = false;
|
||||
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
for _ in range(0, 10) {
|
||||
let c = c.clone();
|
||||
let tx = tx.clone();
|
||||
spawn(proc() {
|
||||
for _ in range(0, 4) { task::deschedule() }
|
||||
unsafe {
|
||||
@ -149,7 +149,7 @@ mod test {
|
||||
});
|
||||
assert!(run);
|
||||
}
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ mod test {
|
||||
}
|
||||
|
||||
for _ in range(0, 10) {
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ enum Msg<T> {
|
||||
}
|
||||
|
||||
pub struct TaskPool<T> {
|
||||
priv channels: ~[Chan<Msg<T>>],
|
||||
priv channels: ~[Sender<Msg<T>>],
|
||||
priv next_index: uint,
|
||||
}
|
||||
|
||||
@ -48,13 +48,13 @@ impl<T> TaskPool<T> {
|
||||
assert!(n_tasks >= 1);
|
||||
|
||||
let channels = vec::from_fn(n_tasks, |i| {
|
||||
let (port, chan) = Chan::<Msg<T>>::new();
|
||||
let (tx, rx) = channel::<Msg<T>>();
|
||||
let init_fn = init_fn_factory();
|
||||
|
||||
let task_body: proc() = proc() {
|
||||
let local_data = init_fn(i);
|
||||
loop {
|
||||
match port.recv() {
|
||||
match rx.recv() {
|
||||
Execute(f) => f(&local_data),
|
||||
Quit => break
|
||||
}
|
||||
@ -64,7 +64,7 @@ impl<T> TaskPool<T> {
|
||||
// Run on this scheduler.
|
||||
task::spawn(task_body);
|
||||
|
||||
chan
|
||||
tx
|
||||
});
|
||||
|
||||
return TaskPool { channels: channels, next_index: 0 };
|
||||
|
@ -53,7 +53,7 @@ use std::f64;
|
||||
use std::fmt;
|
||||
use std::from_str::FromStr;
|
||||
use std::io::stdio::StdWriter;
|
||||
use std::io::{File, PortReader, ChanWriter};
|
||||
use std::io::{File, ChanReader, ChanWriter};
|
||||
use std::io;
|
||||
use std::os;
|
||||
use std::str;
|
||||
@ -827,7 +827,7 @@ fn run_tests(opts: &TestOpts,
|
||||
remaining.reverse();
|
||||
let mut pending = 0;
|
||||
|
||||
let (p, ch) = Chan::<MonitorMsg>::new();
|
||||
let (tx, rx) = channel::<MonitorMsg>();
|
||||
|
||||
while pending > 0 || !remaining.is_empty() {
|
||||
while pending < concurrency && !remaining.is_empty() {
|
||||
@ -838,11 +838,11 @@ fn run_tests(opts: &TestOpts,
|
||||
// that hang forever.
|
||||
try!(callback(TeWait(test.desc.clone(), test.testfn.padding())));
|
||||
}
|
||||
run_test(!opts.run_tests, test, ch.clone());
|
||||
run_test(!opts.run_tests, test, tx.clone());
|
||||
pending += 1;
|
||||
}
|
||||
|
||||
let (desc, result, stdout) = p.recv();
|
||||
let (desc, result, stdout) = rx.recv();
|
||||
if concurrency != 1 {
|
||||
try!(callback(TeWait(desc.clone(), PadNone)));
|
||||
}
|
||||
@ -854,8 +854,8 @@ fn run_tests(opts: &TestOpts,
|
||||
// (this includes metric fns)
|
||||
for b in filtered_benchs_and_metrics.move_iter() {
|
||||
try!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
|
||||
run_test(!opts.run_benchmarks, b, ch.clone());
|
||||
let (test, result, stdout) = p.recv();
|
||||
run_test(!opts.run_benchmarks, b, tx.clone());
|
||||
let (test, result, stdout) = rx.recv();
|
||||
try!(callback(TeResult(test, result, stdout)));
|
||||
}
|
||||
Ok(())
|
||||
@ -938,7 +938,7 @@ pub fn filter_tests(
|
||||
|
||||
pub fn run_test(force_ignore: bool,
|
||||
test: TestDescAndFn,
|
||||
monitor_ch: Chan<MonitorMsg>) {
|
||||
monitor_ch: Sender<MonitorMsg>) {
|
||||
|
||||
let TestDescAndFn {desc, testfn} = test;
|
||||
|
||||
@ -948,13 +948,13 @@ pub fn run_test(force_ignore: bool,
|
||||
}
|
||||
|
||||
fn run_test_inner(desc: TestDesc,
|
||||
monitor_ch: Chan<MonitorMsg>,
|
||||
monitor_ch: Sender<MonitorMsg>,
|
||||
testfn: proc()) {
|
||||
spawn(proc() {
|
||||
let (p, c) = Chan::new();
|
||||
let mut reader = PortReader::new(p);
|
||||
let stdout = ChanWriter::new(c.clone());
|
||||
let stderr = ChanWriter::new(c);
|
||||
let (tx, rx) = channel();
|
||||
let mut reader = ChanReader::new(rx);
|
||||
let stdout = ChanWriter::new(tx.clone());
|
||||
let stderr = ChanWriter::new(tx);
|
||||
let mut task = task::task().named(match desc.name {
|
||||
DynTestName(ref name) => name.clone().into_maybe_owned(),
|
||||
StaticTestName(name) => name.into_maybe_owned(),
|
||||
@ -1321,9 +1321,9 @@ mod tests {
|
||||
},
|
||||
testfn: DynTestFn(proc() f()),
|
||||
};
|
||||
let (p, ch) = Chan::new();
|
||||
run_test(false, desc, ch);
|
||||
let (_, res, _) = p.recv();
|
||||
let (tx, rx) = channel();
|
||||
run_test(false, desc, tx);
|
||||
let (_, res, _) = rx.recv();
|
||||
assert!(res != TrOk);
|
||||
}
|
||||
|
||||
@ -1338,9 +1338,9 @@ mod tests {
|
||||
},
|
||||
testfn: DynTestFn(proc() f()),
|
||||
};
|
||||
let (p, ch) = Chan::new();
|
||||
run_test(false, desc, ch);
|
||||
let (_, res, _) = p.recv();
|
||||
let (tx, rx) = channel();
|
||||
run_test(false, desc, tx);
|
||||
let (_, res, _) = rx.recv();
|
||||
assert!(res == TrIgnored);
|
||||
}
|
||||
|
||||
@ -1355,9 +1355,9 @@ mod tests {
|
||||
},
|
||||
testfn: DynTestFn(proc() f()),
|
||||
};
|
||||
let (p, ch) = Chan::new();
|
||||
run_test(false, desc, ch);
|
||||
let (_, res, _) = p.recv();
|
||||
let (tx, rx) = channel();
|
||||
run_test(false, desc, tx);
|
||||
let (_, res, _) = rx.recv();
|
||||
assert!(res == TrOk);
|
||||
}
|
||||
|
||||
@ -1372,9 +1372,9 @@ mod tests {
|
||||
},
|
||||
testfn: DynTestFn(proc() f()),
|
||||
};
|
||||
let (p, ch) = Chan::new();
|
||||
run_test(false, desc, ch);
|
||||
let (_, res, _) = p.recv();
|
||||
let (tx, rx) = channel();
|
||||
run_test(false, desc, tx);
|
||||
let (_, res, _) = rx.recv();
|
||||
assert!(res == TrFailed);
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@
|
||||
|
||||
use std::task;
|
||||
|
||||
pub fn foo<T:Send + Clone>(x: T) -> Port<T> {
|
||||
let (p, c) = Chan::new();
|
||||
pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> {
|
||||
let (tx, rx) = channel();
|
||||
task::spawn(proc() {
|
||||
c.send(x.clone());
|
||||
tx.send(x.clone());
|
||||
});
|
||||
p
|
||||
rx
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ enum request {
|
||||
stop
|
||||
}
|
||||
|
||||
fn server(requests: &Port<request>, responses: &Chan<uint>) {
|
||||
fn server(requests: &Receiver<request>, responses: &Sender<uint>) {
|
||||
let mut count = 0u;
|
||||
let mut done = false;
|
||||
while !done {
|
||||
@ -52,8 +52,8 @@ fn server(requests: &Port<request>, responses: &Chan<uint>) {
|
||||
}
|
||||
|
||||
fn run(args: &[~str]) {
|
||||
let (from_child, to_parent) = Chan::new();
|
||||
let (from_parent, to_child) = Chan::new();
|
||||
let (to_parent, from_child) = channel();
|
||||
let (to_child, from_parent) = channel();
|
||||
|
||||
let size = from_str::<uint>(args[1]).unwrap();
|
||||
let workers = from_str::<uint>(args[2]).unwrap();
|
||||
|
@ -28,7 +28,7 @@ enum request {
|
||||
stop
|
||||
}
|
||||
|
||||
fn server(requests: &Port<request>, responses: &Chan<uint>) {
|
||||
fn server(requests: &Receiver<request>, responses: &Sender<uint>) {
|
||||
let mut count: uint = 0;
|
||||
let mut done = false;
|
||||
while !done {
|
||||
@ -47,7 +47,7 @@ fn server(requests: &Port<request>, responses: &Chan<uint>) {
|
||||
}
|
||||
|
||||
fn run(args: &[~str]) {
|
||||
let (from_child, to_parent) = Chan::new();
|
||||
let (to_parent, from_child) = channel();
|
||||
|
||||
let size = from_str::<uint>(args[1]).unwrap();
|
||||
let workers = from_str::<uint>(args[2]).unwrap();
|
||||
@ -55,7 +55,7 @@ fn run(args: &[~str]) {
|
||||
let start = time::precise_time_s();
|
||||
let mut worker_results = ~[];
|
||||
let from_parent = if workers == 1 {
|
||||
let (from_parent, to_child) = Chan::new();
|
||||
let (to_child, from_parent) = channel();
|
||||
let mut builder = task::task();
|
||||
worker_results.push(builder.future_result());
|
||||
builder.spawn(proc() {
|
||||
@ -67,7 +67,7 @@ fn run(args: &[~str]) {
|
||||
});
|
||||
from_parent
|
||||
} else {
|
||||
let (from_parent, to_child) = Chan::new();
|
||||
let (to_child, from_parent) = channel();
|
||||
for _ in range(0u, workers) {
|
||||
let to_child = to_child.clone();
|
||||
let mut builder = task::task();
|
||||
|
@ -32,25 +32,23 @@ fn ping_pong_bench(n: uint, m: uint) {
|
||||
// Create pairs of tasks that pingpong back and forth.
|
||||
fn run_pair(n: uint) {
|
||||
// Create a stream A->B
|
||||
let (pa,ca) = Chan::<()>::new();
|
||||
let (atx, arx) = channel::<()>();
|
||||
// Create a stream B->A
|
||||
let (pb,cb) = Chan::<()>::new();
|
||||
let (btx, brx) = channel::<()>();
|
||||
|
||||
spawn(proc() {
|
||||
let chan = ca;
|
||||
let port = pb;
|
||||
let (tx, rx) = (atx, brx);
|
||||
for _ in range(0, n) {
|
||||
chan.send(());
|
||||
port.recv();
|
||||
tx.send(());
|
||||
rx.recv();
|
||||
}
|
||||
});
|
||||
|
||||
spawn(proc() {
|
||||
let chan = cb;
|
||||
let port = pa;
|
||||
let (tx, rx) = (btx, arx);
|
||||
for _ in range(0, n) {
|
||||
port.recv();
|
||||
chan.send(());
|
||||
rx.recv();
|
||||
tx.send(());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -22,12 +22,12 @@ fn parfib(n: uint) -> uint {
|
||||
return 1;
|
||||
}
|
||||
|
||||
let (port,chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
chan.send(parfib(n-1));
|
||||
tx.send(parfib(n-1));
|
||||
});
|
||||
let m2 = parfib(n-2);
|
||||
return (port.recv() + m2);
|
||||
return (rx.recv() + m2);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -99,9 +99,9 @@ fn transform(aa: color, bb: color) -> color {
|
||||
fn creature(
|
||||
name: uint,
|
||||
color: color,
|
||||
from_rendezvous: Port<Option<CreatureInfo>>,
|
||||
to_rendezvous: Chan<CreatureInfo>,
|
||||
to_rendezvous_log: Chan<~str>
|
||||
from_rendezvous: Receiver<Option<CreatureInfo>>,
|
||||
to_rendezvous: Sender<CreatureInfo>,
|
||||
to_rendezvous_log: Sender<~str>
|
||||
) {
|
||||
let mut color = color;
|
||||
let mut creatures_met = 0;
|
||||
@ -137,13 +137,13 @@ fn creature(
|
||||
fn rendezvous(nn: uint, set: ~[color]) {
|
||||
|
||||
// these ports will allow us to hear from the creatures
|
||||
let (from_creatures, to_rendezvous) = Chan::<CreatureInfo>::new();
|
||||
let (from_creatures_log, to_rendezvous_log) = Chan::<~str>::new();
|
||||
let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
|
||||
let (to_rendezvous_log, from_creatures_log) = channel::<~str>();
|
||||
|
||||
// these channels will be passed to the creatures so they can talk to us
|
||||
|
||||
// these channels will allow us to talk to each creature by 'name'/index
|
||||
let to_creature: ~[Chan<Option<CreatureInfo>>] =
|
||||
let to_creature: ~[Sender<Option<CreatureInfo>>] =
|
||||
set.iter().enumerate().map(|(ii, col)| {
|
||||
// create each creature as a listener with a port, and
|
||||
// give us a channel to talk to each
|
||||
@ -151,7 +151,7 @@ fn rendezvous(nn: uint, set: ~[color]) {
|
||||
let col = *col;
|
||||
let to_rendezvous = to_rendezvous.clone();
|
||||
let to_rendezvous_log = to_rendezvous_log.clone();
|
||||
let (from_rendezvous, to_creature) = Chan::new();
|
||||
let (to_creature, from_rendezvous) = channel();
|
||||
task::spawn(proc() {
|
||||
creature(ii,
|
||||
col,
|
||||
|
@ -111,8 +111,8 @@ fn windows_with_carry(bb: &[u8], nn: uint, it: |window: &[u8]|) -> ~[u8] {
|
||||
}
|
||||
|
||||
fn make_sequence_processor(sz: uint,
|
||||
from_parent: &Port<~[u8]>,
|
||||
to_parent: &Chan<~str>) {
|
||||
from_parent: &Receiver<~[u8]>,
|
||||
to_parent: &Sender<~str>) {
|
||||
let mut freqs: HashMap<~[u8], uint> = HashMap::new();
|
||||
let mut carry: ~[u8] = ~[];
|
||||
let mut total: uint = 0u;
|
||||
@ -158,23 +158,23 @@ fn main() {
|
||||
|
||||
// initialize each sequence sorter
|
||||
let sizes = ~[1u,2,3,4,6,12,18];
|
||||
let mut streams = vec::from_fn(sizes.len(), |_| Some(Chan::<~str>::new()));
|
||||
let mut streams = vec::from_fn(sizes.len(), |_| Some(channel::<~str>()));
|
||||
let mut from_child = ~[];
|
||||
let to_child = sizes.iter().zip(streams.mut_iter()).map(|(sz, stream_ref)| {
|
||||
let to_child = sizes.iter().zip(streams.mut_iter()).map(|(sz, stream_ref)| {
|
||||
let sz = *sz;
|
||||
let stream = replace(stream_ref, None);
|
||||
let (from_child_, to_parent_) = stream.unwrap();
|
||||
let (to_parent_, from_child_) = stream.unwrap();
|
||||
|
||||
from_child.push(from_child_);
|
||||
|
||||
let (from_parent, to_child) = Chan::new();
|
||||
let (to_child, from_parent) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
make_sequence_processor(sz, &from_parent, &to_parent_);
|
||||
});
|
||||
|
||||
to_child
|
||||
}).collect::<~[Chan<~[u8]>]>();
|
||||
}).collect::<~[Sender<~[u8]>]>();
|
||||
|
||||
|
||||
// latch stores true after we've started
|
||||
|
@ -27,24 +27,24 @@ use std::task;
|
||||
use std::uint;
|
||||
|
||||
fn fib(n: int) -> int {
|
||||
fn pfib(c: &Chan<int>, n: int) {
|
||||
fn pfib(tx: &Sender<int>, n: int) {
|
||||
if n == 0 {
|
||||
c.send(0);
|
||||
tx.send(0);
|
||||
} else if n <= 2 {
|
||||
c.send(1);
|
||||
tx.send(1);
|
||||
} else {
|
||||
let (pp, cc) = Chan::new();
|
||||
let ch = cc.clone();
|
||||
task::spawn(proc() pfib(&ch, n - 1));
|
||||
let ch = cc.clone();
|
||||
task::spawn(proc() pfib(&ch, n - 2));
|
||||
c.send(pp.recv() + pp.recv());
|
||||
let (tx1, rx) = channel();
|
||||
let tx2 = tx1.clone();
|
||||
task::spawn(proc() pfib(&tx2, n - 1));
|
||||
let tx2 = tx1.clone();
|
||||
task::spawn(proc() pfib(&tx2, n - 2));
|
||||
tx.send(rx.recv() + rx.recv());
|
||||
}
|
||||
}
|
||||
|
||||
let (p, ch) = Chan::new();
|
||||
let _t = task::spawn(proc() pfib(&ch, n) );
|
||||
p.recv()
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() pfib(&tx, n) );
|
||||
rx.recv()
|
||||
}
|
||||
|
||||
struct Config {
|
||||
|
@ -35,13 +35,13 @@ fn mult(v: RWArc<~[f64]>, out: RWArc<~[f64]>, f: fn(&~[f64], uint) -> f64) {
|
||||
// tasks. To do that, we give to each tasks a wait_chan that we
|
||||
// drop at the end of the work. At the end of this function, we
|
||||
// wait until the channel hang up.
|
||||
let (wait_port, wait_chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let len = out.read(|out| out.len());
|
||||
let chunk = len / 100 + 1;
|
||||
for chk in count(0, chunk) {
|
||||
if chk >= len {break;}
|
||||
let w = wait_chan.clone();
|
||||
let tx = tx.clone();
|
||||
let v = v.clone();
|
||||
let out = out.clone();
|
||||
spawn(proc() {
|
||||
@ -49,13 +49,13 @@ fn mult(v: RWArc<~[f64]>, out: RWArc<~[f64]>, f: fn(&~[f64], uint) -> f64) {
|
||||
let val = v.read(|v| f(v, i));
|
||||
out.write(|out| out[i] = val);
|
||||
}
|
||||
drop(w)
|
||||
drop(tx)
|
||||
});
|
||||
}
|
||||
|
||||
// wait until the channel hang up (every task finished)
|
||||
drop(wait_chan);
|
||||
for () in wait_port.iter() {}
|
||||
drop(tx);
|
||||
for () in rx.iter() {}
|
||||
}
|
||||
|
||||
fn mult_Av_impl(v: &~[f64], i: uint) -> f64 {
|
||||
|
@ -13,30 +13,27 @@
|
||||
use std::os;
|
||||
|
||||
fn start(n_tasks: int, token: int) {
|
||||
let (p, ch1) = Chan::new();
|
||||
let mut p = p;
|
||||
let ch1 = ch1;
|
||||
ch1.send(token);
|
||||
let (tx, mut rx) = channel();
|
||||
tx.send(token);
|
||||
// XXX could not get this to work with a range closure
|
||||
let mut i = 2;
|
||||
while i <= n_tasks {
|
||||
let (next_p, ch) = Chan::new();
|
||||
let (tx, next_rx) = channel();
|
||||
let imm_i = i;
|
||||
let imm_p = p;
|
||||
let imm_rx = rx;
|
||||
spawn(proc() {
|
||||
roundtrip(imm_i, n_tasks, &imm_p, &ch);
|
||||
roundtrip(imm_i, n_tasks, &imm_rx, &tx);
|
||||
});
|
||||
p = next_p;
|
||||
rx = next_rx;
|
||||
i += 1;
|
||||
}
|
||||
let imm_p = p;
|
||||
let imm_ch = ch1;
|
||||
let imm_rx = rx;
|
||||
spawn(proc() {
|
||||
roundtrip(1, n_tasks, &imm_p, &imm_ch);
|
||||
roundtrip(1, n_tasks, &imm_rx, &tx);
|
||||
});
|
||||
}
|
||||
|
||||
fn roundtrip(id: int, n_tasks: int, p: &Port<int>, ch: &Chan<int>) {
|
||||
fn roundtrip(id: int, n_tasks: int, p: &Receiver<int>, ch: &Sender<int>) {
|
||||
loop {
|
||||
match p.recv() {
|
||||
1 => {
|
||||
|
@ -22,7 +22,7 @@ use std::os;
|
||||
use std::task;
|
||||
use std::uint;
|
||||
|
||||
fn child_generation(gens_left: uint, c: comm::Chan<()>) {
|
||||
fn child_generation(gens_left: uint, tx: comm::Sender<()>) {
|
||||
// This used to be O(n^2) in the number of generations that ever existed.
|
||||
// With this code, only as many generations are alive at a time as tasks
|
||||
// alive at a time,
|
||||
@ -31,9 +31,9 @@ fn child_generation(gens_left: uint, c: comm::Chan<()>) {
|
||||
task::deschedule(); // shake things up a bit
|
||||
}
|
||||
if gens_left > 0 {
|
||||
child_generation(gens_left - 1, c); // recurse
|
||||
child_generation(gens_left - 1, tx); // recurse
|
||||
} else {
|
||||
c.send(())
|
||||
tx.send(())
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -48,9 +48,9 @@ fn main() {
|
||||
args.clone()
|
||||
};
|
||||
|
||||
let (p,c) = Chan::new();
|
||||
child_generation(from_str::<uint>(args[1]).unwrap(), c);
|
||||
if p.recv_opt().is_none() {
|
||||
let (tx, rx) = channel();
|
||||
child_generation(from_str::<uint>(args[1]).unwrap(), tx);
|
||||
if rx.recv_opt().is_none() {
|
||||
fail!("it happened when we slumbered");
|
||||
}
|
||||
}
|
||||
|
@ -17,24 +17,24 @@ use std::task;
|
||||
use std::uint;
|
||||
use std::vec;
|
||||
|
||||
fn calc(children: uint, parent_wait_chan: &Chan<Chan<Chan<int>>>) {
|
||||
fn calc(children: uint, parent_wait_chan: &Sender<Sender<Sender<int>>>) {
|
||||
|
||||
let wait_ports: ~[Port<Chan<Chan<int>>>] = vec::from_fn(children, |_| {
|
||||
let (wait_port, wait_chan) = stream::<Chan<Chan<int>>>();
|
||||
let wait_ports: ~[Receiver<Sender<Sender<int>>>] = vec::from_fn(children, |_| {
|
||||
let (wait_port, wait_chan) = stream::<Sender<Sender<int>>>();
|
||||
task::spawn(proc() {
|
||||
calc(children / 2, &wait_chan);
|
||||
});
|
||||
wait_port
|
||||
});
|
||||
|
||||
let child_start_chans: ~[Chan<Chan<int>>] =
|
||||
let child_start_chans: ~[Sender<Sender<int>>] =
|
||||
wait_ports.move_iter().map(|port| port.recv()).collect();
|
||||
|
||||
let (start_port, start_chan) = stream::<Chan<int>>();
|
||||
let (start_port, start_chan) = stream::<Sender<int>>();
|
||||
parent_wait_chan.send(start_chan);
|
||||
let parent_result_chan: Chan<int> = start_port.recv();
|
||||
let parent_result_chan: Sender<int> = start_port.recv();
|
||||
|
||||
let child_sum_ports: ~[Port<int>] =
|
||||
let child_sum_ports: ~[Receiver<int>] =
|
||||
child_start_chans.move_iter().map(|child_start_chan| {
|
||||
let (child_sum_port, child_sum_chan) = stream::<int>();
|
||||
child_start_chan.send(child_sum_chan);
|
||||
|
@ -9,9 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
let x = Some(p);
|
||||
c.send(false);
|
||||
let (tx, rx) = channel();
|
||||
let x = Some(rx);
|
||||
tx.send(false);
|
||||
match x {
|
||||
Some(z) if z.recv() => { fail!() }, //~ ERROR cannot bind by-move into a pattern guard
|
||||
Some(z) => { assert!(!z.recv()); },
|
||||
|
@ -65,4 +65,4 @@ fn assign3<'a>(x: &'a mut Own<int>) {
|
||||
**x = 3;
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
pub fn main() {}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// to use capabilities granted by builtin kinds as supertraits.
|
||||
|
||||
trait Foo : Freeze {
|
||||
fn foo(self, mut chan: Chan<Self>) {
|
||||
fn foo(self, mut chan: Sender<Self>) {
|
||||
chan.send(self); //~ ERROR does not fulfill `Send`
|
||||
}
|
||||
}
|
||||
@ -20,7 +20,7 @@ trait Foo : Freeze {
|
||||
impl <T: Freeze> Foo for T { }
|
||||
|
||||
fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
1193182.foo(c);
|
||||
assert!(p.recv() == 1193182);
|
||||
let (tx, rx) = channel();
|
||||
1193182.foo(tx);
|
||||
assert!(rx.recv() == 1193182);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
fn test<T: Freeze>() {}
|
||||
|
||||
fn main() {
|
||||
test::<Chan<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
test::<Port<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
test::<Chan<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
test::<Receiver<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Freeze`
|
||||
}
|
||||
|
@ -21,4 +21,4 @@ extern {
|
||||
fn this_is_actually_ok(a: uint);
|
||||
fn and_so_is_this(_: uint);
|
||||
}
|
||||
fn main() {}
|
||||
fn main() {}
|
||||
|
@ -27,6 +27,6 @@ fn foo(i:int, j: @~str) -> foo {
|
||||
|
||||
fn main() {
|
||||
let cat = ~"kitty";
|
||||
let (_, ch) = Chan::new(); //~ ERROR does not fulfill `Send`
|
||||
ch.send(foo(42, @(cat))); //~ ERROR does not fulfill `Send`
|
||||
let (tx, _) = channel(); //~ ERROR does not fulfill `Send`
|
||||
tx.send(foo(42, @(cat))); //~ ERROR does not fulfill `Send`
|
||||
}
|
||||
|
@ -67,4 +67,4 @@ fn main() {
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn zzz() { () }
|
||||
fn zzz() { () }
|
||||
|
@ -20,12 +20,12 @@ trait Foo : Bar { }
|
||||
impl <T: Send> Foo for T { }
|
||||
impl <T: Send> Bar for T { }
|
||||
|
||||
fn foo<T: Foo>(val: T, chan: Chan<T>) {
|
||||
fn foo<T: Foo>(val: T, chan: Sender<T>) {
|
||||
chan.send(val);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
foo(31337, c);
|
||||
assert!(p.recv() == 31337);
|
||||
let (tx, rx) = channel();
|
||||
foo(31337, tx);
|
||||
assert!(rx.recv() == 31337);
|
||||
}
|
||||
|
@ -24,12 +24,12 @@ struct X<T>(T);
|
||||
impl <T: Freeze> RequiresFreeze for X<T> { }
|
||||
impl <T: Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { }
|
||||
|
||||
fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: Chan<T>) {
|
||||
fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: Sender<T>) {
|
||||
chan.send(val);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
foo(X(31337), c);
|
||||
assert!(p.recv() == X(31337));
|
||||
let (tx, rx) = channel();
|
||||
foo(X(31337), tx);
|
||||
assert!(rx.recv() == X(31337));
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ trait Foo : Send { }
|
||||
|
||||
impl <T: Send> Foo for T { }
|
||||
|
||||
fn foo<T: Foo>(val: T, chan: Chan<T>) {
|
||||
fn foo<T: Foo>(val: T, chan: Sender<T>) {
|
||||
chan.send(val);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
foo(31337, c);
|
||||
assert!(p.recv() == 31337);
|
||||
let (tx, rx) = channel();
|
||||
foo(31337, tx);
|
||||
assert!(rx.recv() == 31337);
|
||||
}
|
||||
|
@ -12,15 +12,15 @@
|
||||
// capabilities granted by builtin kinds as supertraits.
|
||||
|
||||
trait Foo : Send {
|
||||
fn foo(self, chan: Chan<Self>) {
|
||||
chan.send(self);
|
||||
fn foo(self, tx: Sender<Self>) {
|
||||
tx.send(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: Send> Foo for T { }
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
1193182.foo(c);
|
||||
assert!(p.recv() == 1193182);
|
||||
let (tx, rx) = channel();
|
||||
1193182.foo(tx);
|
||||
assert!(rx.recv() == 1193182);
|
||||
}
|
||||
|
@ -26,12 +26,12 @@
|
||||
|
||||
use std::task;
|
||||
|
||||
fn foo(x: ()) -> Port<()> {
|
||||
let (p, c) = Chan::<()>::new();
|
||||
fn foo(x: ()) -> Receiver<()> {
|
||||
let (tx, rx) = channel::<()>();
|
||||
task::spawn(proc() {
|
||||
c.send(x);
|
||||
tx.send(x);
|
||||
});
|
||||
p
|
||||
rx
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -16,7 +16,7 @@
|
||||
extern crate native;
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{PortReader, ChanWriter};
|
||||
use std::io::{ChanReader, ChanWriter};
|
||||
use std::logging::{set_logger, Logger};
|
||||
|
||||
struct MyWriter(ChanWriter);
|
||||
@ -36,8 +36,8 @@ fn start(argc: int, argv: **u8) -> int {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (p, c) = Chan::new();
|
||||
let (mut r, w) = (PortReader::new(p), ChanWriter::new(c));
|
||||
let (tx, rx) = channel();
|
||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
||||
spawn(proc() {
|
||||
set_logger(~MyWriter(w) as ~Logger);
|
||||
debug!("debug");
|
||||
|
@ -15,9 +15,9 @@ fn foo(blk: proc()) {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
foo(proc() {
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
@ -11,15 +11,15 @@
|
||||
use std::task;
|
||||
|
||||
pub fn main() {
|
||||
let (p, ch) = Chan::new();
|
||||
let _t = task::spawn(proc() { child(&ch) });
|
||||
let y = p.recv();
|
||||
let (tx, rx) = channel();
|
||||
let _t = task::spawn(proc() { child(&tx) });
|
||||
let y = rx.recv();
|
||||
error!("received");
|
||||
error!("{:?}", y);
|
||||
assert_eq!(y, 10);
|
||||
}
|
||||
|
||||
fn child(c: &Chan<int>) {
|
||||
fn child(c: &Sender<int>) {
|
||||
error!("sending");
|
||||
c.send(10);
|
||||
error!("value sent");
|
||||
|
@ -31,9 +31,9 @@ mod map_reduce {
|
||||
|
||||
pub type mapper = extern fn(~str, putter);
|
||||
|
||||
enum ctrl_proto { find_reducer(~[u8], Chan<int>), mapper_done, }
|
||||
enum ctrl_proto { find_reducer(~[u8], Sender<int>), mapper_done, }
|
||||
|
||||
fn start_mappers(ctrl: Chan<ctrl_proto>, inputs: ~[~str]) {
|
||||
fn start_mappers(ctrl: Sender<ctrl_proto>, inputs: ~[~str]) {
|
||||
for i in inputs.iter() {
|
||||
let ctrl = ctrl.clone();
|
||||
let i = i.clone();
|
||||
@ -41,20 +41,20 @@ mod map_reduce {
|
||||
}
|
||||
}
|
||||
|
||||
fn map_task(ctrl: Chan<ctrl_proto>, input: ~str) {
|
||||
fn map_task(ctrl: Sender<ctrl_proto>, input: ~str) {
|
||||
let mut intermediates = HashMap::new();
|
||||
|
||||
fn emit(im: &mut HashMap<~str, int>,
|
||||
ctrl: Chan<ctrl_proto>, key: ~str,
|
||||
ctrl: Sender<ctrl_proto>, key: ~str,
|
||||
_val: ~str) {
|
||||
if im.contains_key(&key) {
|
||||
return;
|
||||
}
|
||||
let (pp, cc) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
error!("sending find_reducer");
|
||||
ctrl.send(find_reducer(key.as_bytes().to_owned(), cc));
|
||||
ctrl.send(find_reducer(key.as_bytes().to_owned(), tx));
|
||||
error!("receiving");
|
||||
let c = pp.recv();
|
||||
let c = rx.recv();
|
||||
error!("{:?}", c);
|
||||
im.insert(key, c);
|
||||
}
|
||||
@ -65,7 +65,7 @@ mod map_reduce {
|
||||
}
|
||||
|
||||
pub fn map_reduce(inputs: ~[~str]) {
|
||||
let (ctrl_port, ctrl_chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// This task becomes the master control task. It spawns others
|
||||
// to do the rest.
|
||||
@ -74,12 +74,12 @@ mod map_reduce {
|
||||
|
||||
reducers = HashMap::new();
|
||||
|
||||
start_mappers(ctrl_chan, inputs.clone());
|
||||
start_mappers(tx, inputs.clone());
|
||||
|
||||
let mut num_mappers = inputs.len() as int;
|
||||
|
||||
while num_mappers > 0 {
|
||||
match ctrl_port.recv() {
|
||||
match rx.recv() {
|
||||
mapper_done => { num_mappers -= 1; }
|
||||
find_reducer(k, cc) => {
|
||||
let mut c;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
extern crate extra;
|
||||
|
||||
use std::comm::Chan;
|
||||
use std::task;
|
||||
|
||||
type RingBuffer = ~[f64];
|
||||
@ -21,7 +20,7 @@ enum Msg
|
||||
GetSamples(~str, SamplesFn), // sample set name, callback which receives samples
|
||||
}
|
||||
|
||||
fn foo(name: ~str, samples_chan: Chan<Msg>) {
|
||||
fn foo(name: ~str, samples_chan: Sender<Msg>) {
|
||||
task::spawn(proc() {
|
||||
let mut samples_chan = samples_chan;
|
||||
let callback: SamplesFn = proc(buffer) {
|
||||
|
@ -11,11 +11,11 @@
|
||||
use std::io::println;
|
||||
|
||||
pub fn main() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
println(port.recv());
|
||||
println(rx.recv());
|
||||
});
|
||||
|
||||
chan.send("hello, world");
|
||||
tx.send("hello, world");
|
||||
}
|
||||
|
@ -11,11 +11,11 @@
|
||||
use std::task;
|
||||
|
||||
pub fn main() {
|
||||
let (port, chan) = Chan::<&'static str>::new();
|
||||
let (tx, rx) = channel::<&'static str>();
|
||||
|
||||
task::spawn(proc() {
|
||||
assert_eq!(port.recv(), "hello, world");
|
||||
assert_eq!(rx.recv(), "hello, world");
|
||||
});
|
||||
|
||||
chan.send("hello, world");
|
||||
tx.send("hello, world");
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ use std::comm;
|
||||
use std::io::timer::Timer;
|
||||
|
||||
pub fn main() {
|
||||
let (port, chan) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc (){
|
||||
let mut timer = Timer::new().unwrap();
|
||||
timer.sleep(10);
|
||||
chan.send(());
|
||||
tx.send(());
|
||||
});
|
||||
loop {
|
||||
match port.try_recv() {
|
||||
match rx.try_recv() {
|
||||
comm::Data(()) => break,
|
||||
comm::Empty => {}
|
||||
comm::Disconnected => unreachable!()
|
||||
|
@ -10,17 +10,17 @@
|
||||
|
||||
use std::task;
|
||||
|
||||
fn producer(c: &Chan<~[u8]>) {
|
||||
c.send(
|
||||
fn producer(tx: &Sender<~[u8]>) {
|
||||
tx.send(
|
||||
~[1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8,
|
||||
13u8]);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p, ch) = Chan::<~[u8]>::new();
|
||||
let (tx, rx) = channel::<~[u8]>();
|
||||
let _prod = task::spawn(proc() {
|
||||
producer(&ch)
|
||||
producer(&tx)
|
||||
});
|
||||
|
||||
let _data: ~[u8] = p.recv();
|
||||
let _data: ~[u8] = rx.recv();
|
||||
}
|
||||
|
@ -26,13 +26,13 @@ impl fmt::Show for Foo {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p,c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut f = Foo(Cell::new(0));
|
||||
debug!("{}", f);
|
||||
let Foo(ref mut f) = f;
|
||||
assert!(f.get() == 1);
|
||||
c.send(());
|
||||
tx.send(());
|
||||
});
|
||||
p.recv();
|
||||
rx.recv();
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ extern crate extra;
|
||||
use std::comm;
|
||||
use extra::comm;
|
||||
|
||||
fn starve_main(alive: Port<int>) {
|
||||
fn starve_main(alive: Receiver<int>) {
|
||||
info!("signalling main");
|
||||
alive.recv();
|
||||
info!("starving main");
|
||||
|
@ -25,14 +25,14 @@ fn test(f: int) -> test {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p, c) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
task::spawn(proc() {
|
||||
let (pp, cc) = Chan::new();
|
||||
c.send(cc);
|
||||
let (tx2, rx2) = channel();
|
||||
tx.send(tx2);
|
||||
|
||||
let _r = pp.recv();
|
||||
let _r = rx2.recv();
|
||||
});
|
||||
|
||||
p.recv().send(test(42));
|
||||
rx.recv().send(test(42));
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ struct Command<K, V> {
|
||||
val: V
|
||||
}
|
||||
|
||||
fn cache_server<K:Send,V:Send>(mut c: Chan<Chan<Command<K, V>>>) {
|
||||
let (_ctrl_port, ctrl_chan) = Chan::new();
|
||||
c.send(ctrl_chan);
|
||||
fn cache_server<K:Send,V:Send>(mut tx: Sender<Sender<Command<K, V>>>) {
|
||||
let (tx1, _rx) = channel();
|
||||
tx.send(tx1);
|
||||
}
|
||||
pub fn main() { }
|
||||
|
@ -23,6 +23,6 @@ fn foo(i:int, j: char) -> foo {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (_po, ch) = Chan::new();
|
||||
ch.send(foo(42, 'c'));
|
||||
let (tx, rx) = channel();
|
||||
tx.send(foo(42, 'c'));
|
||||
}
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
use std::task;
|
||||
|
||||
type ctx = Chan<int>;
|
||||
type ctx = Sender<int>;
|
||||
|
||||
fn iotask(_cx: &ctx, ip: ~str) {
|
||||
fn iotask(_tx: &ctx, ip: ~str) {
|
||||
assert_eq!(ip, ~"localhost");
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (_p, ch) = Chan::<int>::new();
|
||||
task::spawn(proc() iotask(&ch, ~"localhost") );
|
||||
let (tx, _rx) = channel::<int>();
|
||||
task::spawn(proc() iotask(&tx, ~"localhost") );
|
||||
}
|
||||
|
@ -16,23 +16,23 @@ use std::task;
|
||||
|
||||
pub fn main() { test05(); }
|
||||
|
||||
fn test05_start(ch : &Chan<int>) {
|
||||
ch.send(10);
|
||||
fn test05_start(tx : &Sender<int>) {
|
||||
tx.send(10);
|
||||
error!("sent 10");
|
||||
ch.send(20);
|
||||
tx.send(20);
|
||||
error!("sent 20");
|
||||
ch.send(30);
|
||||
tx.send(30);
|
||||
error!("sent 30");
|
||||
}
|
||||
|
||||
fn test05() {
|
||||
let (po, ch) = Chan::new();
|
||||
task::spawn(proc() { test05_start(&ch) });
|
||||
let mut value: int = po.recv();
|
||||
let (tx, rx) = channel();
|
||||
task::spawn(proc() { test05_start(&tx) });
|
||||
let mut value: int = rx.recv();
|
||||
error!("{}", value);
|
||||
value = po.recv();
|
||||
value = rx.recv();
|
||||
error!("{}", value);
|
||||
value = po.recv();
|
||||
value = rx.recv();
|
||||
error!("{}", value);
|
||||
assert_eq!(value, 30);
|
||||
}
|
||||
|
@ -14,25 +14,25 @@ extern crate extra;
|
||||
|
||||
use std::task;
|
||||
|
||||
fn start(c: &Chan<Chan<~str>>) {
|
||||
let (p, ch) = Chan::new();
|
||||
c.send(ch);
|
||||
fn start(tx: &Sender<Sender<~str>>) {
|
||||
let (tx2, rx) = channel();
|
||||
tx.send(tx2);
|
||||
|
||||
let mut a;
|
||||
let mut b;
|
||||
a = p.recv();
|
||||
a = rx.recv();
|
||||
assert!(a == ~"A");
|
||||
error!("{:?}", a);
|
||||
b = p.recv();
|
||||
b = rx.recv();
|
||||
assert!(b == ~"B");
|
||||
error!("{:?}", b);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (p, ch) = Chan::new();
|
||||
let _child = task::spawn(proc() { start(&ch) });
|
||||
let (tx, rx) = channel();
|
||||
let _child = task::spawn(proc() { start(&tx) });
|
||||
|
||||
let mut c = p.recv();
|
||||
let mut c = rx.recv();
|
||||
c.send(~"A");
|
||||
c.send(~"B");
|
||||
task::deschedule();
|
||||
|
@ -14,15 +14,15 @@ extern crate extra;
|
||||
|
||||
use std::task;
|
||||
|
||||
fn start(c: &Chan<Chan<int>>) {
|
||||
let (_p, ch) = Chan::new();
|
||||
c.send(ch);
|
||||
fn start(tx: &Sender<Sender<int>>) {
|
||||
let (tx2, _rx) = channel();
|
||||
tx.send(tx2);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let (mut p, ch) = Chan::new();
|
||||
let (tx, rx) = channel();
|
||||
let _child = task::spawn(proc() {
|
||||
start(&ch)
|
||||
start(&tx)
|
||||
});
|
||||
let _c = p.recv();
|
||||
let _tx = rx.recv();
|
||||
}
|
||||
|
@ -14,14 +14,14 @@ extern crate extra;
|
||||
|
||||
use std::task;
|
||||
|
||||
fn start(c: &Chan<int>, start: int, number_of_messages: int) {
|
||||
fn start(tx: &Sender<int>, start: int, number_of_messages: int) {
|
||||
let mut i: int = 0;
|
||||
while i < number_of_messages { c.send(start + i); i += 1; }
|
||||
while i < number_of_messages { tx.send(start + i); i += 1; }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
info!("Check that we don't deadlock.");
|
||||
let (_p, ch) = Chan::new();
|
||||
task::try(proc() { start(&ch, 0, 10) });
|
||||
let (tx, rx) = channel();
|
||||
task::try(proc() { start(&tx, 0, 10) });
|
||||
info!("Joined task");
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user