github.com/kelleygo/clashcore@v1.0.2/common/net/deadline/pipe.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package deadline 6 7 import ( 8 "sync" 9 "time" 10 ) 11 12 // pipeDeadline is an abstraction for handling timeouts. 13 type pipeDeadline struct { 14 mu sync.Mutex // Guards timer and cancel 15 timer *time.Timer 16 cancel chan struct{} // Must be non-nil 17 } 18 19 func makePipeDeadline() pipeDeadline { 20 return pipeDeadline{cancel: make(chan struct{})} 21 } 22 23 // set sets the point in time when the deadline will time out. 24 // A timeout event is signaled by closing the channel returned by waiter. 25 // Once a timeout has occurred, the deadline can be refreshed by specifying a 26 // t value in the future. 27 // 28 // A zero value for t prevents timeout. 29 func (d *pipeDeadline) set(t time.Time) { 30 d.mu.Lock() 31 defer d.mu.Unlock() 32 33 if d.timer != nil && !d.timer.Stop() { 34 <-d.cancel // Wait for the timer callback to finish and close cancel 35 } 36 d.timer = nil 37 38 // Time is zero, then there is no deadline. 39 closed := isClosedChan(d.cancel) 40 if t.IsZero() { 41 if closed { 42 d.cancel = make(chan struct{}) 43 } 44 return 45 } 46 47 // Time in the future, setup a timer to cancel in the future. 48 if dur := time.Until(t); dur > 0 { 49 if closed { 50 d.cancel = make(chan struct{}) 51 } 52 d.timer = time.AfterFunc(dur, func() { 53 close(d.cancel) 54 }) 55 return 56 } 57 58 // Time in the past, so close immediately. 59 if !closed { 60 close(d.cancel) 61 } 62 } 63 64 // wait returns a channel that is closed when the deadline is exceeded. 65 func (d *pipeDeadline) wait() chan struct{} { 66 d.mu.Lock() 67 defer d.mu.Unlock() 68 return d.cancel 69 } 70 71 func isClosedChan(c <-chan struct{}) bool { 72 select { 73 case <-c: 74 return true 75 default: 76 return false 77 } 78 } 79 80 func makeFilledChan() chan struct{} { 81 ch := make(chan struct{}, 1) 82 ch <- struct{}{} 83 return ch 84 }