@@ -20,7 +20,8 @@ type ErrSizedGroup struct {
2020}
2121
2222// NewErrSizedGroup makes wait group with limited size alive goroutines.
23- // By default all goroutines will be started but will wait inside. For limited number of goroutines use Preemptive() options.
23+ // By default, all goroutines will be started but will wait inside.
24+ // For limited number of goroutines use Preemptive() options.
2425// TermOnErr will skip (won't start) all other goroutines if any error returned.
2526func NewErrSizedGroup (size int , options ... GroupOption ) * ErrSizedGroup {
2627 res := ErrSizedGroup {
@@ -39,6 +40,27 @@ func NewErrSizedGroup(size int, options ...GroupOption) *ErrSizedGroup {
3940// The first call to return a non-nil error cancels the group if termOnError; its error will be
4041// returned by Wait. If no termOnError all errors will be collected in multierror.
4142func (g * ErrSizedGroup ) Go (f func () error ) {
43+
44+ canceled := func () bool {
45+ if g .ctx == nil {
46+ return false
47+ }
48+ select {
49+ case <- g .ctx .Done ():
50+ return true
51+ default :
52+ return false
53+ }
54+ }
55+
56+ if canceled () {
57+ g .errOnce .Do (func () {
58+ // don't repeat this error
59+ g .err .append (g .ctx .Err ())
60+ })
61+ return
62+ }
63+
4264 g .wg .Add (1 )
4365
4466 isLocked := false
@@ -87,16 +109,9 @@ func (g *ErrSizedGroup) Go(f func() error) {
87109 }
88110
89111 if err := f (); err != nil {
90-
91112 g .errLock .Lock ()
92113 g .err = g .err .append (err )
93114 g .errLock .Unlock ()
94-
95- g .errOnce .Do (func () { // call context cancel once
96- if g .cancel != nil {
97- g .cancel ()
98- }
99- })
100115 }
101116 }()
102117}
@@ -105,9 +120,6 @@ func (g *ErrSizedGroup) Go(f func() error) {
105120// returns all errors (if any) wrapped with multierror from them.
106121func (g * ErrSizedGroup ) Wait () error {
107122 g .wg .Wait ()
108- if g .cancel != nil {
109- g .cancel ()
110- }
111123 return g .err .errorOrNil ()
112124}
113125
0 commit comments