diff --git a/os/gtimer/gtimer_queue.go b/os/gtimer/gtimer_queue.go index b805d7d22..9fb6af73d 100644 --- a/os/gtimer/gtimer_queue.go +++ b/os/gtimer/gtimer_queue.go @@ -63,7 +63,11 @@ func (q *priorityQueue) LatestPriority() int64 { // 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, + }) + q.mu.Unlock() // Update the minimum priority using atomic operation. for { latestPriority := q.latestPriority.Val() @@ -74,18 +78,27 @@ func (q *priorityQueue) Push(value interface{}, priority int64) { break } } - heap.Push(q.heap, priorityQueueItem{ - value: value, - priority: 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 item := heap.Pop(q.heap); item != nil { - return item.(priorityQueueItem).value + if v := heap.Pop(q.heap); v != nil { + item := v.(priorityQueueItem) + q.mu.Unlock() + // Update the minimum priority using atomic operation. + for { + latestPriority := q.latestPriority.Val() + if item.priority >= latestPriority { + break + } + if q.latestPriority.Cas(latestPriority, item.priority) { + break + } + } + return item.value + } else { + q.mu.Unlock() } return nil } diff --git a/os/gtimer/gtimer_z_bench_test.go b/os/gtimer/gtimer_z_bench_test.go index 66ab4e0d6..139bf1c4a 100644 --- a/os/gtimer/gtimer_z_bench_test.go +++ b/os/gtimer/gtimer_z_bench_test.go @@ -4,17 +4,15 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package gtimer_test +package gtimer import ( "testing" "time" - - "github.com/gogf/gf/os/gtimer" ) var ( - timer = gtimer.New() + timer = New() ) func Benchmark_Add(b *testing.B) { @@ -25,6 +23,12 @@ func Benchmark_Add(b *testing.B) { } } +func Benchmark_PriorityQueue_Pop(b *testing.B) { + for i := 0; i < b.N; i++ { + timer.queue.Pop() + } +} + func Benchmark_StartStop(b *testing.B) { for i := 0; i < b.N; i++ { timer.Start()