Skip to content

Commit d9cdadf

Browse files
committed
sync: add WaitGroup
1 parent 1091665 commit d9cdadf

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/sync/waitgroup.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package sync
2+
3+
import "internal/task"
4+
5+
type WaitGroup struct {
6+
counter uint
7+
waiters task.Stack
8+
}
9+
10+
func (wg *WaitGroup) Add(delta int) {
11+
if delta > 0 {
12+
// Check for overflow.
13+
if uint(delta) > (^uint(0))-wg.counter {
14+
panic("sync: WaitGroup counter overflowed")
15+
}
16+
17+
// Add to the counter.
18+
wg.counter += uint(delta)
19+
} else {
20+
// Check for underflow.
21+
if uint(-delta) > wg.counter {
22+
panic("sync: negative WaitGroup counter")
23+
}
24+
25+
// Subtract from the counter.
26+
wg.counter -= uint(-delta)
27+
28+
// If the counter is zero, everything is done and the waiters should be resumed.
29+
// This code assumes that the waiters cannot wake up until after this function returns.
30+
// In the current implementation, this is always correct.
31+
if wg.counter == 0 {
32+
for t := wg.waiters.Pop(); t != nil; t = wg.waiters.Pop() {
33+
scheduleTask(t)
34+
}
35+
}
36+
}
37+
}
38+
39+
func (wg *WaitGroup) Done() {
40+
wg.Add(-1)
41+
}
42+
43+
func (wg *WaitGroup) Wait() {
44+
if wg.counter == 0 {
45+
// Everything already finished.
46+
return
47+
}
48+
49+
// Push the current goroutine onto the waiter stack.
50+
wg.waiters.Push(task.Current())
51+
52+
// Pause until the waiters are awoken by Add/Done.
53+
task.Pause()
54+
}

0 commit comments

Comments
 (0)