github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf. 6 7 package gtimer 8 9 import ( 10 "container/heap" 11 "math" 12 "sync" 13 14 "github.com/wangyougui/gf/v2/container/gtype" 15 ) 16 17 // priorityQueue is an abstract data type similar to a regular queue or stack data structure in which 18 // each element additionally has a "priority" associated with it. In a priority queue, an element with 19 // high priority is served before an element with low priority. 20 // priorityQueue is based on heap structure. 21 type priorityQueue struct { 22 mu sync.Mutex 23 heap *priorityQueueHeap // the underlying queue items manager using heap. 24 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. 25 } 26 27 // priorityQueueHeap is a heap manager, of which the underlying `array` is an array implementing a heap structure. 28 type priorityQueueHeap struct { 29 array []priorityQueueItem 30 } 31 32 // priorityQueueItem stores the queue item which has a `priority` attribute to sort itself in heap. 33 type priorityQueueItem struct { 34 value interface{} 35 priority int64 36 } 37 38 // newPriorityQueue creates and returns a priority queue. 39 func newPriorityQueue() *priorityQueue { 40 queue := &priorityQueue{ 41 heap: &priorityQueueHeap{array: make([]priorityQueueItem, 0)}, 42 nextPriority: gtype.NewInt64(math.MaxInt64), 43 } 44 heap.Init(queue.heap) 45 return queue 46 } 47 48 // NextPriority retrieves and returns the minimum and the most priority value of the queue. 49 func (q *priorityQueue) NextPriority() int64 { 50 return q.nextPriority.Val() 51 } 52 53 // Push pushes a value to the queue. 54 // The `priority` specifies the priority of the value. 55 // The lesser the `priority` value the higher priority of the `value`. 56 func (q *priorityQueue) Push(value interface{}, priority int64) { 57 q.mu.Lock() 58 defer q.mu.Unlock() 59 heap.Push(q.heap, priorityQueueItem{ 60 value: value, 61 priority: priority, 62 }) 63 // Update the minimum priority using atomic operation. 64 nextPriority := q.nextPriority.Val() 65 if priority >= nextPriority { 66 return 67 } 68 q.nextPriority.Set(priority) 69 } 70 71 // Pop retrieves, removes and returns the most high priority value from the queue. 72 func (q *priorityQueue) Pop() interface{} { 73 q.mu.Lock() 74 defer q.mu.Unlock() 75 if v := heap.Pop(q.heap); v != nil { 76 var nextPriority int64 = math.MaxInt64 77 if len(q.heap.array) > 0 { 78 nextPriority = q.heap.array[0].priority 79 } 80 q.nextPriority.Set(nextPriority) 81 return v.(priorityQueueItem).value 82 } 83 return nil 84 }