@@ -11,51 +11,52 @@ import (
11
11
)
12
12
13
13
// A WaitGroup is a counting semaphore typically used to wait
14
- // for a group of goroutines to finish.
14
+ // for a group of goroutines or tasks to finish.
15
15
//
16
- // The main goroutine calls [WaitGroup.Add] to set (or increase) the number of
17
- // goroutines to wait for. Then each of the goroutines
18
- // runs and calls [WaitGroup.Done] when finished. At the same time,
19
- // [WaitGroup.Wait] can be used to block until all goroutines have finished.
20
- //
21
- // This is a typical pattern of WaitGroup usage to
22
- // synchronize 3 goroutines, each calling the function f:
16
+ // Typically, a main goroutine will start tasks, each in a new
17
+ // goroutine, by calling [WaitGroup.Go] and then wait for all tasks to
18
+ // complete by calling [WaitGroup.Wait]. For example:
23
19
//
24
20
// var wg sync.WaitGroup
25
- // for range 3 {
26
- // wg.Add(1)
27
- // go func() {
28
- // defer wg.Done()
29
- // f()
30
- // }()
31
- // }
21
+ // wg.Go(task1)
22
+ // wg.Go(task2)
32
23
// wg.Wait()
33
24
//
34
- // For convenience, the [WaitGroup.Go] method simplifies this pattern to:
25
+ // A WaitGroup may also be used for tracking tasks without using Go to
26
+ // start new goroutines by using [WaitGroup.Add] and [WaitGroup.Done].
27
+ //
28
+ // The previous example can be rewritten using explicitly created
29
+ // goroutines along with Add and Done:
35
30
//
36
31
// var wg sync.WaitGroup
37
- // for range 3 {
38
- // wg.Go(f)
39
- // }
32
+ // wg.Add(1)
33
+ // go func() {
34
+ // defer wg.Done()
35
+ // task1()
36
+ // }()
37
+ // wg.Add(1)
38
+ // go func() {
39
+ // defer wg.Done()
40
+ // task2()
41
+ // }()
40
42
// wg.Wait()
41
43
//
42
- // A WaitGroup must not be copied after first use.
43
- //
44
- // In the terminology of [the Go memory model], a call to [WaitGroup.Done]
45
- // “synchronizes before” the return of any Wait call that it unblocks.
44
+ // This pattern is common in code that predates [WaitGroup.Go].
46
45
//
47
- // [the Go memory model]: https://go.dev/ref/mem
46
+ // A WaitGroup must not be copied after first use.
48
47
type WaitGroup struct {
49
48
noCopy noCopy
50
49
51
50
state atomic.Uint64 // high 32 bits are counter, low 32 bits are waiter count.
52
51
sema uint32
53
52
}
54
53
55
- // Add adds delta, which may be negative, to the [WaitGroup] counter.
54
+ // Add adds delta, which may be negative, to the [WaitGroup] task counter.
56
55
// If the counter becomes zero, all goroutines blocked on [WaitGroup.Wait] are released.
57
56
// If the counter goes negative, Add panics.
58
57
//
58
+ // Callers should prefer [WaitGroup.Go].
59
+ //
59
60
// Note that calls with a positive delta that occur when the counter is zero
60
61
// must happen before a Wait. Calls with a negative delta, or calls with a
61
62
// positive delta that start when the counter is greater than zero, may happen
@@ -107,12 +108,20 @@ func (wg *WaitGroup) Add(delta int) {
107
108
}
108
109
}
109
110
110
- // Done decrements the [WaitGroup] counter by one.
111
+ // Done decrements the [WaitGroup] task counter by one.
112
+ // It is equivalent to Add(-1).
113
+ //
114
+ // Callers should prefer [WaitGroup.Go].
115
+ //
116
+ // In the terminology of [the Go memory model], a call to Done
117
+ // "synchronizes before" the return of any Wait call that it unblocks.
118
+ //
119
+ // [the Go memory model]: https://go.dev/ref/mem
111
120
func (wg * WaitGroup ) Done () {
112
121
wg .Add (- 1 )
113
122
}
114
123
115
- // Wait blocks until the [WaitGroup] counter is zero.
124
+ // Wait blocks until the [WaitGroup] task counter is zero.
116
125
func (wg * WaitGroup ) Wait () {
117
126
if race .Enabled {
118
127
race .Disable ()
@@ -151,7 +160,7 @@ func (wg *WaitGroup) Wait() {
151
160
}
152
161
}
153
162
154
- // Go calls f in a new goroutine and adds that task to the WaitGroup.
163
+ // Go calls f in a new goroutine and adds that task to the [ WaitGroup] .
155
164
// When f returns, the task is removed from the WaitGroup.
156
165
//
157
166
// If the WaitGroup is empty, Go must happen before a [WaitGroup.Wait].
@@ -161,8 +170,10 @@ func (wg *WaitGroup) Wait() {
161
170
// If a WaitGroup is reused to wait for several independent sets of tasks,
162
171
// new Go calls must happen after all previous Wait calls have returned.
163
172
//
164
- // In the terminology of [the Go memory model](https://go.dev/ref/mem),
165
- // the return from f "synchronizes before" the return of any Wait call that it unblocks.
173
+ // In the terminology of [the Go memory model], the return from f
174
+ // "synchronizes before" the return of any Wait call that it unblocks.
175
+ //
176
+ // [the Go memory model]: https://go.dev/ref/mem
166
177
func (wg * WaitGroup ) Go (f func ()) {
167
178
wg .Add (1 )
168
179
go func () {
0 commit comments