lnd.xprv/ticker/ticker.go
Wilmer Paulino faccccf93f
ticker/ticker: rename ticker -> T
In this commit, we rename the previously unexported ticker into T,
making it exported along the way. This is nice as we now have access to
the actual interface implementation without the need of making further
type assertions.
2019-02-12 16:05:24 -08:00

127 lines
3.6 KiB
Go

package ticker
import "time"
// Ticker defines a resumable ticker interface, whose activity can be toggled to
// free up resources during periods of inactivity.
//
// Example of resuming ticker:
//
// ticker.Resume() // can remove to keep inactive at first
// defer ticker.Stop()
// for {
// select {
// case <-ticker.Tick():
// if shouldGoInactive {
// ticker.Pause()
// continue
// }
// ...
//
// case <-otherEvent:
// ...
// if shouldGoActive {
// ticker.Resume()
// }
// }
//
// NOTE: ONE DOES NOT SIMPLY assume that Tickers are safe for concurrent access.
type Ticker interface {
// Ticks returns a read-only channel delivering ticks according to a
// prescribed interval. The value returned does not need to be the same
// channel, and may be nil.
//
// NOTE: Callers should assume that reads from Ticks() are stale after
// any invocations of Resume, Pause, or Stop.
Ticks() <-chan time.Time
// Resume starts or resumes the underlying ticker, such that Ticks()
// will fire at regular intervals. After calling Resume, Ticks() should
// minimally send ticks at the prescribed interval.
//
// NOTE: It MUST be safe to call Resume at any time, and more than once
// successively.
Resume()
// Pause suspends the underlying ticker, such that Ticks() stops
// signaling at regular intervals. After calling Pause, the ticker
// should not send any ticks scheduled with the chosen interval. Forced
// ticks are still permissible, as in the case of the Mock Ticker.
//
// NOTE: It MUST be safe to call Pause at any time, and more than once
// successively.
Pause()
// Stop suspends the underlying ticker, such that Ticks() stops
// signaling at regular intervals, and permanently frees up any
// remaining resources.
//
// NOTE: The behavior of a Ticker is undefined after calling Stop.
Stop()
}
// T is the production implementation of the resumable Ticker interface. This
// allows various components to toggle their need for tick events, which may
// vary depending on system load.
type T struct {
// interval is the desired duration between ticks when active.
interval time.Duration
// ticker is the ephemeral, underlying time.Ticker. We keep a reference
// to this ticker so that it can be stopped and cleaned up on Pause or
// Stop.
ticker *time.Ticker
}
// A compile-time constraint to ensure T satisfies the Ticker interface.
var _ Ticker = (*T)(nil)
// New returns a new ticker that signals with the given interval when not
// paused. The ticker starts off inactive.
func New(interval time.Duration) *T {
return &T{
interval: interval,
}
}
// Ticks returns a receive-only channel that delivers times at the ticker's
// prescribed interval. This method returns nil when the ticker is paused.
//
// NOTE: Part of the Ticker interface.
func (t *T) Ticks() <-chan time.Time {
if t.ticker == nil {
return nil
}
return t.ticker.C
}
// Resume starts underlying time.Ticker and causes the ticker to begin
// delivering scheduled events.
//
// NOTE: Part of the Ticker interface.
func (t *T) Resume() {
if t.ticker == nil {
t.ticker = time.NewTicker(t.interval)
}
}
// Pause suspends the underlying ticker, such that Ticks() stops signaling at
// regular intervals.
//
// NOTE: Part of the Ticker interface.
func (t *T) Pause() {
if t.ticker != nil {
t.ticker.Stop()
t.ticker = nil
}
}
// Stop suspends the underlying ticker, such that Ticks() stops signaling at
// regular intervals, and permanently frees up any resources. For this
// implementation, this is equivalent to Pause.
//
// NOTE: Part of the Ticker interface.
func (t *T) Stop() {
t.Pause()
}