44 lines
957 B
Go
44 lines
957 B
Go
package utils
|
|
|
|
import "time"
|
|
|
|
// A Timer wrapper that behaves correctly when resetting
|
|
type Timer struct {
|
|
t *time.Timer
|
|
read bool
|
|
deadline time.Time
|
|
}
|
|
|
|
// NewTimer creates a new timer that is not set
|
|
func NewTimer() *Timer {
|
|
return &Timer{t: time.NewTimer(0)}
|
|
}
|
|
|
|
// Chan returns the channel of the wrapped timer
|
|
func (t *Timer) Chan() <-chan time.Time {
|
|
return t.t.C
|
|
}
|
|
|
|
// Reset the timer, no matter whether the value was read or not
|
|
func (t *Timer) Reset(deadline time.Time) {
|
|
if deadline.Equal(t.deadline) {
|
|
// No need to reset the timer
|
|
return
|
|
}
|
|
|
|
// We need to drain the timer if the value from its channel was not read yet.
|
|
// See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
|
|
if !t.t.Stop() && !t.read {
|
|
<-t.t.C
|
|
}
|
|
t.t.Reset(deadline.Sub(time.Now()))
|
|
|
|
t.read = false
|
|
t.deadline = deadline
|
|
}
|
|
|
|
// SetRead should be called after the value from the chan was read
|
|
func (t *Timer) SetRead() {
|
|
t.read = true
|
|
}
|