123 lines
1.9 KiB
V
123 lines
1.9 KiB
V
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, 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, 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{}
|
|
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, sem)
|
|
n := <-ch3
|
|
assert n == 23
|
|
ch2 <- St{
|
|
a: 13
|
|
}
|
|
sem.wait()
|
|
stopwatch := time.new_stopwatch({})
|
|
go f1(ch1, ch2, ch3, ch4, ch5, 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
|
|
}
|