| 1 | // vtest retry: 5 |
| 2 | |
| 3 | // This test case runs concurrent 3 instances of `do_select` that |
| 4 | // communicate with 6 other threads doing send and receive operations. |
| 5 | // There are buffered and unbuffered channels - handled by one or two |
| 6 | // concurrend threads on the other side |
| 7 | |
| 8 | fn do_select(ch1 chan int, ch2 chan int, chf1 chan f64, chf2 chan f64, sumch1 chan i64, sumch2 chan i64) { |
| 9 | mut sum1 := i64(0) |
| 10 | mut sum2 := i64(0) |
| 11 | f1 := 17.0 |
| 12 | f2 := 7.0 |
| 13 | for _ in 0 .. 20000 + chf1.cap / 3 { |
| 14 | select { |
| 15 | chf1 <- f1 {} |
| 16 | i := <-ch1 { |
| 17 | sum1 += i |
| 18 | } |
| 19 | j := <-ch2 { |
| 20 | sum2 += j |
| 21 | } |
| 22 | chf2 <- f2 {} |
| 23 | } |
| 24 | } |
| 25 | sumch1 <- sum1 |
| 26 | sumch2 <- sum2 |
| 27 | } |
| 28 | |
| 29 | fn do_send_int(ch chan int, factor int) { |
| 30 | for i in 0 .. 10000 { |
| 31 | ch <- (i * factor) |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | fn do_rec_f64(ch chan f64, sumch chan f64) { |
| 36 | mut sum := 0.0 |
| 37 | for _ in 0 .. 10000 { |
| 38 | sum += <-ch |
| 39 | } |
| 40 | sumch <- sum |
| 41 | } |
| 42 | |
| 43 | fn test_select() { |
| 44 | ch1 := chan int{cap: 3} |
| 45 | ch2 := chan int{} |
| 46 | // buffer length of chf1 mus be multiple of 3 (# select threads) |
| 47 | chf1 := chan f64{cap: 30} |
| 48 | chf2 := chan f64{} |
| 49 | chsum1 := chan i64{} |
| 50 | chsum2 := chan i64{} |
| 51 | chsumf1 := chan f64{} |
| 52 | chsumf2 := chan f64{} |
| 53 | spawn do_send_int(ch1, 3) |
| 54 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
| 55 | spawn do_rec_f64(chf1, chsumf1) |
| 56 | spawn do_rec_f64(chf2, chsumf2) |
| 57 | spawn do_rec_f64(chf2, chsumf2) |
| 58 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
| 59 | spawn do_send_int(ch2, 7) |
| 60 | spawn do_send_int(ch2, 17) |
| 61 | spawn do_select(ch1, ch2, chf1, chf2, chsum1, chsum2) |
| 62 | |
| 63 | sum1 := <-chsum1 + <-chsum1 + <-chsum1 |
| 64 | sum2 := <-chsum2 + <-chsum2 + <-chsum2 |
| 65 | mut sumf1 := <-chsumf1 |
| 66 | // empty channel buffer |
| 67 | for _ in 0 .. chf1.cap { |
| 68 | sumf1 += <-chf1 |
| 69 | } |
| 70 | sumf2 := <-chsumf2 + <-chsumf2 |
| 71 | // Use Gauß' formula |
| 72 | expected_sum := i64(10000) * (10000 - 1) / 2 |
| 73 | assert sum1 == 3 * expected_sum |
| 74 | assert sum2 == (7 + 17) * expected_sum |
| 75 | assert sumf1 == 17.0 * f64(10000 + chf1.cap) |
| 76 | assert sumf2 == 7.0 * 20000 |
| 77 | } |
| 78 | |