mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
55b53555e9
This commit fixes the readability of some of the defer calls in goroutines by making sure the defer stands out properly.
107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
package ticker
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// Force implements the Ticker interface, and provides a method of force-feeding
|
|
// ticks, even while paused.
|
|
type Force struct {
|
|
isActive uint32 // used atomically
|
|
|
|
// Force is used to force-feed a ticks into the ticker. Useful for
|
|
// debugging when trying to wake an event.
|
|
Force chan time.Time
|
|
|
|
ticker <-chan time.Time
|
|
skip chan struct{}
|
|
|
|
wg sync.WaitGroup
|
|
quit chan struct{}
|
|
}
|
|
|
|
// A compile-time constraint to ensure Force satisfies the Ticker interface.
|
|
var _ Ticker = (*Force)(nil)
|
|
|
|
// NewForce returns a Force ticker, used for testing and debugging. It supports
|
|
// the ability to force-feed events that get output by the
|
|
func NewForce(interval time.Duration) *Force {
|
|
m := &Force{
|
|
ticker: time.NewTicker(interval).C,
|
|
Force: make(chan time.Time),
|
|
skip: make(chan struct{}),
|
|
quit: make(chan struct{}),
|
|
}
|
|
|
|
// Proxy the real ticks to our Force channel if we are active.
|
|
m.wg.Add(1)
|
|
go func() {
|
|
defer m.wg.Done()
|
|
|
|
for {
|
|
select {
|
|
case t := <-m.ticker:
|
|
if atomic.LoadUint32(&m.isActive) == 0 {
|
|
continue
|
|
}
|
|
|
|
select {
|
|
case m.Force <- t:
|
|
case <-m.skip:
|
|
case <-m.quit:
|
|
return
|
|
}
|
|
|
|
case <-m.quit:
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
return m
|
|
}
|
|
|
|
// Ticks returns a receive-only channel that delivers times at the ticker's
|
|
// prescribed interval when active. Force-fed ticks can be delivered at any
|
|
// time.
|
|
//
|
|
// NOTE: Part of the Ticker interface.
|
|
func (m *Force) Ticks() <-chan time.Time {
|
|
return m.Force
|
|
}
|
|
|
|
// Resume starts underlying time.Ticker and causes the ticker to begin
|
|
// delivering scheduled events.
|
|
//
|
|
// NOTE: Part of the Ticker interface.
|
|
func (m *Force) Resume() {
|
|
atomic.StoreUint32(&m.isActive, 1)
|
|
}
|
|
|
|
// Pause suspends the underlying ticker, such that Ticks() stops signaling at
|
|
// regular intervals.
|
|
//
|
|
// NOTE: Part of the Ticker interface.
|
|
func (m *Force) Pause() {
|
|
atomic.StoreUint32(&m.isActive, 0)
|
|
|
|
// If the ticker fired and read isActive as true, it may still send the
|
|
// tick. We'll try to send on the skip channel to drop it.
|
|
select {
|
|
case m.skip <- struct{}{}:
|
|
default:
|
|
}
|
|
}
|
|
|
|
// Stop suspends the underlying ticker, such that Ticks() stops signaling at
|
|
// regular intervals, and permanently frees up any resources.
|
|
//
|
|
// NOTE: Part of the Ticker interface.
|
|
func (m *Force) Stop() {
|
|
m.Pause()
|
|
close(m.quit)
|
|
m.wg.Wait()
|
|
}
|