OSDN Git Service

Latest updates from FSF 4.7 branch
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / go.test / test / chan / doubleselect.go
1 // $G $D/$F.go && $L $F.$A && ./$A.out
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 // This test is designed to flush out the case where two cases of a select can
8 // both end up running. See http://codereview.appspot.com/180068.
9 package main
10
11 import (
12         "flag"
13         "runtime"
14 )
15
16 var iterations *int = flag.Int("n", 100000, "number of iterations")
17
18 // sender sends a counter to one of four different channels. If two
19 // cases both end up running in the same iteration, the same value will be sent
20 // to two different channels.
21 func sender(n int, c1, c2, c3, c4 chan<- int) {
22         defer close(c1)
23         defer close(c2)
24
25         for i := 0; i < n; i++ {
26                 select {
27                 case c1 <- i:
28                 case c2 <- i:
29                 case c3 <- i:
30                 case c4 <- i:
31                 }
32         }
33 }
34
35 // mux receives the values from sender and forwards them onto another channel.
36 // It would be simplier to just have sender's four cases all be the same
37 // channel, but this doesn't actually trigger the bug.
38 func mux(out chan<- int, in <-chan int) {
39         for {
40                 v := <-in
41                 if closed(in) {
42                         close(out)
43                         break
44                 }
45                 out <- v
46         }
47 }
48
49 // recver gets a steam of values from the four mux's and checks for duplicates.
50 func recver(in <-chan int) {
51         seen := make(map[int]bool)
52
53         for {
54                 v := <-in
55                 if closed(in) {
56                         break
57                 }
58                 if _, ok := seen[v]; ok {
59                         println("got duplicate value: ", v)
60                         panic("fail")
61                 }
62                 seen[v] = true
63         }
64 }
65
66 func main() {
67         runtime.GOMAXPROCS(2)
68
69         c1 := make(chan int)
70         c2 := make(chan int)
71         c3 := make(chan int)
72         c4 := make(chan int)
73         cmux := make(chan int)
74         go sender(*iterations, c1, c2, c3, c4)
75         go mux(cmux, c1)
76         go mux(cmux, c2)
77         go mux(cmux, c3)
78         go mux(cmux, c4)
79         // We keep the recver because it might catch more bugs in the future.
80         // However, the result of the bug linked to at the top is that we'll
81         // end up panicing with: "throw: bad g->status in ready".
82         recver(cmux)
83         print("PASS\n")
84 }