aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/old/vlib/sync/channel_select_3_test.v
blob: fdf609659de30dcea6120525aef6ec7baaf7e95a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import time
import sync

struct St {
	a int
}

fn getint() int {
	return 8
}

fn f1(ch1 chan int, ch2 chan St, ch3 chan int, ch4 chan int, ch5 chan int, mut sem sync.Semaphore) {
	mut a := 5
	select {
		a = <-ch3 {
			a = 0
		}
		b := <-ch2 {
			a = b.a
		}
		ch3 <- 5 {
			a = 1
		}
		ch2 <- St{
			a: 37
		} {
			a = 2
		}
		ch4 <- (6 + 7 * 9) {
			a = 8
		}
		ch5 <- getint() {
			a = 9
		}
		300 * time.millisecond {
			a = 3
		}
	}
	assert a == 3
	sem.post()
}

fn f2(ch1 chan St, ch2 chan int, mut sem sync.Semaphore) {
	mut r := 23
	for i in 0 .. 2 {
		select {
			b := <-ch1 {
				r = b.a
			}
			ch2 <- r {
				r = 17
			}
		}
		if i == 0 {
			assert r == 17
		} else {
			assert r == 13
		}
	}
	sem.post()
}

fn test_select_blocks() {
	ch1 := chan int{cap: 1}
	ch2 := chan St{}
	ch3 := chan int{}
	ch4 := chan int{}
	ch5 := chan int{}
	mut sem := sync.new_semaphore()
	mut r := false
	t := select {
		b := <-ch1 {
			println(b)
		}
		else {
			// no channel ready
			r = true
		}
	}
	assert r == true
	assert t == true
	go f2(ch2, ch3, mut sem)
	n := <-ch3
	assert n == 23
	ch2 <- St{
		a: 13
	}
	sem.wait()
	stopwatch := time.new_stopwatch()
	go f1(ch1, ch2, ch3, ch4, ch5, mut sem)
	sem.wait()
	elapsed_ms := f64(stopwatch.elapsed()) / time.millisecond
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/high-resolution-timers
	// > For example, for Windows running on an x86 processor, the default interval between
	// > system clock ticks is typically about 15 milliseconds, and the minimum interval
	// > between system clock ticks is about 1 millisecond.
	assert elapsed_ms >= 280.0 // 300 - (15ms + 5ms just in case)

	ch1.close()
	ch2.close()
	mut h := 7
	mut is_open := true
	if select {
		_ := <-ch2 {
			h = 0
		}
		ch1 <- h {
			h = 1
		}
		else {
			h = 2
		}
	} {
		panic('channel is still open')
	} else {
		is_open = false
	}
	// no branch should have run
	assert h == 7
	// since all channels are closed `select` should return `false`
	assert is_open == false
}