mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-12-24 16:57:53 +00:00
add util.CancellationChild() and run gofmt
This commit is contained in:
parent
06e8403aaf
commit
6bf182e341
@ -1,83 +1,94 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"runtime"
|
||||||
"time"
|
"sync"
|
||||||
"runtime"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cancellation interface {
|
type Cancellation interface {
|
||||||
Finished() <-chan struct{}
|
Finished() <-chan struct{}
|
||||||
Cancel(error) error
|
Cancel(error) error
|
||||||
Error() error
|
Error() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancellationFinalizer(c Cancellation) {
|
func CancellationFinalizer(c Cancellation) {
|
||||||
c.Cancel(errors.New("finalizer called"))
|
c.Cancel(errors.New("finalizer called"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type cancellation struct {
|
type cancellation struct {
|
||||||
signal chan error
|
signal chan error
|
||||||
cancel chan struct{}
|
cancel chan struct{}
|
||||||
errMtx sync.RWMutex
|
errMtx sync.RWMutex
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cancellation) worker() {
|
func (c *cancellation) worker() {
|
||||||
// Launch this in a separate goroutine when creating a cancellation
|
// Launch this in a separate goroutine when creating a cancellation
|
||||||
err := <-c.signal
|
err := <-c.signal
|
||||||
c.errMtx.Lock()
|
c.errMtx.Lock()
|
||||||
c.err = err
|
c.err = err
|
||||||
c.errMtx.Unlock()
|
c.errMtx.Unlock()
|
||||||
close(c.cancel)
|
close(c.cancel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCancellation() Cancellation {
|
func NewCancellation() Cancellation {
|
||||||
c := cancellation{
|
c := cancellation{
|
||||||
signal: make(chan error),
|
signal: make(chan error),
|
||||||
cancel: make(chan struct{}),
|
cancel: make(chan struct{}),
|
||||||
}
|
}
|
||||||
runtime.SetFinalizer(&c, CancellationFinalizer)
|
runtime.SetFinalizer(&c, CancellationFinalizer)
|
||||||
go c.worker()
|
go c.worker()
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cancellation) Finished() <-chan struct{} {
|
func (c *cancellation) Finished() <-chan struct{} {
|
||||||
return c.cancel
|
return c.cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cancellation) Cancel(err error) error {
|
func (c *cancellation) Cancel(err error) error {
|
||||||
select {
|
select {
|
||||||
case c.signal<-err:
|
case c.signal <- err:
|
||||||
return nil
|
return nil
|
||||||
case <-c.cancel:
|
case <-c.cancel:
|
||||||
return c.Error()
|
return c.Error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cancellation) Error() error {
|
func (c *cancellation) Error() error {
|
||||||
c.errMtx.RLock()
|
c.errMtx.RLock()
|
||||||
err := c.err
|
err := c.err
|
||||||
c.errMtx.RUnlock()
|
c.errMtx.RUnlock()
|
||||||
return err
|
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 {
|
func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancellation {
|
||||||
child := NewCancellation()
|
child := CancellationChild(parent)
|
||||||
go func() {
|
go func() {
|
||||||
timer := time.NewTimer(timeout)
|
timer := time.NewTimer(timeout)
|
||||||
defer TimerStop(timer)
|
defer TimerStop(timer)
|
||||||
select {
|
select {
|
||||||
case <-parent.Finished():
|
case <-child.Finished():
|
||||||
child.Cancel(parent.Error())
|
case <-timer.C:
|
||||||
case <-timer.C:
|
child.Cancel(errors.New("timeout"))
|
||||||
child.Cancel(errors.New("timeout"))
|
}
|
||||||
}
|
}()
|
||||||
}()
|
return child
|
||||||
return child
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancellationWithDeadline(parent Cancellation, deadline time.Time) Cancellation {
|
func CancellationWithDeadline(parent Cancellation, deadline time.Time) Cancellation {
|
||||||
return CancellationWithTimeout(parent, deadline.Sub(time.Now()))
|
return CancellationWithTimeout(parent, deadline.Sub(time.Now()))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user