v / vlib / sync
Raw file | 122 loc (116 sloc) | 1.97 KB | Latest commit hash e81e0ac70
1import time
2import sync
3
4struct St {
5 a int
6}
7
8fn getint() int {
9 return 8
10}
11
12fn 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
43fn 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
63fn 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}