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 }