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  }