common/prque: refactor LazyQueue (#21236)

This commit is contained in:
Daniel Liu 2024-12-16 18:52:16 +08:00
parent d3a943d0b3
commit cf0c5c8cd2

View file

@ -29,6 +29,7 @@ import (
// - priority evaluates the actual priority of an item
// - maxPriority gives an upper estimate for the priority in any moment between
// now and the given absolute time
//
// If the upper estimate is exceeded then Update should be called for that item.
// A global Refresh function should also be called periodically.
type LazyQueue struct {
@ -44,6 +45,7 @@ type LazyQueue struct {
setIndex SetIndexCallback
priority PriorityCallback
maxPriority MaxPriorityCallback
lastRefresh1, lastRefresh2 mclock.AbsTime
}
type (
@ -59,9 +61,12 @@ func NewLazyQueue(setIndex SetIndexCallback, priority PriorityCallback, maxPrior
priority: priority,
maxPriority: maxPriority,
clock: clock,
period: refreshPeriod}
period: refreshPeriod,
lastRefresh1: clock.Now(),
lastRefresh2: clock.Now(),
}
q.Reset()
q.Refresh()
q.refresh(clock.Now())
return q
}
@ -71,9 +76,19 @@ func (q *LazyQueue) Reset() {
q.queue[1] = newSstack(q.setIndex1)
}
// Refresh should be called at least with the frequency specified by the refreshPeriod parameter
// Refresh performs queue re-evaluation if necessary
func (q *LazyQueue) Refresh() {
q.maxUntil = q.clock.Now() + mclock.AbsTime(q.period)
now := q.clock.Now()
for time.Duration(now-q.lastRefresh2) >= q.period*2 {
q.refresh(now)
q.lastRefresh2 = q.lastRefresh1
q.lastRefresh1 = now
}
}
// refresh re-evaluates items in the older queue and swaps the two queues
func (q *LazyQueue) refresh(now mclock.AbsTime) {
q.maxUntil = now + mclock.AbsTime(q.period)
for q.queue[0].Len() != 0 {
q.Push(heap.Pop(q.queue[0]).(*item).value)
}
@ -139,6 +154,7 @@ func (q *LazyQueue) MultiPop(callback func(data interface{}, priority int64) boo
}
return
}
nextIndex = q.peekIndex() // re-check because callback is allowed to push items back
}
}
}