Skip to content

Instantly share code, notes, and snippets.

@virtuald
Created September 13, 2018 00:38
Show Gist options
  • Save virtuald/943a6296d0fdba28a5a0bb1788603553 to your computer and use it in GitHub Desktop.
Save virtuald/943a6296d0fdba28a5a0bb1788603553 to your computer and use it in GitHub Desktop.
Similar to golang.org/x/sync/errgroup
package anyerr
// portions derived from golang context package, BSD license
import (
"github.com/hashicorp/go-multierror"
"sync"
)
// closedchan is a reusable closed channel.
var closedchan = make(chan struct{})
func init() {
close(closedchan)
}
// AnyError guarantees that at least one error is propagated to the waiter,
// and that any error callers will not have to wait to pass the error in
type AnyError interface {
// Marks this object as done, with an optional error
SetDone(err error)
// Similar to context.Done, returns a channel that's closed when the
// object is done
Done() <-chan struct{}
// Returns any error that is signaled. If multiple errors are signaled,
// a go-multierror derived error is returned
Error() error
}
// NewAnyError constructs an AnyError object
func NewAnyError() AnyError {
return &anyError{}
}
type anyError struct {
done chan struct{}
mu sync.Mutex
err error
}
func (ae *anyError) SetDone(err error) {
ae.mu.Lock()
if ae.done == nil {
ae.done = closedchan
}
if err != nil {
ae.err = multierror.Append(ae.err, err)
}
ae.mu.Unlock()
}
func (ae *anyError) Done() <-chan struct{} {
ae.mu.Lock()
if ae.done == nil {
ae.done = make(chan struct{})
}
done := ae.done
ae.mu.Unlock()
return done
}
func (ae *anyError) Error() error {
ae.mu.Lock()
defer ae.mu.Unlock()
return ae.err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment