mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 12:17:53 +08:00
85 lines
2.6 KiB
Go
85 lines
2.6 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gtimer
|
|
|
|
import (
|
|
"container/heap"
|
|
"math"
|
|
"sync"
|
|
|
|
"github.com/gogf/gf/v2/container/gtype"
|
|
)
|
|
|
|
// priorityQueue is an abstract data type similar to a regular queue or stack data structure in which
|
|
// each element additionally has a "priority" associated with it. In a priority queue, an element with
|
|
// high priority is served before an element with low priority.
|
|
// priorityQueue is based on heap structure.
|
|
type priorityQueue struct {
|
|
mu sync.Mutex
|
|
heap *priorityQueueHeap // the underlying queue items manager using heap.
|
|
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.
|
|
}
|
|
|
|
// priorityQueueHeap is a heap manager, of which the underlying `array` is a array implementing a heap structure.
|
|
type priorityQueueHeap struct {
|
|
array []priorityQueueItem
|
|
}
|
|
|
|
// priorityQueueItem stores the queue item which has a `priority` attribute to sort itself in heap.
|
|
type priorityQueueItem struct {
|
|
value interface{}
|
|
priority int64
|
|
}
|
|
|
|
// newPriorityQueue creates and returns a priority queue.
|
|
func newPriorityQueue() *priorityQueue {
|
|
queue := &priorityQueue{
|
|
heap: &priorityQueueHeap{array: make([]priorityQueueItem, 0)},
|
|
nextPriority: gtype.NewInt64(math.MaxInt64),
|
|
}
|
|
heap.Init(queue.heap)
|
|
return queue
|
|
}
|
|
|
|
// NextPriority retrieves and returns the minimum and the most priority value of the queue.
|
|
func (q *priorityQueue) NextPriority() int64 {
|
|
return q.nextPriority.Val()
|
|
}
|
|
|
|
// Push pushes a value to the queue.
|
|
// The `priority` specifies the priority of the value.
|
|
// The lesser the `priority` value the higher priority of the `value`.
|
|
func (q *priorityQueue) Push(value interface{}, priority int64) {
|
|
q.mu.Lock()
|
|
defer q.mu.Unlock()
|
|
heap.Push(q.heap, priorityQueueItem{
|
|
value: value,
|
|
priority: priority,
|
|
})
|
|
// Update the minimum priority using atomic operation.
|
|
nextPriority := q.nextPriority.Val()
|
|
if priority >= nextPriority {
|
|
return
|
|
}
|
|
q.nextPriority.Set(priority)
|
|
}
|
|
|
|
// Pop retrieves, removes and returns the most high priority value from the queue.
|
|
func (q *priorityQueue) Pop() interface{} {
|
|
q.mu.Lock()
|
|
defer q.mu.Unlock()
|
|
if v := heap.Pop(q.heap); v != nil {
|
|
var nextPriority int64 = math.MaxInt64
|
|
if len(q.heap.array) > 0 {
|
|
nextPriority = q.heap.array[0].priority
|
|
}
|
|
q.nextPriority.Set(nextPriority)
|
|
return v.(priorityQueueItem).value
|
|
}
|
|
return nil
|
|
}
|