blob: 533438d91c1f8d1be78205a890a1f75ae5871af7 [file] [log] [blame]
Serge Bazanski31dd6162018-10-25 14:20:50 +02001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package errgroup provides synchronization, error propagation, and Context
6// cancelation for groups of goroutines working on subtasks of a common task.
7package errgroup
8
9import (
10 "sync"
11
12 "golang.org/x/net/context"
13)
14
15// A Group is a collection of goroutines working on subtasks that are part of
16// the same overall task.
17//
18// A zero Group is valid and does not cancel on error.
19type Group struct {
20 cancel func()
21
22 wg sync.WaitGroup
23
24 errOnce sync.Once
25 err error
26}
27
28// WithContext returns a new Group and an associated Context derived from ctx.
29//
30// The derived Context is canceled the first time a function passed to Go
31// returns a non-nil error or the first time Wait returns, whichever occurs
32// first.
33func WithContext(ctx context.Context) (*Group, context.Context) {
34 ctx, cancel := context.WithCancel(ctx)
35 return &Group{cancel: cancel}, ctx
36}
37
38// Wait blocks until all function calls from the Go method have returned, then
39// returns the first non-nil error (if any) from them.
40func (g *Group) Wait() error {
41 g.wg.Wait()
42 if g.cancel != nil {
43 g.cancel()
44 }
45 return g.err
46}
47
48// Go calls the given function in a new goroutine.
49//
50// The first call to return a non-nil error cancels the group; its error will be
51// returned by Wait.
52func (g *Group) Go(f func() error) {
53 g.wg.Add(1)
54
55 go func() {
56 defer g.wg.Done()
57
58 if err := f(); err != nil {
59 g.errOnce.Do(func() {
60 g.err = err
61 if g.cancel != nil {
62 g.cancel()
63 }
64 })
65 }
66 }()
67}