54 lines
1.1 KiB
Go
54 lines
1.1 KiB
Go
package utils
|
|
|
|
import (
|
|
"math"
|
|
"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(time.Duration(math.MaxInt64))}
|
|
}
|
|
|
|
// 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) && !t.read {
|
|
// 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
|
|
}
|
|
if !deadline.IsZero() {
|
|
t.t.Reset(time.Until(deadline))
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// Stop stops the timer
|
|
func (t *Timer) Stop() {
|
|
t.t.Stop()
|
|
}
|