1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- // 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"
- "github.com/gogf/gf/container/gtype"
- "math"
- "sync"
- )
- // 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
- }
|