mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
76 lines
1.8 KiB
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()
|
|
}
|
|
}
|