You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

73 lines
2.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//! Using `select!` to send and receive on the same channel at the same time.
//!
//! This example is based on the following program in Go.
//!
//! Source:
//! - https://web.archive.org/web/20171209034309/https://www.nada.kth.se/~snilsson/concurrency
//! - http://www.nada.kth.se/~snilsson/concurrency/src/matching.go
//!
//! Copyright & License:
//! - Stefan Nilsson
//! - Creative Commons Attribution 3.0 Unported License
//! - https://creativecommons.org/licenses/by/3.0/
//!
//! ```go
//! func main() {
//! people := []string{"Anna", "Bob", "Cody", "Dave", "Eva"}
//! match := make(chan string, 1) // Make room for one unmatched send.
//! wg := new(sync.WaitGroup)
//! for _, name := range people {
//! wg.Add(1)
//! go Seek(name, match, wg)
//! }
//! wg.Wait()
//! select {
//! case name := <-match:
//! fmt.Printf("No one received %ss message.\n", name)
//! default:
//! // There was no pending send operation.
//! }
//! }
//!
//! // Seek either sends or receives, whichever possible, a name on the match
//! // channel and notifies the wait group when done.
//! func Seek(name string, match chan string, wg *sync.WaitGroup) {
//! select {
//! case peer := <-match:
//! fmt.Printf("%s received a message from %s.\n", name, peer)
//! case match <- name:
//! // Wait for someone to receive my message.
//! }
//! wg.Done()
//! }
//! ```
use crossbeam_channel::{bounded, select};
use crossbeam_utils::thread;
fn main() {
let people = vec!["Anna", "Bob", "Cody", "Dave", "Eva"];
let (s, r) = bounded(1); // Make room for one unmatched send.
// Either send my name into the channel or receive someone else's, whatever happens first.
let seek = |name, s, r| {
select! {
recv(r) -> peer => println!("{} received a message from {}.", name, peer.unwrap()),
send(s, name) -> _ => {}, // Wait for someone to receive my message.
}
};
thread::scope(|scope| {
for name in people {
let (s, r) = (s.clone(), r.clone());
scope.spawn(move |_| seek(name, s, r));
}
})
.unwrap();
// Check if there is a pending send operation.
if let Ok(name) = r.try_recv() {
println!("No one received {}s message.", name);
}
}