mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	add util.CancellationChild() and run gofmt
This commit is contained in:
		
							parent
							
								
									06e8403aaf
								
							
						
					
					
						commit
						6bf182e341
					
				
					 1 changed files with 60 additions and 49 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue