github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/sync/waitgroup.go (about) 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 }