You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.6 KiB
126 lines
3.6 KiB
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 Force 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() |
|
}
|
|
|