[#708] morph/timer: Add single tick timer

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-07-21 17:28:59 +03:00 committed by Alex Vanin
parent 7146afcd28
commit 67b3682348
2 changed files with 76 additions and 6 deletions

View file

@ -31,6 +31,8 @@ type BlockTimer struct {
ps []BlockTimer ps []BlockTimer
once bool
deltaCfg deltaCfg
} }
@ -72,6 +74,20 @@ func NewBlockTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer {
} }
} }
// NewOneTickTimer creates a new BlockTimer that ticks only once.
//
// Do not use delta handlers with pulse in this timer.
func NewOneTickTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer {
return &BlockTimer{
mtx: new(sync.Mutex),
dur: dur,
mul: 1,
div: 1,
h: h,
once: true,
}
}
// OnDelta registers handler which is executed on (mul / div * BlockMeter()) block // OnDelta registers handler which is executed on (mul / div * BlockMeter()) block
// after basic interval reset. // after basic interval reset.
// //
@ -90,6 +106,7 @@ func (t *BlockTimer) OnDelta(mul, div uint32, h BlockTickHandler, opts ...DeltaO
mul: mul, mul: mul,
div: div, div: div,
h: h, h: h,
once: t.once,
deltaCfg: c, deltaCfg: c,
}) })
@ -157,10 +174,12 @@ func (t *BlockTimer) tick() {
// 2. call t.tickH(h) // 2. call t.tickH(h)
t.h() t.h()
if !t.once {
t.cur = 0 t.cur = 0
t.rolledBack = true t.rolledBack = true
t.reset() t.reset()
} }
}
for i := range t.ps { for i := range t.ps {
t.ps[i].tick() t.ps[i].tick()

View file

@ -108,3 +108,54 @@ func TestDeltaReset(t *testing.T) {
require.Equal(t, 2, detlaCallCounter) require.Equal(t, 2, detlaCallCounter)
} }
func TestNewOneTickTimer(t *testing.T) {
blockDur := uint32(1)
baseCallCounter := 0
bt := timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
require.NoError(t, bt.Reset())
tickN(bt, 10)
require.Equal(t, 1, baseCallCounter) // happens once no matter what
t.Run("zero duration", func(t *testing.T) {
blockDur = uint32(0)
baseCallCounter = 0
bt = timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
require.NoError(t, bt.Reset())
tickN(bt, 10)
require.Equal(t, 1, baseCallCounter)
})
t.Run("delta without pulse", func(t *testing.T) {
blockDur = uint32(10)
baseCallCounter = 0
bt = timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
detlaCallCounter := 0
bt.OnDelta(1, 10, func() {
detlaCallCounter++
})
require.NoError(t, bt.Reset())
tickN(bt, 10)
require.Equal(t, 1, baseCallCounter)
require.Equal(t, 1, detlaCallCounter)
tickN(bt, 10) // 10 more ticks must not affect counters
require.Equal(t, 1, baseCallCounter)
require.Equal(t, 1, detlaCallCounter)
})
}