From adb0401dac41c81571722312d4586b2693f95aa6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 16 Sep 2011 15:47:21 +0000 Subject: Update Go library to r60. From-SVN: r178910 --- libgo/go/sync/waitgroup.go | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'libgo/go/sync/waitgroup.go') diff --git a/libgo/go/sync/waitgroup.go b/libgo/go/sync/waitgroup.go index 05478c6..a4c9b7e 100644 --- a/libgo/go/sync/waitgroup.go +++ b/libgo/go/sync/waitgroup.go @@ -4,7 +4,10 @@ package sync -import "runtime" +import ( + "runtime" + "sync/atomic" +) // A WaitGroup waits for a collection of goroutines to finish. // The main goroutine calls Add to set the number of @@ -28,8 +31,8 @@ import "runtime" // type WaitGroup struct { m Mutex - counter int - waiters int + counter int32 + waiters int32 sema *uint32 } @@ -48,19 +51,19 @@ type WaitGroup struct { // Add adds delta, which may be negative, to the WaitGroup counter. // If the counter becomes zero, all goroutines blocked on Wait() are released. func (wg *WaitGroup) Add(delta int) { - wg.m.Lock() - if delta < -wg.counter { - wg.m.Unlock() + v := atomic.AddInt32(&wg.counter, int32(delta)) + if v < 0 { panic("sync: negative WaitGroup count") } - wg.counter += delta - if wg.counter == 0 && wg.waiters > 0 { - for i := 0; i < wg.waiters; i++ { - runtime.Semrelease(wg.sema) - } - wg.waiters = 0 - wg.sema = nil + if v > 0 || atomic.LoadInt32(&wg.waiters) == 0 { + return } + wg.m.Lock() + for i := int32(0); i < wg.waiters; i++ { + runtime.Semrelease(wg.sema) + } + wg.waiters = 0 + wg.sema = nil wg.m.Unlock() } @@ -71,12 +74,20 @@ func (wg *WaitGroup) Done() { // Wait blocks until the WaitGroup counter is zero. func (wg *WaitGroup) Wait() { + if atomic.LoadInt32(&wg.counter) == 0 { + return + } wg.m.Lock() - if wg.counter == 0 { + atomic.AddInt32(&wg.waiters, 1) + // This code is racing with the unlocked path in Add above. + // The code above modifies counter and then reads waiters. + // We must modify waiters and then read counter (the opposite order) + // to avoid missing an Add. + if atomic.LoadInt32(&wg.counter) == 0 { + atomic.AddInt32(&wg.waiters, -1) wg.m.Unlock() return } - wg.waiters++ if wg.sema == nil { wg.sema = new(uint32) } -- cgit v1.1