frostfs-node/pkg/morph/timer/block.go
Evgenii Stratonikov 3042490340 [#1507] timer: Remove unused OnDelta() method
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-20 08:36:25 +00:00

120 lines
2 KiB
Go

package timer
import (
"sync"
)
// BlockMeter calculates block time interval dynamically.
type BlockMeter func() (uint32, error)
// BlockTickHandler is a callback of a certain block advance.
type BlockTickHandler func()
// BlockTimer represents block timer.
//
// It can tick the blocks and perform certain actions
// on block time intervals.
type BlockTimer struct {
mtx sync.Mutex
dur BlockMeter
baseDur uint32
cur, tgt uint32
last uint32
h BlockTickHandler
once bool
}
// StaticBlockMeter returns BlockMeters that always returns (d, nil).
func StaticBlockMeter(d uint32) BlockMeter {
return func() (uint32, error) {
return d, nil
}
}
// NewBlockTimer creates a new BlockTimer.
//
// Reset should be called before timer ticking.
func NewBlockTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer {
return &BlockTimer{
dur: dur,
h: h,
}
}
// NewOneTickTimer creates a new BlockTimer that ticks only once.
func NewOneTickTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer {
return &BlockTimer{
dur: dur,
h: h,
once: true,
}
}
// Reset resets previous ticks of the BlockTimer.
//
// Returns BlockMeter's error upon occurrence.
func (t *BlockTimer) Reset() error {
d, err := t.dur()
if err != nil {
return err
}
t.mtx.Lock()
t.resetWithBaseInterval(d)
t.mtx.Unlock()
return nil
}
func (t *BlockTimer) resetWithBaseInterval(d uint32) {
t.baseDur = d
t.reset()
}
func (t *BlockTimer) reset() {
delta := t.baseDur
if delta == 0 {
delta = 1
}
t.tgt = delta
t.cur = 0
}
// Tick ticks one block in the BlockTimer.
//
// Executes all callbacks which are awaiting execution at the new block.
func (t *BlockTimer) Tick(h uint32) {
t.mtx.Lock()
t.tick(h)
t.mtx.Unlock()
}
func (t *BlockTimer) tick(h uint32) {
if h != 0 && t.last == h {
return
}
t.last = h
t.cur++
if t.cur == t.tgt {
// it would be advisable to optimize such execution, for example:
// 1. push handler to worker pool t.wp.Submit(h);
// 2. call t.tickH(h)
t.h()
if !t.once {
t.cur = 0
t.reset()
}
}
}