github.com/searKing/golang/go@v1.2.117/time/sleep.go (about) 1 // Copyright 2020 The searKing Author. 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 time 6 7 import ( 8 "time" 9 ) 10 11 // Timer to fix time: Timer.Stop documentation example easily leads to deadlocks 12 // https://github.com/golang/go/issues/27169 13 type Timer struct { 14 *time.Timer 15 } 16 17 // Stop prevents the Timer from firing, with the channel drained. 18 // Stop ensures the channel is empty after a call to Stop. 19 // Stop == std [Stop + drain] 20 // It returns true if the call stops the timer, false if the timer has already 21 // expired or been stopped. 22 // Stop does not close the channel, to prevent a read from the channel succeeding 23 // incorrectly. 24 func (t *Timer) Stop() bool { 25 if t.Timer == nil { 26 panic("time: Stop called on uninitialized Timer") 27 } 28 29 active := t.Timer.Stop() 30 if !active { 31 // drain the channel, prevents the Timer from blocking on Send to t.C by sendTime, t.C is reused. 32 // The underlying Timer is not recovered by the garbage collector until the timer fires. 33 // consume the channel only once for the channel can be triggered only one time at most before Stop is called. 34 L: 35 for { 36 select { 37 case _, ok := <-t.Timer.C: 38 if !ok { 39 break L 40 } 41 default: 42 break L 43 } 44 } 45 } 46 return active 47 } 48 49 // Reset changes the timer to expire after duration d. 50 // Reset can be invoked anytime, which enhances std time.Reset 51 // Reset == std [Stop + drain + Reset] 52 // It returns true if the timer had been active, false if the timer had 53 // expired or been stopped. 54 func (t *Timer) Reset(d time.Duration) bool { 55 if t.Timer == nil { 56 panic("time: Reset called on uninitialized Timer") 57 } 58 active := t.Stop() 59 t.Timer.Reset(d) 60 return active 61 } 62 63 func NewTimer(d time.Duration) *Timer { 64 return &Timer{ 65 Timer: time.NewTimer(d), 66 } 67 } 68 69 func WrapTimer(t *time.Timer) *Timer { 70 return &Timer{ 71 Timer: t, 72 } 73 } 74 75 func After(d time.Duration) <-chan time.Time { 76 return NewTimer(d).C 77 } 78 79 func AfterFunc(d time.Duration, f func()) *Timer { 80 t := &Timer{} 81 t.Timer = time.AfterFunc(d, func() { 82 f() 83 }) 84 return t 85 }