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
 | 
			
		||||
 | 
			
		||||
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()))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue