github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/canceler/instance.go (about)

     1  package canceler
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/sagernet/sing/common"
    10  )
    11  
    12  type Instance struct {
    13  	ctx        context.Context
    14  	cancelFunc common.ContextCancelCauseFunc
    15  	timer      *time.Timer
    16  	timeout    time.Duration
    17  }
    18  
    19  func New(ctx context.Context, cancelFunc common.ContextCancelCauseFunc, timeout time.Duration) *Instance {
    20  	instance := &Instance{
    21  		ctx,
    22  		cancelFunc,
    23  		time.NewTimer(timeout),
    24  		timeout,
    25  	}
    26  	go instance.wait()
    27  	return instance
    28  }
    29  
    30  func (i *Instance) Update() bool {
    31  	if !i.timer.Stop() {
    32  		return false
    33  	}
    34  	if !i.timer.Reset(i.timeout) {
    35  		return false
    36  	}
    37  	return true
    38  }
    39  
    40  func (i *Instance) Timeout() time.Duration {
    41  	return i.timeout
    42  }
    43  
    44  func (i *Instance) SetTimeout(timeout time.Duration) {
    45  	i.timeout = timeout
    46  	i.Update()
    47  }
    48  
    49  func (i *Instance) wait() {
    50  	select {
    51  	case <-i.timer.C:
    52  	case <-i.ctx.Done():
    53  	}
    54  	i.CloseWithError(os.ErrDeadlineExceeded)
    55  }
    56  
    57  func (i *Instance) Close() error {
    58  	i.CloseWithError(net.ErrClosed)
    59  	return nil
    60  }
    61  
    62  func (i *Instance) CloseWithError(err error) {
    63  	i.timer.Stop()
    64  	i.cancelFunc(err)
    65  }