//! 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 %s’s 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); } }