1 //! Using `select!` to send and receive on the same channel at the same time.
2 //!
3 //! This example is based on the following program in Go.
4 //!
5 //! Source:
6 //!   - https://web.archive.org/web/20171209034309/https://www.nada.kth.se/~snilsson/concurrency
7 //!   - http://www.nada.kth.se/~snilsson/concurrency/src/matching.go
8 //!
9 //! Copyright & License:
10 //!   - Stefan Nilsson
11 //!   - Creative Commons Attribution 3.0 Unported License
12 //!   - https://creativecommons.org/licenses/by/3.0/
13 //!
14 //! ```go
15 //! func main() {
16 //!     people := []string{"Anna", "Bob", "Cody", "Dave", "Eva"}
17 //!     match := make(chan string, 1) // Make room for one unmatched send.
18 //!     wg := new(sync.WaitGroup)
19 //!     for _, name := range people {
20 //!         wg.Add(1)
21 //!         go Seek(name, match, wg)
22 //!     }
23 //!     wg.Wait()
24 //!     select {
25 //!     case name := <-match:
26 //!         fmt.Printf("No one received %s’s message.\n", name)
27 //!     default:
28 //!         // There was no pending send operation.
29 //!     }
30 //! }
31 //!
32 //! // Seek either sends or receives, whichever possible, a name on the match
33 //! // channel and notifies the wait group when done.
34 //! func Seek(name string, match chan string, wg *sync.WaitGroup) {
35 //!     select {
36 //!     case peer := <-match:
37 //!         fmt.Printf("%s received a message from %s.\n", name, peer)
38 //!     case match <- name:
39 //!         // Wait for someone to receive my message.
40 //!     }
41 //!     wg.Done()
42 //! }
43 //! ```
44 
45 #[macro_use]
46 extern crate crossbeam_channel;
47 extern crate crossbeam_utils;
48 
49 use crossbeam_channel::bounded;
50 use crossbeam_utils::thread;
51 
main()52 fn main() {
53     let people = vec!["Anna", "Bob", "Cody", "Dave", "Eva"];
54     let (s, r) = bounded(1); // Make room for one unmatched send.
55 
56     // Either send my name into the channel or receive someone else's, whatever happens first.
57     let seek = |name, s, r| {
58         select! {
59             recv(r) -> peer => println!("{} received a message from {}.", name, peer.unwrap()),
60             send(s, name) -> _ => {}, // Wait for someone to receive my message.
61         }
62     };
63 
64     thread::scope(|scope| {
65         for name in people {
66             let (s, r) = (s.clone(), r.clone());
67             scope.spawn(move |_| seek(name, s, r));
68         }
69     })
70     .unwrap();
71 
72     // Check if there is a pending send operation.
73     if let Ok(name) = r.try_recv() {
74         println!("No one received {}’s message.", name);
75     }
76 }
77