From 6bf182e341db390d3e05db9de72dba08b8d73c44 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Wed, 17 Jul 2019 21:15:02 -0500 Subject: [PATCH] add util.CancellationChild() and run gofmt --- src/util/cancellation.go | 109 +++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/src/util/cancellation.go b/src/util/cancellation.go index 1433c734..fa980084 100644 --- a/src/util/cancellation.go +++ b/src/util/cancellation.go @@ -1,83 +1,94 @@ package util import ( - "errors" - "sync" - "time" - "runtime" + "errors" + "runtime" + "sync" + "time" ) type Cancellation interface { - Finished() <-chan struct{} - Cancel(error) error - Error() error + Finished() <-chan struct{} + Cancel(error) error + Error() error } func CancellationFinalizer(c Cancellation) { - c.Cancel(errors.New("finalizer called")) + c.Cancel(errors.New("finalizer called")) } type cancellation struct { - signal chan error - cancel chan struct{} - errMtx sync.RWMutex - err error + signal chan error + cancel chan struct{} + errMtx sync.RWMutex + err error } func (c *cancellation) worker() { - // Launch this in a separate goroutine when creating a cancellation - err := <-c.signal - c.errMtx.Lock() - c.err = err - c.errMtx.Unlock() - close(c.cancel) + // Launch this in a separate goroutine when creating a cancellation + err := <-c.signal + c.errMtx.Lock() + c.err = err + c.errMtx.Unlock() + close(c.cancel) } func NewCancellation() Cancellation { - c := cancellation{ - signal: make(chan error), - cancel: make(chan struct{}), - } - runtime.SetFinalizer(&c, CancellationFinalizer) - go c.worker() - return &c + c := cancellation{ + signal: make(chan error), + cancel: make(chan struct{}), + } + runtime.SetFinalizer(&c, CancellationFinalizer) + go c.worker() + return &c } func (c *cancellation) Finished() <-chan struct{} { - return c.cancel + return c.cancel } func (c *cancellation) Cancel(err error) error { - select { - case c.signal<-err: - return nil - case <-c.cancel: - return c.Error() - } + select { + case c.signal <- err: + return nil + case <-c.cancel: + return c.Error() + } } func (c *cancellation) Error() error { - c.errMtx.RLock() - err := c.err - c.errMtx.RUnlock() - return err + c.errMtx.RLock() + err := c.err + c.errMtx.RUnlock() + return err +} + +func CancellationChild(parent Cancellation) Cancellation { + child := NewCancellation() + go func() { + select { + case <-child.Finished(): + case <-parent.Finished(): + child.Cancel(parent.Error()) + } + }() + return child } func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancellation { - child := NewCancellation() - go func() { - timer := time.NewTimer(timeout) - defer TimerStop(timer) - select { - case <-parent.Finished(): - child.Cancel(parent.Error()) - case <-timer.C: - child.Cancel(errors.New("timeout")) - } - }() - return child + child := CancellationChild(parent) + go func() { + timer := time.NewTimer(timeout) + defer TimerStop(timer) + select { + case <-child.Finished(): + case <-timer.C: + child.Cancel(errors.New("timeout")) + } + }() + return child } func CancellationWithDeadline(parent Cancellation, deadline time.Time) Cancellation { - return CancellationWithTimeout(parent, deadline.Sub(time.Now())) + return CancellationWithTimeout(parent, deadline.Sub(time.Now())) }