util: Add context wait signal to easy exit
Add an alternate way to wait for a signal. This just makes code look a bit cleaner and less cluttered.
This commit is contained in:
21
util/sync.go
21
util/sync.go
@@ -18,6 +18,7 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,11 +67,13 @@ func (obj *EasyOnce) Done() {
|
|||||||
|
|
||||||
// EasyExit is a struct that helps you build a close switch and signal which can
|
// EasyExit is a struct that helps you build a close switch and signal which can
|
||||||
// be called multiple times safely, and used as a signal many times in parallel.
|
// be called multiple times safely, and used as a signal many times in parallel.
|
||||||
|
// It can also provide a context, if you prefer to use that as a signal instead.
|
||||||
type EasyExit struct {
|
type EasyExit struct {
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
exit chan struct{}
|
exit chan struct{}
|
||||||
once *sync.Once
|
once *sync.Once
|
||||||
err error
|
err error
|
||||||
|
wg *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEasyExit builds an easy exit struct.
|
// NewEasyExit builds an easy exit struct.
|
||||||
@@ -79,6 +82,7 @@ func NewEasyExit() *EasyExit {
|
|||||||
mutex: &sync.Mutex{},
|
mutex: &sync.Mutex{},
|
||||||
exit: make(chan struct{}),
|
exit: make(chan struct{}),
|
||||||
once: &sync.Once{},
|
once: &sync.Once{},
|
||||||
|
wg: &sync.WaitGroup{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +108,22 @@ func (obj *EasyExit) Signal() <-chan struct{} {
|
|||||||
return obj.exit
|
return obj.exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Context returns a context that is canceled when the Done signal is triggered.
|
||||||
|
// This can be used in addition to or instead of the Signal method.
|
||||||
|
func (obj *EasyExit) Context() context.Context {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
obj.wg.Add(1) // prevent leaks
|
||||||
|
go func() {
|
||||||
|
defer obj.wg.Done()
|
||||||
|
defer cancel()
|
||||||
|
select {
|
||||||
|
case <-obj.Signal():
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
// Error returns the error condition associated with the Done signal. It blocks
|
// Error returns the error condition associated with the Done signal. It blocks
|
||||||
// until Done is called at least once. It then returns any of the errors or nil.
|
// until Done is called at least once. It then returns any of the errors or nil.
|
||||||
// It is only guaranteed to at least return the error from the first Done error.
|
// It is only guaranteed to at least return the error from the first Done error.
|
||||||
@@ -111,5 +131,6 @@ func (obj *EasyExit) Error() error {
|
|||||||
select {
|
select {
|
||||||
case <-obj.exit:
|
case <-obj.exit:
|
||||||
}
|
}
|
||||||
|
obj.wg.Wait() // wait for cleanup
|
||||||
return obj.err
|
return obj.err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user