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  }