github.com/gogf/gf@v1.16.9/os/gtimer/gtimer_queue.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gtimer 8 9 import ( 10 "container/heap" 11 "github.com/gogf/gf/container/gtype" 12 "math" 13 "sync" 14 ) 15 16 // priorityQueue is an abstract data type similar to a regular queue or stack data structure in which 17 // each element additionally has a "priority" associated with it. In a priority queue, an element with 18 // high priority is served before an element with low priority. 19 // priorityQueue is based on heap structure. 20 type priorityQueue struct { 21 mu sync.Mutex 22 heap *priorityQueueHeap // the underlying queue items manager using heap. 23 nextPriority *gtype.Int64 // nextPriority stores the next priority value of the heap, which is used to check if necessary to call the Pop of heap by Timer. 24 } 25 26 // priorityQueueHeap is a heap manager, of which the underlying `array` is a array implementing a heap structure. 27 type priorityQueueHeap struct { 28 array []priorityQueueItem 29 } 30 31 // priorityQueueItem stores the queue item which has a `priority` attribute to sort itself in heap. 32 type priorityQueueItem struct { 33 value interface{} 34 priority int64 35 } 36 37 // newPriorityQueue creates and returns a priority queue. 38 func newPriorityQueue() *priorityQueue { 39 queue := &priorityQueue{ 40 heap: &priorityQueueHeap{array: make([]priorityQueueItem, 0)}, 41 nextPriority: gtype.NewInt64(math.MaxInt64), 42 } 43 heap.Init(queue.heap) 44 return queue 45 } 46 47 // NextPriority retrieves and returns the minimum and the most priority value of the queue. 48 func (q *priorityQueue) NextPriority() int64 { 49 return q.nextPriority.Val() 50 } 51 52 // Push pushes a value to the queue. 53 // The `priority` specifies the priority of the value. 54 // The lesser the `priority` value the higher priority of the `value`. 55 func (q *priorityQueue) Push(value interface{}, priority int64) { 56 q.mu.Lock() 57 defer q.mu.Unlock() 58 heap.Push(q.heap, priorityQueueItem{ 59 value: value, 60 priority: priority, 61 }) 62 // Update the minimum priority using atomic operation. 63 nextPriority := q.nextPriority.Val() 64 if priority >= nextPriority { 65 return 66 } 67 q.nextPriority.Set(priority) 68 } 69 70 // Pop retrieves, removes and returns the most high priority value from the queue. 71 func (q *priorityQueue) Pop() interface{} { 72 q.mu.Lock() 73 defer q.mu.Unlock() 74 if v := heap.Pop(q.heap); v != nil { 75 var nextPriority int64 = math.MaxInt64 76 if len(q.heap.array) > 0 { 77 nextPriority = q.heap.array[0].priority 78 } 79 q.nextPriority.Set(nextPriority) 80 return v.(priorityQueueItem).value 81 } 82 return nil 83 }