// 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); }