]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/oklog/run/group.go
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / oklog / run / group.go
CommitLineData
15c0b25d
AP
1// Package run implements an actor-runner with deterministic teardown. It is
2// somewhat similar to package errgroup, except it does not require actor
3// goroutines to understand context semantics. This makes it suitable for use in
4// more circumstances; for example, goroutines which are handling connections
5// from net.Listeners, or scanning input from a closable io.Reader.
6package run
7
8// Group collects actors (functions) and runs them concurrently.
9// When one actor (function) returns, all actors are interrupted.
10// The zero value of a Group is useful.
11type Group struct {
12 actors []actor
13}
14
15// Add an actor (function) to the group. Each actor must be pre-emptable by an
16// interrupt function. That is, if interrupt is invoked, execute should return.
17// Also, it must be safe to call interrupt even after execute has returned.
18//
19// The first actor (function) to return interrupts all running actors.
20// The error is passed to the interrupt functions, and is returned by Run.
21func (g *Group) Add(execute func() error, interrupt func(error)) {
22 g.actors = append(g.actors, actor{execute, interrupt})
23}
24
25// Run all actors (functions) concurrently.
26// When the first actor returns, all others are interrupted.
27// Run only returns when all actors have exited.
28// Run returns the error returned by the first exiting actor.
29func (g *Group) Run() error {
30 if len(g.actors) == 0 {
31 return nil
32 }
33
34 // Run each actor.
35 errors := make(chan error, len(g.actors))
36 for _, a := range g.actors {
37 go func(a actor) {
38 errors <- a.execute()
39 }(a)
40 }
41
42 // Wait for the first actor to stop.
43 err := <-errors
44
45 // Signal all actors to stop.
46 for _, a := range g.actors {
47 a.interrupt(err)
48 }
49
50 // Wait for all actors to stop.
51 for i := 1; i < cap(errors); i++ {
52 <-errors
53 }
54
55 // Return the original error.
56 return err
57}
58
59type actor struct {
60 execute func() error
61 interrupt func(error)
62}