Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
66 lines (56 sloc)
1.58 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2016 The Go Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style | |
// license that can be found in the LICENSE file. | |
// Package errgroup provides synchronization, error propagation, and Context | |
// cancelation for groups of goroutines working on subtasks of a common task. | |
package errgroup | |
import ( | |
"context" | |
"sync" | |
) | |
// A Group is a collection of goroutines working on subtasks that are part of | |
// the same overall task. | |
// | |
// A zero Group is valid and does not cancel on error. | |
type Group struct { | |
cancel func() | |
wg sync.WaitGroup | |
errOnce sync.Once | |
err error | |
} | |
// WithContext returns a new Group and an associated Context derived from ctx. | |
// | |
// The derived Context is canceled the first time a function passed to Go | |
// returns a non-nil error or the first time Wait returns, whichever occurs | |
// first. | |
func WithContext(ctx context.Context) (*Group, context.Context) { | |
ctx, cancel := context.WithCancel(ctx) | |
return &Group{cancel: cancel}, ctx | |
} | |
// Wait blocks until all function calls from the Go method have returned, then | |
// returns the first non-nil error (if any) from them. | |
func (g *Group) Wait() error { | |
g.wg.Wait() | |
if g.cancel != nil { | |
g.cancel() | |
} | |
return g.err | |
} | |
// Go calls the given function in a new goroutine. | |
// | |
// The first call to return a non-nil error cancels the group; its error will be | |
// returned by Wait. | |
func (g *Group) Go(f func() error) { | |
g.wg.Add(1) | |
go func() { | |
defer g.wg.Done() | |
if err := f(); err != nil { | |
g.errOnce.Do(func() { | |
g.err = err | |
if g.cancel != nil { | |
g.cancel() | |
} | |
}) | |
} | |
}() | |
} |