You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.5 KiB
62 lines
1.5 KiB
// Package tdsync contains some useful synchronization utilities. |
|
package tdsync |
|
|
|
import ( |
|
"context" |
|
|
|
"golang.org/x/sync/errgroup" |
|
) |
|
|
|
// CancellableGroup is simple wrapper around |
|
// errgroup.Group to make group cancellation easier. |
|
// Unlike WaitGroup and errgroup.Group this is not allowed to use zero value. |
|
type CancellableGroup struct { |
|
cancel context.CancelFunc |
|
|
|
group *errgroup.Group |
|
ctx context.Context |
|
} |
|
|
|
// NewCancellableGroup creates new CancellableGroup. |
|
// |
|
// Example: |
|
// g := NewCancellableGroup(ctx) |
|
// g.Go(func(ctx context.Context) error { |
|
// <-ctx.Done() |
|
// return ctx.Err() |
|
// }) |
|
// g.Cancel() |
|
// g.Wait() |
|
func NewCancellableGroup(parent context.Context) *CancellableGroup { |
|
ctx, cancel := context.WithCancel(parent) |
|
group, groupCtx := errgroup.WithContext(ctx) |
|
|
|
return &CancellableGroup{ |
|
cancel: cancel, |
|
group: group, |
|
ctx: groupCtx, |
|
} |
|
} |
|
|
|
// 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 *CancellableGroup) Go(f func(ctx context.Context) error) { |
|
g.group.Go(func() error { |
|
return f(g.ctx) |
|
}) |
|
} |
|
|
|
// Cancel cancels all goroutines in group. |
|
// |
|
// Note: context cancellation error will be returned by Wait(). |
|
func (g *CancellableGroup) Cancel() { |
|
g.cancel() |
|
} |
|
|
|
// 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 *CancellableGroup) Wait() error { |
|
return g.group.Wait() |
|
}
|
|
|