[#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
once bool
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
// after basic interval reset.
//
@ -87,9 +103,10 @@ func (t *BlockTimer) OnDelta(mul, div uint32, h BlockTickHandler, opts ...DeltaO
}
t.ps = append(t.ps, BlockTimer{
mul: mul,
div: div,
h: h,
mul: mul,
div: div,
h: h,
once: t.once,
deltaCfg: c,
})
@ -157,9 +174,11 @@ func (t *BlockTimer) tick() {
// 2. call t.tickH(h)
t.h()
t.cur = 0
t.rolledBack = true
t.reset()
if !t.once {
t.cur = 0
t.rolledBack = true
t.reset()
}
}
for i := range t.ps {

View file

@ -108,3 +108,54 @@ func TestDeltaReset(t *testing.T) {
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)
})
}