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