gitlab.com/beacon-software/gadget@v0.0.0-20181217202115-54565ea1ed5e/collection/specialized/hashpriorityqueue.go (about) 1 package specialized 2 3 import ( 4 "gitlab.com/beacon-software/gadget/collection" 5 ) 6 7 // HashPriority exposes both a priority function and Hash function. 8 type HashPriority interface { 9 Priority 10 GetHash() interface{} 11 } 12 13 // HashPriorityQueue prevents duplicate prioritized entries in a queue. 14 type HashPriorityQueue interface { 15 // Size of this queue 16 Size() int 17 // Push the passed element onto this queue if it does not already exist in 18 // the queue. 19 Push(element HashPriority) 20 // Pop the highest priority element off the queue 21 Pop() (HashPriority, bool) 22 // Peek at the highest priority element without modifying the queue 23 Peek() (HashPriority, bool) 24 } 25 26 // NewHashPriorityQueue for queueing unique elements by priority. 27 func NewHashPriorityQueue() HashPriorityQueue { 28 return &hashPriorityQueue{ 29 set: collection.NewSet(), 30 pqueue: NewPriorityQueue(), 31 } 32 } 33 34 type hashPriorityWrapper struct { 35 priority int 36 element HashPriority 37 } 38 39 func (hpw *hashPriorityWrapper) GetPriority() int { 40 return hpw.priority 41 } 42 43 func (hpw *hashPriorityWrapper) GetHash() interface{} { 44 return hpw.element.GetHash() 45 } 46 47 func newHashPriorityWrapper(element HashPriority) *hashPriorityWrapper { 48 return &hashPriorityWrapper{ 49 priority: element.GetPriority(), 50 element: element, 51 } 52 } 53 54 type hashPriorityQueue struct { 55 set collection.Set 56 pqueue PriorityQueue 57 } 58 59 func (hpq *hashPriorityQueue) Size() int { 60 return hpq.pqueue.Size() 61 } 62 63 func (hpq *hashPriorityQueue) Push(element HashPriority) { 64 hash := element.GetHash() 65 wrappedElement := newHashPriorityWrapper(element) 66 if hpq.set.Contains(hash) { 67 for elm := hpq.pqueue.(*priorityQueue).list.Head(); elm != nil; elm = elm.Next() { 68 d := hpq.convert(elm.Data()) 69 if d.GetHash() == hash { 70 hpq.pqueue.(*priorityQueue).list.Remove(elm) 71 wrappedElement.priority = d.GetPriority() 72 } 73 } 74 } 75 hpq.pqueue.Push(wrappedElement) 76 hpq.set.Add(hash) 77 } 78 79 func (hpq *hashPriorityQueue) convert(data interface{}) HashPriority { 80 p, _ := data.(HashPriority) 81 return p 82 } 83 84 func (hpq *hashPriorityQueue) nextElement(next func() (Priority, bool), remove bool) (HashPriority, bool) { 85 p, ok := next() 86 var hp *hashPriorityWrapper 87 if !ok { 88 return nil, false 89 } 90 91 hp, _ = p.(*hashPriorityWrapper) 92 if remove { 93 hpq.set.Remove(hp.GetHash()) 94 } 95 return hp.element, true 96 } 97 98 func (hpq *hashPriorityQueue) Pop() (HashPriority, bool) { 99 return hpq.nextElement(hpq.pqueue.Pop, true) 100 } 101 102 func (hpq *hashPriorityQueue) Peek() (HashPriority, bool) { 103 return hpq.nextElement(hpq.pqueue.Peek, false) 104 }