54 lines
1.0 KiB
Go
54 lines
1.0 KiB
Go
|
package sync
|
||
|
|
||
|
import "sync"
|
||
|
|
||
|
// OnceErr wraps the behavior of recording an error
|
||
|
// once and signal on a channel when this has occurred.
|
||
|
// Signaling is done by closing of the channel.
|
||
|
//
|
||
|
// Type is safe for concurrent usage.
|
||
|
type OnceErr struct {
|
||
|
mu sync.RWMutex
|
||
|
err error
|
||
|
ch chan struct{}
|
||
|
}
|
||
|
|
||
|
// NewOnceErr return a new OnceErr
|
||
|
func NewOnceErr() *OnceErr {
|
||
|
return &OnceErr{
|
||
|
ch: make(chan struct{}, 1),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Err acquires a read-lock and returns an
|
||
|
// error if one has been set.
|
||
|
func (e *OnceErr) Err() error {
|
||
|
e.mu.RLock()
|
||
|
err := e.err
|
||
|
e.mu.RUnlock()
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// SetError acquires a write-lock and will set
|
||
|
// the underlying error value if one has not been set.
|
||
|
func (e *OnceErr) SetError(err error) {
|
||
|
if err == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
e.mu.Lock()
|
||
|
if e.err == nil {
|
||
|
e.err = err
|
||
|
close(e.ch)
|
||
|
}
|
||
|
e.mu.Unlock()
|
||
|
}
|
||
|
|
||
|
// ErrorSet returns a channel that will be used to signal
|
||
|
// that an error has been set. This channel will be closed
|
||
|
// when the error value has been set for OnceErr.
|
||
|
func (e *OnceErr) ErrorSet() <-chan struct{} {
|
||
|
return e.ch
|
||
|
}
|