OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 package sync_test | 4 package sync_test |
5 | 5 |
6 import ( | 6 import ( |
7 . "sync" | 7 . "sync" |
| 8 |
| 9 "runtime" |
8 "testing" | 10 "testing" |
9 ) | 11 ) |
10 | 12 |
11 func TestCondSignal(t *testing.T) { | 13 func TestCondSignal(t *testing.T) { |
12 var m Mutex | 14 var m Mutex |
13 c := NewCond(&m) | 15 c := NewCond(&m) |
14 n := 2 | 16 n := 2 |
15 running := make(chan bool, n) | 17 running := make(chan bool, n) |
16 awake := make(chan bool, n) | 18 awake := make(chan bool, n) |
17 for i := 0; i < n; i++ { | 19 for i := 0; i < n; i++ { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 seen[g] = true | 119 seen[g] = true |
118 } | 120 } |
119 } | 121 } |
120 select { | 122 select { |
121 case <-running: | 123 case <-running: |
122 t.Fatal("goroutine did not exit") | 124 t.Fatal("goroutine did not exit") |
123 default: | 125 default: |
124 } | 126 } |
125 c.Broadcast() | 127 c.Broadcast() |
126 } | 128 } |
| 129 |
| 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") |
| 140 } |
| 141 x = 3 |
| 142 c.Signal() |
| 143 c.L.Unlock() |
| 144 done <- true |
| 145 }() |
| 146 go func() { |
| 147 c.L.Lock() |
| 148 for { |
| 149 if x == 1 { |
| 150 x = 2 |
| 151 c.Signal() |
| 152 break |
| 153 } |
| 154 c.L.Unlock() |
| 155 runtime.Gosched() |
| 156 c.L.Lock() |
| 157 } |
| 158 c.L.Unlock() |
| 159 done <- true |
| 160 }() |
| 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") |
| 168 } |
| 169 break |
| 170 } |
| 171 if x == 3 { |
| 172 break |
| 173 } |
| 174 c.L.Unlock() |
| 175 runtime.Gosched() |
| 176 c.L.Lock() |
| 177 } |
| 178 c.L.Unlock() |
| 179 done <- true |
| 180 }() |
| 181 <-done |
| 182 <-done |
| 183 <-done |
| 184 } |
| 185 |
| 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) |
| 191 } |
| 192 }() |
| 193 c := Cond{L: &Mutex{}} |
| 194 c.Signal() |
| 195 c2 := c |
| 196 c2.Signal() |
| 197 } |
| 198 |
| 199 func BenchmarkCond1(b *testing.B) { |
| 200 benchmarkCond(b, 1) |
| 201 } |
| 202 |
| 203 func BenchmarkCond2(b *testing.B) { |
| 204 benchmarkCond(b, 2) |
| 205 } |
| 206 |
| 207 func BenchmarkCond4(b *testing.B) { |
| 208 benchmarkCond(b, 4) |
| 209 } |
| 210 |
| 211 func BenchmarkCond8(b *testing.B) { |
| 212 benchmarkCond(b, 8) |
| 213 } |
| 214 |
| 215 func BenchmarkCond16(b *testing.B) { |
| 216 benchmarkCond(b, 16) |
| 217 } |
| 218 |
| 219 func BenchmarkCond32(b *testing.B) { |
| 220 benchmarkCond(b, 32) |
| 221 } |
| 222 |
| 223 func benchmarkCond(b *testing.B, waiters int) { |
| 224 c := NewCond(&Mutex{}) |
| 225 done := make(chan bool) |
| 226 id := 0 |
| 227 |
| 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 |
| 235 } |
| 236 id++ |
| 237 if id == waiters+1 { |
| 238 id = 0 |
| 239 c.Broadcast() |
| 240 } else { |
| 241 c.Wait() |
| 242 } |
| 243 c.L.Unlock() |
| 244 } |
| 245 c.L.Lock() |
| 246 id = -1 |
| 247 c.Broadcast() |
| 248 c.L.Unlock() |
| 249 done <- true |
| 250 }() |
| 251 } |
| 252 for routine := 0; routine < waiters+1; routine++ { |
| 253 <-done |
| 254 } |
| 255 } |
OLD | NEW |