-
Notifications
You must be signed in to change notification settings - Fork 61
/
group.go
71 lines (60 loc) · 1.77 KB
/
group.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package wait
import (
"sync"
)
type Group struct {
sync.Mutex
waitables []Waitable
}
// NewGroup returns a newly instantiated `Group` object. This instance can collect
// objects implementing the `algolia.Waitable` interface, including most of the
// Algolia response objects, and wait for their completion in a concurrent
// fashion.
func NewGroup() *Group {
return new(Group)
}
// Wait blocks until all the given `algolia.Waitable` objects have completed. If
// one of the objects returned an error upon `Wait` invocation, this error is
// returned. Otherwise, nil is returned.
func Wait(waitables ...Waitable) error {
g := NewGroup()
g.Collect(waitables...)
return g.Wait()
}
// Collect holds references to the given `algolia.Waitable` objects in order to
// wait for their completion once the `Wait` method will be invoked. Calling
// `Collect` from multiple goroutines is safe.
func (a *Group) Collect(waitables ...Waitable) {
a.Lock()
a.waitables = append(a.waitables, waitables...)
a.Unlock()
}
// Wait blocks until all the collected `algolia.Waitable` objects have
// completed. If one of the objects returned an error upon `Wait` invocation,
// this error is returned. Otherwise, nil is returned. Calling `Wait` from
// multiple goroutines is safe.
//
// Upon successful completion, the `Group` object can be reused directly to
// collect other `algolia.Waitable` objects.
func (a *Group) Wait() error {
a.Lock()
defer a.Unlock()
var wg sync.WaitGroup
errs := make(chan error, len(a.waitables))
for _, w := range a.waitables {
wg.Add(1)
go func(wg *sync.WaitGroup, w Waitable, errs chan<- error) {
errs <- w.Wait()
wg.Done()
}(&wg, w, errs)
}
wg.Wait()
close(errs)
a.waitables = nil
for err := range errs {
if err != nil {
return err
}
}
return nil
}