Files
coder/clock/ticker.go

76 lines
1.8 KiB
Go

package clock
import "time"
// A Ticker holds a channel that delivers “ticks” of a clock at intervals.
type Ticker struct {
C <-chan time.Time
//nolint: revive
c chan time.Time
ticker *time.Ticker // realtime impl, if set
d time.Duration // period, if set
nxt time.Time // next tick time
mock *Mock // mock clock, if set
stopped bool // true if the ticker is not running
}
func (t *Ticker) fire(tt time.Time) {
t.mock.mu.Lock()
defer t.mock.mu.Unlock()
if t.stopped {
return
}
for !t.nxt.After(t.mock.cur) {
t.nxt = t.nxt.Add(t.d)
}
t.mock.recomputeNextLocked()
select {
case t.c <- tt:
default:
}
}
func (t *Ticker) next() time.Time {
return t.nxt
}
// Stop turns off a ticker. After Stop, no more ticks will be sent. Stop does
// not close the channel, to prevent a concurrent goroutine reading from the
// channel from seeing an erroneous "tick".
func (t *Ticker) Stop(tags ...string) {
if t.ticker != nil {
t.ticker.Stop()
return
}
t.mock.mu.Lock()
defer t.mock.mu.Unlock()
c := newCall(clockFunctionTickerStop, tags)
t.mock.matchCallLocked(c)
defer close(c.complete)
t.mock.removeEventLocked(t)
t.stopped = true
}
// Reset stops a ticker and resets its period to the specified duration. The
// next tick will arrive after the new period elapses. The duration d must be
// greater than zero; if not, Reset will panic.
func (t *Ticker) Reset(d time.Duration, tags ...string) {
if t.ticker != nil {
t.ticker.Reset(d)
return
}
t.mock.mu.Lock()
defer t.mock.mu.Unlock()
c := newCall(clockFunctionTickerReset, tags, withDuration(d))
t.mock.matchCallLocked(c)
defer close(c.complete)
t.nxt = t.mock.cur.Add(d)
t.d = d
if t.stopped {
t.stopped = false
t.mock.addEventLocked(t)
} else {
t.mock.recomputeNextLocked()
}
}