Source File
ticker.go
Belonging Package
go.pact.im/x/clock
package clock
import (
)
// TickerScheduler is the interface implemented by a clock that provides an
// optimized implementation of Ticker.
type TickerScheduler interface {
Scheduler
// Ticker returns a new Ticker containing a channel that will send the time
// on the channel after each tick. The period of the ticks is specified by the
// duration argument. The ticker will adjust the time interval or drop ticks to
// make up for slow receivers. The duration d must be greater than zero; if
// not, Ticker will panic. Stop the ticker to release associated resources.
Ticker(d time.Duration) Ticker
}
// A Ticker holds a channel that delivers “ticks” of a clock at intervals.
type Ticker interface {
// C returns the channel on which the ticks are delivered.
C() <-chan time.Time
// 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”.
Stop()
// 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.
Reset(d time.Duration)
}
// Ticker returns a new Ticker containing a channel that will send the current
// time on the channel after each tick. The period of the ticks is specified by
// the duration argument. The ticker will adjust the time interval or drop ticks
// to make up for slow receivers. The duration d must be greater than zero; if
// not, Ticker will panic. Stop the ticker to release associated resources.
//
// Unless the underlying Scheduler implements TickerScheduler, Ticker calls
// Timer and resets the returned timer on each tick.
func ( *Clock) ( time.Duration) Ticker {
if <= 0 {
panic("non-positive interval for Ticker")
}
:= .sched()
if , := .(TickerScheduler); {
return .Ticker()
}
return newEventTicker(, )
}
// eventTicker implements Ticker interface using a Timer. It intercepts timer’s
// channel and then resets it to continue ticking.
type eventTicker struct {
t Timer
c chan time.Time
mu sync.Mutex
wg sync.WaitGroup
resetc chan time.Duration
stopc chan struct{}
stopped bool
resetTimer bool
}
func ( *Clock, time.Duration) *eventTicker {
:= &eventTicker{
t: .Timer(),
c: make(chan time.Time, 1),
resetc: make(chan time.Duration),
stopc: make(chan struct{}),
}
.start()
return
}
// C implements the Ticker interface.
func ( *eventTicker) () <-chan time.Time {
return .c
}
// Stop implements the Ticker interface.
func ( *eventTicker) () {
.stop()
}
// Reset implements the Ticker interface.
func ( *eventTicker) ( time.Duration) {
if <= 0 {
panic("non-positive interval for Ticker.Reset")
}
.reset()
}
func ( *eventTicker) ( time.Duration) {
.wg.Add(1)
go func() {
defer .wg.Done()
.run()
}()
}
func ( *eventTicker) ( time.Duration) {
:= .t
:= .C()
if .resetTimer {
.Reset()
}
.resetTimer = true
for {
select {
case <-.stopc:
.stopTimer()
return
case = <-.resetc:
.stopTimer()
.Reset()
case := <-:
.Reset()
select {
case .c <- :
default:
}
}
}
}
func ( *eventTicker) ( time.Duration) {
.mu.Lock()
defer .mu.Unlock()
if .stopped {
.stopped = false
.start()
return
}
.resetc <-
}
func ( *eventTicker) () {
.mu.Lock()
defer .mu.Unlock()
if .stopped {
return
}
.stopped = true
.stopc <- struct{}{}
.wg.Wait()
}
func ( *eventTicker) () {
if .t.Stop() {
return
}
<-.t.C()
}
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)