2014-04-11 Marc Glisse <marc.glisse@inria.fr>
[official-gcc.git] / libgo / go / sync / cond_test.go
blob467c80621de2c57a76f129cf151b2d9037d35f1a
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 package sync_test
6 import (
7 . "sync"
9 "runtime"
10 "testing"
13 func TestCondSignal(t *testing.T) {
14 var m Mutex
15 c := NewCond(&m)
16 n := 2
17 running := make(chan bool, n)
18 awake := make(chan bool, n)
19 for i := 0; i < n; i++ {
20 go func() {
21 m.Lock()
22 running <- true
23 c.Wait()
24 awake <- true
25 m.Unlock()
26 }()
28 for i := 0; i < n; i++ {
29 <-running // Wait for everyone to run.
31 for n > 0 {
32 select {
33 case <-awake:
34 t.Fatal("goroutine not asleep")
35 default:
37 m.Lock()
38 c.Signal()
39 m.Unlock()
40 <-awake // Will deadlock if no goroutine wakes up
41 select {
42 case <-awake:
43 t.Fatal("too many goroutines awake")
44 default:
46 n--
48 c.Signal()
51 func TestCondSignalGenerations(t *testing.T) {
52 var m Mutex
53 c := NewCond(&m)
54 n := 100
55 running := make(chan bool, n)
56 awake := make(chan int, n)
57 for i := 0; i < n; i++ {
58 go func(i int) {
59 m.Lock()
60 running <- true
61 c.Wait()
62 awake <- i
63 m.Unlock()
64 }(i)
65 if i > 0 {
66 a := <-awake
67 if a != i-1 {
68 t.Fatalf("wrong goroutine woke up: want %d, got %d", i-1, a)
71 <-running
72 m.Lock()
73 c.Signal()
74 m.Unlock()
78 func TestCondBroadcast(t *testing.T) {
79 var m Mutex
80 c := NewCond(&m)
81 n := 200
82 running := make(chan int, n)
83 awake := make(chan int, n)
84 exit := false
85 for i := 0; i < n; i++ {
86 go func(g int) {
87 m.Lock()
88 for !exit {
89 running <- g
90 c.Wait()
91 awake <- g
93 m.Unlock()
94 }(i)
96 for i := 0; i < n; i++ {
97 for i := 0; i < n; i++ {
98 <-running // Will deadlock unless n are running.
100 if i == n-1 {
101 m.Lock()
102 exit = true
103 m.Unlock()
105 select {
106 case <-awake:
107 t.Fatal("goroutine not asleep")
108 default:
110 m.Lock()
111 c.Broadcast()
112 m.Unlock()
113 seen := make([]bool, n)
114 for i := 0; i < n; i++ {
115 g := <-awake
116 if seen[g] {
117 t.Fatal("goroutine woke up twice")
119 seen[g] = true
122 select {
123 case <-running:
124 t.Fatal("goroutine did not exit")
125 default:
127 c.Broadcast()
130 func TestRace(t *testing.T) {
131 x := 0
132 c := NewCond(&Mutex{})
133 done := make(chan bool)
134 go func() {
135 c.L.Lock()
136 x = 1
137 c.Wait()
138 if x != 2 {
139 t.Fatal("want 2")
141 x = 3
142 c.Signal()
143 c.L.Unlock()
144 done <- true
146 go func() {
147 c.L.Lock()
148 for {
149 if x == 1 {
150 x = 2
151 c.Signal()
152 break
154 c.L.Unlock()
155 runtime.Gosched()
156 c.L.Lock()
158 c.L.Unlock()
159 done <- true
161 go func() {
162 c.L.Lock()
163 for {
164 if x == 2 {
165 c.Wait()
166 if x != 3 {
167 t.Fatal("want 3")
169 break
171 if x == 3 {
172 break
174 c.L.Unlock()
175 runtime.Gosched()
176 c.L.Lock()
178 c.L.Unlock()
179 done <- true
181 <-done
182 <-done
183 <-done
186 func TestCondCopy(t *testing.T) {
187 defer func() {
188 err := recover()
189 if err == nil || err.(string) != "sync.Cond is copied" {
190 t.Fatalf("got %v, expect sync.Cond is copied", err)
193 c := Cond{L: &Mutex{}}
194 c.Signal()
195 c2 := c
196 c2.Signal()
199 func BenchmarkCond1(b *testing.B) {
200 benchmarkCond(b, 1)
203 func BenchmarkCond2(b *testing.B) {
204 benchmarkCond(b, 2)
207 func BenchmarkCond4(b *testing.B) {
208 benchmarkCond(b, 4)
211 func BenchmarkCond8(b *testing.B) {
212 benchmarkCond(b, 8)
215 func BenchmarkCond16(b *testing.B) {
216 benchmarkCond(b, 16)
219 func BenchmarkCond32(b *testing.B) {
220 benchmarkCond(b, 32)
223 func benchmarkCond(b *testing.B, waiters int) {
224 c := NewCond(&Mutex{})
225 done := make(chan bool)
226 id := 0
228 for routine := 0; routine < waiters+1; routine++ {
229 go func() {
230 for i := 0; i < b.N; i++ {
231 c.L.Lock()
232 if id == -1 {
233 c.L.Unlock()
234 break
236 id++
237 if id == waiters+1 {
238 id = 0
239 c.Broadcast()
240 } else {
241 c.Wait()
243 c.L.Unlock()
245 c.L.Lock()
246 id = -1
247 c.Broadcast()
248 c.L.Unlock()
249 done <- true
252 for routine := 0; routine < waiters+1; routine++ {
253 <-done