mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
sync: add WaitGroup.Go
Fixes #63796 Change-Id: I2a941275dd64ef858cbf02d31a759fdc5c082ceb Reviewed-on: https://go-review.googlesource.com/c/go/+/662635 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com> Auto-Submit: Carlos Amedee <carlos@golang.org> Reviewed-by: Carlos Amedee <carlos@golang.org>
This commit is contained in:
parent
d164776615
commit
822031dffc
1
api/next/63796.txt
Normal file
1
api/next/63796.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
pkg sync, method (*WaitGroup) Go(func()) #63769
|
2
doc/next/6-stdlib/99-minor/sync/63769.md
Normal file
2
doc/next/6-stdlib/99-minor/sync/63769.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[WaitGroup] has added a new method [WaitGroup.Go],
|
||||||
|
that makes the common pattern of creating and counting goroutines more convenient.
|
@ -10,12 +10,35 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A WaitGroup waits for a collection of goroutines to finish.
|
// A WaitGroup is a counting semaphore typically used to wait
|
||||||
// The main goroutine calls [WaitGroup.Add] to set the number of
|
// for a group of goroutines to finish.
|
||||||
|
//
|
||||||
|
// The main goroutine calls [WaitGroup.Add] to set (or increase) the number of
|
||||||
// goroutines to wait for. Then each of the goroutines
|
// goroutines to wait for. Then each of the goroutines
|
||||||
// runs and calls [WaitGroup.Done] when finished. At the same time,
|
// runs and calls [WaitGroup.Done] when finished. At the same time,
|
||||||
// [WaitGroup.Wait] can be used to block until all goroutines have finished.
|
// [WaitGroup.Wait] can be used to block until all goroutines have finished.
|
||||||
//
|
//
|
||||||
|
// This is a typical pattern of WaitGroup usage to
|
||||||
|
// synchronize 3 goroutines, each calling the function f:
|
||||||
|
//
|
||||||
|
// var wg sync.WaitGroup
|
||||||
|
// for range 3 {
|
||||||
|
// wg.Add(1)
|
||||||
|
// go func() {
|
||||||
|
// defer wg.Done()
|
||||||
|
// f()
|
||||||
|
// }()
|
||||||
|
// }
|
||||||
|
// wg.Wait()
|
||||||
|
//
|
||||||
|
// For convenience, the [WaitGroup.Go] method simplifies this pattern to:
|
||||||
|
//
|
||||||
|
// var wg sync.WaitGroup
|
||||||
|
// for range 3 {
|
||||||
|
// wg.Go(f)
|
||||||
|
// }
|
||||||
|
// wg.Wait()
|
||||||
|
//
|
||||||
// A WaitGroup must not be copied after first use.
|
// A WaitGroup must not be copied after first use.
|
||||||
//
|
//
|
||||||
// In the terminology of [the Go memory model], a call to [WaitGroup.Done]
|
// In the terminology of [the Go memory model], a call to [WaitGroup.Done]
|
||||||
@ -127,3 +150,23 @@ func (wg *WaitGroup) Wait() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go calls f in a new goroutine and adds that task to the WaitGroup.
|
||||||
|
// When f returns, the task is removed from the WaitGroup.
|
||||||
|
//
|
||||||
|
// If the WaitGroup is empty, Go must happen before a [WaitGroup.Wait].
|
||||||
|
// Typically, this simply means Go is called to start tasks before Wait is called.
|
||||||
|
// If the WaitGroup is not empty, Go may happen at any time.
|
||||||
|
// This means a goroutine started by Go may itself call Go.
|
||||||
|
// If a WaitGroup is reused to wait for several independent sets of tasks,
|
||||||
|
// new Go calls must happen after all previous Wait calls have returned.
|
||||||
|
//
|
||||||
|
// In the terminology of [the Go memory model](https://go.dev/ref/mem),
|
||||||
|
// the return from f "synchronizes before" the return of any Wait call that it unblocks.
|
||||||
|
func (wg *WaitGroup) Go(f func()) {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
@ -98,6 +98,18 @@ func TestWaitGroupAlign(t *testing.T) {
|
|||||||
x.wg.Wait()
|
x.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWaitGroupGo(t *testing.T) {
|
||||||
|
wg := &WaitGroup{}
|
||||||
|
var i int
|
||||||
|
wg.Go(func() {
|
||||||
|
i++
|
||||||
|
})
|
||||||
|
wg.Wait()
|
||||||
|
if i != 1 {
|
||||||
|
t.Fatalf("got %d, want 1", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkWaitGroupUncontended(b *testing.B) {
|
func BenchmarkWaitGroupUncontended(b *testing.B) {
|
||||||
type PaddedWaitGroup struct {
|
type PaddedWaitGroup struct {
|
||||||
WaitGroup
|
WaitGroup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user