]> Cypherpunks.ru repositories - gostls13.git/blob - test/chan/doubleselect.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / chan / doubleselect.go
1 // run
2
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Test the situation in which two cases of a select can
8 // both end up running. See http://codereview.appspot.com/180068.
9
10 package main
11
12 import (
13         "flag"
14         "runtime"
15 )
16
17 var iterations *int = flag.Int("n", 100000, "number of iterations")
18
19 // sender sends a counter to one of four different channels. If two
20 // cases both end up running in the same iteration, the same value will be sent
21 // to two different channels.
22 func sender(n int, c1, c2, c3, c4 chan<- int) {
23         defer close(c1)
24         defer close(c2)
25         defer close(c3)
26         defer close(c4)
27
28         for i := 0; i < n; i++ {
29                 select {
30                 case c1 <- i:
31                 case c2 <- i:
32                 case c3 <- i:
33                 case c4 <- i:
34                 }
35         }
36 }
37
38 // mux receives the values from sender and forwards them onto another channel.
39 // It would be simpler to just have sender's four cases all be the same
40 // channel, but this doesn't actually trigger the bug.
41 func mux(out chan<- int, in <-chan int, done chan<- bool) {
42         for v := range in {
43                 out <- v
44         }
45         done <- true
46 }
47
48 // recver gets a steam of values from the four mux's and checks for duplicates.
49 func recver(in <-chan int) {
50         seen := make(map[int]bool)
51
52         for v := range in {
53                 if _, ok := seen[v]; ok {
54                         println("got duplicate value: ", v)
55                         panic("fail")
56                 }
57                 seen[v] = true
58         }
59 }
60
61 func main() {
62         runtime.GOMAXPROCS(2)
63
64         flag.Parse()
65         c1 := make(chan int)
66         c2 := make(chan int)
67         c3 := make(chan int)
68         c4 := make(chan int)
69         done := make(chan bool)
70         cmux := make(chan int)
71         go sender(*iterations, c1, c2, c3, c4)
72         go mux(cmux, c1, done)
73         go mux(cmux, c2, done)
74         go mux(cmux, c3, done)
75         go mux(cmux, c4, done)
76         go func() {
77                 <-done
78                 <-done
79                 <-done
80                 <-done
81                 close(cmux)
82         }()
83         // We keep the recver because it might catch more bugs in the future.
84         // However, the result of the bug linked to at the top is that we'll
85         // end up panicking with: "throw: bad g->status in ready".
86         recver(cmux)
87 }