go.mway.dev/x@v0.0.0-20240520034138-950aede9a3fb/sync/waitgroup.go (about) 1 // Copyright (c) 2022 Matt Way 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to 5 // deal in the Software without restriction, including without limitation the 6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 // sell copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 // IN THE THE SOFTWARE. 20 21 // Package sync provides synchronization tools, primitives, and wrappers. 22 package sync 23 24 import ( 25 "sync" 26 "sync/atomic" 27 ) 28 29 // WaitGroup is a wrapper around sync.WaitGroup that adds a length component. 30 // It is a drop-in replacement that is functionally equivalent in every way 31 // except that it also tracks the value of the underlying WaitGroup counter. 32 type WaitGroup struct { 33 wg sync.WaitGroup 34 n [1]int64 35 } 36 37 // Add adds delta, which may be negative, to the WaitGroup counter. If the 38 // counter becomes zero, all goroutines blocked on Wait are released. If the 39 // counter goes negative, Add panics. 40 func (g *WaitGroup) Add(delta int) { 41 atomic.AddInt64(&g.n[0], int64(delta)) 42 g.wg.Add(delta) 43 } 44 45 // Done decrements the WaitGroup counter by one. 46 func (g *WaitGroup) Done() { 47 atomic.AddInt64(&g.n[0], -1) 48 g.wg.Done() 49 } 50 51 // Inc increments the WaitGroup counter by one. 52 func (g *WaitGroup) Inc() { 53 g.Add(1) 54 } 55 56 // Len returns the current value of the underlying WaitGroup counter. 57 func (g *WaitGroup) Len() int { 58 return int(atomic.LoadInt64(&g.n[0])) 59 } 60 61 // Wait blocks until the WaitGroup counter is zero. 62 func (g *WaitGroup) Wait() { 63 g.wg.Wait() 64 }