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, mut sem sync.Semaphore) { |
13 | mut a := 5 |
14 | select { |
15 | a = <-ch3 { |
16 | a = 0 |
17 | } |
18 | b := <-ch2 { |
19 | a = b.a |
20 | } |
21 | ch3 <- 5 { |
22 | a = 1 |
23 | } |
24 | ch2 <- St{ |
25 | a: 37 |
26 | } { |
27 | a = 2 |
28 | } |
29 | ch4 <- (6 + 7 * 9) { |
30 | a = 8 |
31 | } |
32 | ch5 <- getint() { |
33 | a = 9 |
34 | } |
35 | 300 * time.millisecond { |
36 | a = 3 |
37 | } |
38 | } |
39 | assert a == 3 |
40 | sem.post() |
41 | } |
42 | |
43 | fn f2(ch1 chan St, ch2 chan int, mut sem sync.Semaphore) { |
44 | mut r := 23 |
45 | for i in 0 .. 2 { |
46 | select { |
47 | b := <-ch1 { |
48 | r = b.a |
49 | } |
50 | ch2 <- r { |
51 | r = 17 |
52 | } |
53 | } |
54 | if i == 0 { |
55 | assert r == 17 |
56 | } else { |
57 | assert r == 13 |
58 | } |
59 | } |
60 | sem.post() |
61 | } |
62 | |
63 | fn test_select_blocks() { |
64 | ch1 := chan int{cap: 1} |
65 | ch2 := chan St{} |
66 | ch3 := chan int{} |
67 | ch4 := chan int{} |
68 | ch5 := chan int{} |
69 | mut sem := sync.new_semaphore() |
70 | mut r := false |
71 | t := select { |
72 | b := <-ch1 { |
73 | println(b) |
74 | } |
75 | else { |
76 | // no channel ready |
77 | r = true |
78 | } |
79 | } |
80 | assert r == true |
81 | assert t == true |
82 | spawn f2(ch2, ch3, mut sem) |
83 | n := <-ch3 |
84 | assert n == 23 |
85 | ch2 <- St{ |
86 | a: 13 |
87 | } |
88 | sem.wait() |
89 | stopwatch := time.new_stopwatch() |
90 | spawn f1(ch1, ch2, ch3, ch4, ch5, mut sem) |
91 | sem.wait() |
92 | elapsed_ms := f64(stopwatch.elapsed()) / time.millisecond |
93 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/high-resolution-timers |
94 | // > For example, for Windows running on an x86 processor, the default interval between |
95 | // > system clock ticks is typically about 15 milliseconds, and the minimum interval |
96 | // > between system clock ticks is about 1 millisecond. |
97 | assert elapsed_ms >= 280.0 // 300 - (15ms + 5ms just in case) |
98 | |
99 | ch1.close() |
100 | ch2.close() |
101 | mut h := 7 |
102 | mut is_open := true |
103 | if select { |
104 | _ := <-ch2 { |
105 | h = 0 |
106 | } |
107 | ch1 <- h { |
108 | h = 1 |
109 | } |
110 | else { |
111 | h = 2 |
112 | } |
113 | } { |
114 | panic('channel is still open') |
115 | } else { |
116 | is_open = false |
117 | } |
118 | // no branch should have run |
119 | assert h == 7 |
120 | // since all channels are closed `select` should return `false` |
121 | assert is_open == false |
122 | } |