Module ergo_sync::ch
[−]
[src]
Module for working with channels. Rexport of crossbeam_channel
Examples
Several of these examples are copies of the
chan
andcrossbeam_channel
crates.
Example: unbounded (async) channel
#[macro_use] extern crate ergo_sync; use ergo_sync::*; let (tx, rx) = ch::unbounded(); // Can send an arbitrarily large number of messages. for i in 0..1000 { ch!(tx <- i); }
Example: bounded (sync) channel
#[macro_use] extern crate ergo_sync; use ergo_sync::*; // Create a channel that can hold at most 5 messages at a time. let (tx, rx) = ch::bounded(5); // Can send only 5 messages. for i in 0..5 { ch!(tx <- i); } // An attempt to send one more message will fail. assert!(tx.try_send(5).is_err());
Example: rendevous channel
#[macro_use] extern crate ergo_sync; use ergo_sync::*; let (send, recv) = ch::bounded(0); spawn(move || ch!(send <- 5)); assert_eq!(ch!(<- recv), 5); // blocks until the previous send occurs
Example: the sentinel channel idiom
When writing concurrent programs with ergo
, you will often find that you need
to somehow "wait" until some operation is done. For example, let's say you want
to run a function in a separate thread, but wait until it completes. Here's
one way to do it:
#[macro_use] extern crate ergo_sync; use ergo_sync::*; fn do_work(done: ch::Sender<()>) { // do something // signal that we're done. ch!(done <- ()); } fn main() { let (sdone, rdone) = ch::bounded(0); spawn(move || do_work(sdone)); // block until work is done, and then quit the program. ch!(<- rdone); }
In effect, we've created a new channel that sends unit values. When we're
done doing work, we send a unit value and main
waits for it to be delivered.
Another way of achieving the same thing is to simply close the channel. Once the channel is closed, any previously blocked receive operations become immediately unblocked. What's even cooler is that channels are closed automatically when all senders are dropped. So the new program looks something like this:
#[macro_use] extern crate ergo_sync; use ergo_sync::*; fn do_work(_done: ch::Sender<()>) { // do something } fn main() { let (sdone, rdone) = ch::bounded(0); spawn(move || do_work(sdone)); // Block until the channel is closed. // // Note: this _expects_ the error that // all senders have been dropped and will // panic if a value is sent instead. ch!(! <- rdone); }
We no longer need to explicitly do anything with the _done
channel. We give
do_work
ownership of the channel, but as soon as the function stops
executing, _done
is dropped, the channel is closed and rdone.recv()
unblocks returning an error, which we expect with ch!(! <- rdone)
.
Example: non-blocking sends/receives
#[macro_use] extern crate ergo_sync; use ergo_sync::*; let (send, recv) = ch::bounded(1); let data = "send data".to_string(); match ch!(send <-? data) { Some(data) => { println!("didn't send data, but got it back: {}", data); unreachable!(); // in this case we don't expect it } None => println!("message sent successfully"), } // attempting to send additional data fails let data = "more data".to_string(); assert_eq!(Some(data.clone()), ch!(send <-? data)); match ch!(<-? recv) { Some(data) => println!("received data: {}", data), None => { println!("didn't receive any data yet"); unreachable!(); // in this case we don't expect it } }
Example: using select_loop
#[macro_use] extern crate ergo_sync; use ergo_sync::*; let (tx1, rx1) = ch::unbounded(); let (tx2, rx2) = ch::unbounded(); spawn(move || ch!(tx1 <- "foo")); spawn(move || ch!(tx2 <- "bar")); select_loop! { recv(rx1, msg) => { println!("Received a message from the first channel: {}", msg); } recv(rx2, msg) => { println!("Received a message from the second channel: {}", msg); } }
Structs
IntoIter |
An owning iterator that waits for messages until the channel is disconnected. |
Iter |
An iterator that waits for messages until the channel is disconnected. |
Receiver |
The receiving half of a channel. |
RecvError |
An error returned from the |
Select |
The dynamic selection interface. |
SelectRecvError |
An error returned from the |
SelectSendError |
An error returned from the |
SendError |
An error returned from the |
Sender |
The sending half of a channel. |
TryIter |
An iterator that receives messages until the channel is empty or disconnected. |
Enums
RecvTimeoutError |
This enumeration is the list of possible errors that made |
SendTimeoutError |
This enumeration is the list of possible errors that made |
TryRecvError |
This enumeration is the list of the possible reasons that |
TrySendError |
This enumeration is the list of the possible error outcomes for the |
Functions
bounded |
Creates a new channel of bounded capacity, returning the sender/receiver halves. |
unbounded |
Creates a new channel of unbounded capacity, returning the sender/receiver halves. |