forked from cerc-io/plugeth
common/prque: generic priority queue (#26290)
* common, core, eth, les, trie: make prque generic * les/vflux/server: fixed issues in priorityPool * common, core, eth, les, trie: make priority also generic in prque * les/flowcontrol: add test case for priority accumulator overflow * les/flowcontrol: avoid priority value overflow * common/prque: use int priority in some tests No need to convert to int64 when we can just change the type used by the queue. * common/prque: remove comment about int64 range --------- Co-authored-by: Zsolt Felfoldi <zsfelfoldi@gmail.com> Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
co-authored by
Zsolt Felfoldi
Felix Lange
parent
6a148dd5c3
commit
bf1798e04e
+19
-25
@@ -19,65 +19,59 @@ package prque
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
// Priority queue data structure.
|
||||
type Prque struct {
|
||||
cont *sstack
|
||||
type Prque[P constraints.Ordered, V any] struct {
|
||||
cont *sstack[P, V]
|
||||
}
|
||||
|
||||
// New creates a new priority queue.
|
||||
func New(setIndex SetIndexCallback) *Prque {
|
||||
return &Prque{newSstack(setIndex, false)}
|
||||
}
|
||||
|
||||
// NewWrapAround creates a new priority queue with wrap-around priority handling.
|
||||
func NewWrapAround(setIndex SetIndexCallback) *Prque {
|
||||
return &Prque{newSstack(setIndex, true)}
|
||||
func New[P constraints.Ordered, V any](setIndex SetIndexCallback[V]) *Prque[P, V] {
|
||||
return &Prque[P, V]{newSstack[P, V](setIndex)}
|
||||
}
|
||||
|
||||
// Pushes a value with a given priority into the queue, expanding if necessary.
|
||||
func (p *Prque) Push(data interface{}, priority int64) {
|
||||
heap.Push(p.cont, &item{data, priority})
|
||||
func (p *Prque[P, V]) Push(data V, priority P) {
|
||||
heap.Push(p.cont, &item[P, V]{data, priority})
|
||||
}
|
||||
|
||||
// Peek returns the value with the greatest priority but does not pop it off.
|
||||
func (p *Prque) Peek() (interface{}, int64) {
|
||||
func (p *Prque[P, V]) Peek() (V, P) {
|
||||
item := p.cont.blocks[0][0]
|
||||
return item.value, item.priority
|
||||
}
|
||||
|
||||
// Pops the value with the greatest priority off the stack and returns it.
|
||||
// Currently no shrinking is done.
|
||||
func (p *Prque) Pop() (interface{}, int64) {
|
||||
item := heap.Pop(p.cont).(*item)
|
||||
func (p *Prque[P, V]) Pop() (V, P) {
|
||||
item := heap.Pop(p.cont).(*item[P, V])
|
||||
return item.value, item.priority
|
||||
}
|
||||
|
||||
// Pops only the item from the queue, dropping the associated priority value.
|
||||
func (p *Prque) PopItem() interface{} {
|
||||
return heap.Pop(p.cont).(*item).value
|
||||
func (p *Prque[P, V]) PopItem() V {
|
||||
return heap.Pop(p.cont).(*item[P, V]).value
|
||||
}
|
||||
|
||||
// Remove removes the element with the given index.
|
||||
func (p *Prque) Remove(i int) interface{} {
|
||||
if i < 0 {
|
||||
return nil
|
||||
}
|
||||
return heap.Remove(p.cont, i)
|
||||
func (p *Prque[P, V]) Remove(i int) V {
|
||||
return heap.Remove(p.cont, i).(*item[P, V]).value
|
||||
}
|
||||
|
||||
// Checks whether the priority queue is empty.
|
||||
func (p *Prque) Empty() bool {
|
||||
func (p *Prque[P, V]) Empty() bool {
|
||||
return p.cont.Len() == 0
|
||||
}
|
||||
|
||||
// Returns the number of element in the priority queue.
|
||||
func (p *Prque) Size() int {
|
||||
func (p *Prque[P, V]) Size() int {
|
||||
return p.cont.Len()
|
||||
}
|
||||
|
||||
// Clears the contents of the priority queue.
|
||||
func (p *Prque) Reset() {
|
||||
*p = *New(p.cont.setIndex)
|
||||
func (p *Prque[P, V]) Reset() {
|
||||
*p = *New[P, V](p.cont.setIndex)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user