Add gcc ka.po
[official-gcc.git] / libgo / go / sync / cond_test.go
blob859cae59bca829aaaa3ab8e3a8465c02c241a89e
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.
5 package sync_test
7 import (
8 "reflect"
9 "runtime"
10 . "sync"
11 "testing"
12 "time"
15 func TestCondSignal(t *testing.T) {
16 var m Mutex
17 c := NewCond(&m)
18 n := 2
19 running := make(chan bool, n)
20 awake := make(chan bool, n)
21 for i := 0; i < n; i++ {
22 go func() {
23 m.Lock()
24 running <- true
25 c.Wait()
26 awake <- true
27 m.Unlock()
28 }()
30 for i := 0; i < n; i++ {
31 <-running // Wait for everyone to run.
33 for n > 0 {
34 select {
35 case <-awake:
36 t.Fatal("goroutine not asleep")
37 default:
39 m.Lock()
40 c.Signal()
41 m.Unlock()
42 <-awake // Will deadlock if no goroutine wakes up
43 select {
44 case <-awake:
45 t.Fatal("too many goroutines awake")
46 default:
48 n--
50 c.Signal()
53 func TestCondSignalGenerations(t *testing.T) {
54 var m Mutex
55 c := NewCond(&m)
56 n := 100
57 running := make(chan bool, n)
58 awake := make(chan int, n)
59 for i := 0; i < n; i++ {
60 go func(i int) {
61 m.Lock()
62 running <- true
63 c.Wait()
64 awake <- i
65 m.Unlock()
66 }(i)
67 if i > 0 {
68 a := <-awake
69 if a != i-1 {
70 t.Fatalf("wrong goroutine woke up: want %d, got %d", i-1, a)
73 <-running
74 m.Lock()
75 c.Signal()
76 m.Unlock()
80 func TestCondBroadcast(t *testing.T) {
81 var m Mutex
82 c := NewCond(&m)
83 n := 200
84 running := make(chan int, n)
85 awake := make(chan int, n)
86 exit := false
87 for i := 0; i < n; i++ {
88 go func(g int) {
89 m.Lock()
90 for !exit {
91 running <- g
92 c.Wait()
93 awake <- g
95 m.Unlock()
96 }(i)
98 for i := 0; i < n; i++ {
99 for i := 0; i < n; i++ {
100 <-running // Will deadlock unless n are running.
102 if i == n-1 {
103 m.Lock()
104 exit = true
105 m.Unlock()
107 select {
108 case <-awake:
109 t.Fatal("goroutine not asleep")
110 default:
112 m.Lock()
113 c.Broadcast()
114 m.Unlock()
115 seen := make([]bool, n)
116 for i := 0; i < n; i++ {
117 g := <-awake
118 if seen[g] {
119 t.Fatal("goroutine woke up twice")
121 seen[g] = true
124 select {
125 case <-running:
126 t.Fatal("goroutine did not exit")
127 default:
129 c.Broadcast()
132 func TestRace(t *testing.T) {
133 x := 0
134 c := NewCond(&Mutex{})
135 done := make(chan bool)
136 go func() {
137 c.L.Lock()
138 x = 1
139 c.Wait()
140 if x != 2 {
141 t.Error("want 2")
143 x = 3
144 c.Signal()
145 c.L.Unlock()
146 done <- true
148 go func() {
149 c.L.Lock()
150 for {
151 if x == 1 {
152 x = 2
153 c.Signal()
154 break
156 c.L.Unlock()
157 runtime.Gosched()
158 c.L.Lock()
160 c.L.Unlock()
161 done <- true
163 go func() {
164 c.L.Lock()
165 for {
166 if x == 2 {
167 c.Wait()
168 if x != 3 {
169 t.Error("want 3")
171 break
173 if x == 3 {
174 break
176 c.L.Unlock()
177 runtime.Gosched()
178 c.L.Lock()
180 c.L.Unlock()
181 done <- true
183 <-done
184 <-done
185 <-done
188 func TestCondSignalStealing(t *testing.T) {
189 for iters := 0; iters < 1000; iters++ {
190 var m Mutex
191 cond := NewCond(&m)
193 // Start a waiter.
194 ch := make(chan struct{})
195 go func() {
196 m.Lock()
197 ch <- struct{}{}
198 cond.Wait()
199 m.Unlock()
201 ch <- struct{}{}
204 <-ch
205 m.Lock()
206 m.Unlock()
208 // We know that the waiter is in the cond.Wait() call because we
209 // synchronized with it, then acquired/released the mutex it was
210 // holding when we synchronized.
212 // Start two goroutines that will race: one will broadcast on
213 // the cond var, the other will wait on it.
215 // The new waiter may or may not get notified, but the first one
216 // has to be notified.
217 done := false
218 go func() {
219 cond.Broadcast()
222 go func() {
223 m.Lock()
224 for !done {
225 cond.Wait()
227 m.Unlock()
230 // Check that the first waiter does get signaled.
231 select {
232 case <-ch:
233 case <-time.After(2 * time.Second):
234 t.Fatalf("First waiter didn't get broadcast.")
237 // Release the second waiter in case it didn't get the
238 // broadcast.
239 m.Lock()
240 done = true
241 m.Unlock()
242 cond.Broadcast()
246 func TestCondCopy(t *testing.T) {
247 defer func() {
248 err := recover()
249 if err == nil || err.(string) != "sync.Cond is copied" {
250 t.Fatalf("got %v, expect sync.Cond is copied", err)
253 c := Cond{L: &Mutex{}}
254 c.Signal()
255 var c2 Cond
256 reflect.ValueOf(&c2).Elem().Set(reflect.ValueOf(&c).Elem()) // c2 := c, hidden from vet
257 c2.Signal()
260 func BenchmarkCond1(b *testing.B) {
261 benchmarkCond(b, 1)
264 func BenchmarkCond2(b *testing.B) {
265 benchmarkCond(b, 2)
268 func BenchmarkCond4(b *testing.B) {
269 benchmarkCond(b, 4)
272 func BenchmarkCond8(b *testing.B) {
273 benchmarkCond(b, 8)
276 func BenchmarkCond16(b *testing.B) {
277 benchmarkCond(b, 16)
280 func BenchmarkCond32(b *testing.B) {
281 benchmarkCond(b, 32)
284 func benchmarkCond(b *testing.B, waiters int) {
285 c := NewCond(&Mutex{})
286 done := make(chan bool)
287 id := 0
289 for routine := 0; routine < waiters+1; routine++ {
290 go func() {
291 for i := 0; i < b.N; i++ {
292 c.L.Lock()
293 if id == -1 {
294 c.L.Unlock()
295 break
297 id++
298 if id == waiters+1 {
299 id = 0
300 c.Broadcast()
301 } else {
302 c.Wait()
304 c.L.Unlock()
306 c.L.Lock()
307 id = -1
308 c.Broadcast()
309 c.L.Unlock()
310 done <- true
313 for routine := 0; routine < waiters+1; routine++ {
314 <-done