github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/http/longpoll/priority_queue.go (about) 1 package longpoll 2 3 import ( 4 "container/heap" 5 "fmt" 6 ) 7 8 // This priority queue manages eventBuffers that expire after a certain 9 // period of inactivity (no new events). 10 type expiringBuffer struct { 11 // references an eventBuffer 12 eventBuffer_ptr *eventBuffer 13 // The subscription category for the given event buffer 14 // This is needed so we can clean up our category-to-Item map 15 // by doing a simple key lookup and removing the eventBuffer ref 16 category string 17 // The priority of the item in the queue. 18 // For our purposes, this is milliseconds since epoch 19 priority int64 20 // index is needed by update and is maintained by heap.Interface 21 // The index of this item in the heap. 22 index int 23 } 24 25 // A Priority Queue (min heap) implemented with go's heap container. 26 // Adapted from go's example at: https://golang.org/pkg/container/heap/ 27 // 28 // This priorityQueue is used to keep track of eventBuffer objects in order of 29 // oldest last-event-timestamp so that we can more efficiently purge buffers 30 // that have expired events. 31 // 32 // The priority here will be a timestamp in milliseconds since epoch (int64) 33 // with lower values (older timestamps) being at the top of the heap/queue and 34 // higher values (more recent timestamps) being further down. 35 // So this is a Min Heap. 36 // 37 // A priorityQueue implements heap.Interface and holds Items. 38 type priorityQueue []*expiringBuffer 39 40 func (pq priorityQueue) Len() int { return len(pq) } 41 42 func (pq priorityQueue) Less(i, j int) bool { 43 // We want Pop to give us the lowest priority, so less uses < here: 44 return pq[i].priority < pq[j].priority 45 } 46 47 func (pq priorityQueue) Swap(i, j int) { 48 pq[i], pq[j] = pq[j], pq[i] 49 pq[i].index = i 50 pq[j].index = j 51 } 52 53 func (pq *priorityQueue) Push(x interface{}) { 54 n := len(*pq) 55 item := x.(*expiringBuffer) 56 item.index = n 57 *pq = append(*pq, item) 58 } 59 60 func (pq *priorityQueue) Pop() interface{} { 61 old := *pq 62 n := len(old) 63 item := old[n-1] 64 item.index = -1 // for safety 65 *pq = old[0 : n-1] 66 return item 67 } 68 69 // update modifies the priority of an item and updates the heap accordingly 70 func (pq *priorityQueue) updatePriority(item *expiringBuffer, priority int64) { 71 item.priority = priority 72 // NOTE: fix is a slightly more efficient version of calling Remove() and 73 // then Push() 74 heap.Fix(pq, item.index) 75 } 76 77 // get the priority of the heap's top item. 78 func (pq *priorityQueue) peakTopPriority() (int64, error) { 79 if len(*pq) > 0 { 80 return (*pq)[0].priority, nil 81 } else { 82 return -1, fmt.Errorf("PriorityQueue is empty. No top priority.") 83 } 84 }