| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // GOMAXPROCS=10 gotest |
| |
| package sync_test |
| |
| import ( |
| "fmt"; |
| "runtime"; |
| . "sync"; |
| "testing"; |
| ) |
| |
| func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) { |
| m.RLock(); |
| clocked <- true; |
| <-cunlock; |
| m.RUnlock(); |
| cdone <- true; |
| } |
| |
| func doTestParallelReaders(numReaders, gomaxprocs int) { |
| runtime.GOMAXPROCS(gomaxprocs); |
| var m RWMutex; |
| clocked := make(chan bool); |
| cunlock := make(chan bool); |
| cdone := make(chan bool); |
| for i := 0; i < numReaders; i++ { |
| go parallelReader(&m, clocked, cunlock, cdone) |
| } |
| // Wait for all parallel RLock()s to succeed. |
| for i := 0; i < numReaders; i++ { |
| <-clocked |
| } |
| for i := 0; i < numReaders; i++ { |
| cunlock <- true |
| } |
| // Wait for the goroutines to finish. |
| for i := 0; i < numReaders; i++ { |
| <-cdone |
| } |
| } |
| |
| func TestParallelReaders(t *testing.T) { |
| doTestParallelReaders(1, 4); |
| doTestParallelReaders(3, 4); |
| doTestParallelReaders(4, 2); |
| } |
| |
| func reader(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) { |
| for i := 0; i < num_iterations; i++ { |
| rwm.RLock(); |
| n := Xadd(activity, 1); |
| if n < 1 || n >= 10000 { |
| panic(fmt.Sprintf("wlock(%d)\n", n)) |
| } |
| for i := 0; i < 100; i++ { |
| } |
| Xadd(activity, -1); |
| rwm.RUnlock(); |
| } |
| cdone <- true; |
| } |
| |
| func writer(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) { |
| for i := 0; i < num_iterations; i++ { |
| rwm.Lock(); |
| n := Xadd(activity, 10000); |
| if n != 10000 { |
| panic(fmt.Sprintf("wlock(%d)\n", n)) |
| } |
| for i := 0; i < 100; i++ { |
| } |
| Xadd(activity, -10000); |
| rwm.Unlock(); |
| } |
| cdone <- true; |
| } |
| |
| func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) { |
| runtime.GOMAXPROCS(gomaxprocs); |
| // Number of active readers + 10000 * number of active writers. |
| var activity uint32; |
| var rwm RWMutex; |
| cdone := make(chan bool); |
| go writer(&rwm, num_iterations, &activity, cdone); |
| var i int; |
| for i = 0; i < numReaders/2; i++ { |
| go reader(&rwm, num_iterations, &activity, cdone) |
| } |
| go writer(&rwm, num_iterations, &activity, cdone); |
| for ; i < numReaders; i++ { |
| go reader(&rwm, num_iterations, &activity, cdone) |
| } |
| // Wait for the 2 writers and all readers to finish. |
| for i := 0; i < 2+numReaders; i++ { |
| <-cdone |
| } |
| } |
| |
| func TestRWMutex(t *testing.T) { |
| HammerRWMutex(1, 1, 1000); |
| HammerRWMutex(1, 3, 1000); |
| HammerRWMutex(1, 10, 1000); |
| HammerRWMutex(4, 1, 1000); |
| HammerRWMutex(4, 3, 1000); |
| HammerRWMutex(4, 10, 1000); |
| HammerRWMutex(10, 1, 1000); |
| HammerRWMutex(10, 3, 1000); |
| HammerRWMutex(10, 10, 1000); |
| HammerRWMutex(10, 5, 10000); |
| } |