| 1 | import time |
| 2 | import sync |
| 3 | |
| 4 | struct St { |
| 5 | a int |
| 6 | } |
| 7 | |
| 8 | fn getint() int { |
| 9 | return 8 |
| 10 | } |
| 11 | |
| 12 | fn f1(ch1 chan int, ch2 chan St, ch3 chan int, ch4 chan int, ch5 chan int, sem sync.Semaphore) { |
| 13 | mut a := 5 |
| 14 | select { |
| 15 | // pre comment |
| 16 | a = <-ch3 { |
| 17 | a = 0 |
| 18 | } |
| 19 | b := <-ch2 { |
| 20 | a = b.a |
| 21 | } |
| 22 | ch3 <- 5 { |
| 23 | a = 1 |
| 24 | } |
| 25 | ch2 <- St{ |
| 26 | a: 37 |
| 27 | } { |
| 28 | a = 2 |
| 29 | } |
| 30 | // another comment |
| 31 | ch4 <- (6 + 7 * 9) { |
| 32 | a = 8 |
| 33 | } |
| 34 | ch5 <- getint() { |
| 35 | a = 9 |
| 36 | } |
| 37 | 300 * time.millisecond { |
| 38 | a = 3 |
| 39 | } |
| 40 | // post comment |
| 41 | } |
| 42 | assert a == 3 |
| 43 | sem.post() |
| 44 | } |
| 45 | |
| 46 | fn f2(ch1 chan St, ch2 chan int, sem sync.Semaphore) { |
| 47 | mut r := 23 |
| 48 | for i in 0 .. 2 { |
| 49 | select { |
| 50 | b := <-ch1 { |
| 51 | r = b.a |
| 52 | } |
| 53 | ch2 <- r { |
| 54 | r = 17 |
| 55 | } |
| 56 | } |
| 57 | if i == 0 { |
| 58 | assert r == 17 |
| 59 | } else { |
| 60 | assert r == 13 |
| 61 | } |
| 62 | } |
| 63 | sem.post() |
| 64 | } |
| 65 | |
| 66 | fn test_select_blocks() { |
| 67 | ch1 := chan int{cap: 1} |
| 68 | ch2 := chan St{} |
| 69 | ch3 := chan int{} |
| 70 | ch4 := chan int{} |
| 71 | ch5 := chan int{} |
| 72 | sem := sync.new_semaphore() |
| 73 | mut r := false |
| 74 | t := select { |
| 75 | b := <-ch1 { |
| 76 | println(b) |
| 77 | } |
| 78 | else { |
| 79 | // no channel ready |
| 80 | r = true |
| 81 | } |
| 82 | } |
| 83 | assert r == true |
| 84 | assert t == true |
| 85 | spawn f2(ch2, ch3, sem) |
| 86 | n := <-ch3 |
| 87 | assert n == 23 |
| 88 | ch2 <- St{ |
| 89 | a: 13 |
| 90 | } |
| 91 | sem.wait() |
| 92 | stopwatch := time.new_stopwatch() |
| 93 | spawn f1(ch1, ch2, ch3, ch4, ch5, sem) |
| 94 | sem.wait() |
| 95 | elapsed_ms := f64(stopwatch.elapsed()) / time.millisecond |
| 96 | assert elapsed_ms >= 295.0 |
| 97 | ch1.close() |
| 98 | ch2.close() |
| 99 | mut h := 7 |
| 100 | mut is_open := true |
| 101 | if select { |
| 102 | b := <-ch2 { |
| 103 | h = 0 |
| 104 | } |
| 105 | ch1 <- h { |
| 106 | h = 1 |
| 107 | } |
| 108 | else { |
| 109 | h = 2 |
| 110 | } |
| 111 | } { |
| 112 | panic('channel is still open') |
| 113 | } else { |
| 114 | is_open = false |
| 115 | } |
| 116 | // no branch should have run |
| 117 | for select { |
| 118 | b := <-ch2 { |
| 119 | h = 0 |
| 120 | } |
| 121 | } { |
| 122 | println('ch2 open') |
| 123 | } |
| 124 | println('ch2 closed') |
| 125 | assert h == 7 |
| 126 | // since all channels are closed `select` should return `false` |
| 127 | assert is_open == false |
| 128 | } |
| 129 | |