-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
waitgroup.go
37 lines (31 loc) · 980 Bytes
/
waitgroup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package helpers
import "sync/atomic"
// Go's "sync.WaitGroup" is not thread-safe. Specifically it's not safe to call
// "Add" concurrently with "Wait", which is problematic because we have a case
// where we would like to do that.
//
// This is a simple alternative implementation of "sync.WaitGroup" that is
// thread-safe and that works for our purposes. We don't need to worry about
// multiple waiters so the implementation can be very simple.
type ThreadSafeWaitGroup struct {
counter int32
channel chan struct{}
}
func MakeThreadSafeWaitGroup() *ThreadSafeWaitGroup {
return &ThreadSafeWaitGroup{
channel: make(chan struct{}, 1),
}
}
func (wg *ThreadSafeWaitGroup) Add(delta int32) {
if counter := atomic.AddInt32(&wg.counter, delta); counter == 0 {
wg.channel <- struct{}{}
} else if counter < 0 {
panic("sync: negative WaitGroup counter")
}
}
func (wg *ThreadSafeWaitGroup) Done() {
wg.Add(-1)
}
func (wg *ThreadSafeWaitGroup) Wait() {
<-wg.channel
}