55package queue
66
77import (
8- "container/heap"
98 "sync"
109)
1110
11+ type QueuePriority int
12+
1213// The priority levels for the priority Queue.
1314const (
14- PriorityLow int = iota
15- PriorityNormal
16- PriorityHigh
17- PriorityCritical
15+ PriorityLow QueuePriority = 0
16+ PriorityNormal QueuePriority = 1
17+ PriorityHigh QueuePriority = 2
18+ PriorityCritical QueuePriority = 3
1819)
1920
20- // Queue implements a FIFO data structure that can support priorities.
21+ // Queue implements a FIFO data structure that can support a few priorities.
2122type Queue interface {
2223 // Append adds the data to the Queue at priority level PriorityNormal.
2324 Append (data interface {})
2425
2526 // AppendPriority adds the data to the Queue with respect to priority.
26- AppendPriority (data interface {}, priority int )
27+ AppendPriority (data interface {}, priority QueuePriority )
2728
2829 // Signal returns the Queue signal channel.
2930 Signal () <- chan struct {}
@@ -41,59 +42,18 @@ type Queue interface {
4142 Len () int
4243}
4344
44- type queueElement struct {
45- Data interface {}
46- priority int
47- index int
48- }
49-
50- type priorityQueue []* queueElement
51-
52- // Len returns the number of elements remaining in the queue.
53- func (pq priorityQueue ) Len () int { return len (pq ) }
54-
55- // Less returns true when i has a higher priority than j.
56- func (pq priorityQueue ) Less (i , j int ) bool {
57- return pq [i ].priority > pq [j ].priority
58- }
59-
60- // Swap exchanges the ith and jth element of the priority queue.
61- func (pq priorityQueue ) Swap (i , j int ) {
62- pq [i ], pq [j ] = pq [j ], pq [i ]
63- pq [i ].index = i
64- pq [j ].index = j
65- }
66-
67- // Push adds a new element to the priority queue.
68- func (pq * priorityQueue ) Push (x interface {}) {
69- n := len (* pq )
70- element := x .(* queueElement )
71- element .index = n
72- * pq = append (* pq , element )
73- }
74-
75- // Pop removes the next element from the queue in priority order.
76- func (pq * priorityQueue ) Pop () interface {} {
77- old := * pq
78- n := len (old )
79- element := old [n - 1 ]
80- old [n - 1 ] = nil // avoid memory leak
81- element .index = - 1 // for safety
82- * pq = old [:n - 1 ]
83- return element
84- }
85-
8645type queue struct {
8746 sync.Mutex
8847 signal chan struct {}
89- pq priorityQueue
48+ low []interface {}
49+ norm []interface {}
50+ high []interface {}
51+ crit []interface {}
9052}
9153
9254// NewQueue returns an initialized Queue.
9355func NewQueue () Queue {
94- q := & queue {signal : make (chan struct {}, 1 )}
95- heap .Init (& q .pq )
96- return q
56+ return & queue {signal : make (chan struct {}, 1 )}
9757}
9858
9959// Append implements the Queue interface.
@@ -102,18 +62,24 @@ func (q *queue) Append(data interface{}) {
10262}
10363
10464// AppendPriority implements the Queue interface.
105- func (q * queue ) AppendPriority (data interface {}, priority int ) {
65+ func (q * queue ) AppendPriority (data interface {}, priority QueuePriority ) {
10666 q .append (data , priority )
10767}
10868
109- func (q * queue ) append (data interface {}, priority int ) {
69+ func (q * queue ) append (data interface {}, priority QueuePriority ) {
11070 q .Lock ()
11171 defer q .Unlock ()
11272
113- heap .Push (& q .pq , & queueElement {
114- Data : data ,
115- priority : priority ,
116- })
73+ switch priority {
74+ case PriorityLow :
75+ q .low = append (q .low , data )
76+ case PriorityNormal :
77+ q .norm = append (q .norm , data )
78+ case PriorityHigh :
79+ q .high = append (q .high , data )
80+ case PriorityCritical :
81+ q .crit = append (q .crit , data )
82+ }
11783
11884 select {
11985 case q .signal <- struct {}{}:
@@ -128,16 +94,14 @@ func (q *queue) Signal() <-chan struct{} {
12894}
12995
13096func (q * queue ) prepSignal () {
131- q .Lock ()
132- defer q .Unlock ()
133-
13497 var send bool
98+
13599 select {
136100 case _ , send = <- q .signal :
137101 default :
138102 }
139103
140- if ! send && q .pq . Len () > 0 {
104+ if ! send && q .Len () > 0 {
141105 send = true
142106 }
143107 if send {
@@ -164,13 +128,25 @@ func (q *queue) Next() (interface{}, bool) {
164128 q .Lock ()
165129 defer q .Unlock ()
166130
167- if q .pq .Len () == 0 {
131+ var data interface {}
132+ if len (q .crit ) > 0 {
133+ data = q .crit [0 ]
134+ q .crit = q .crit [1 :]
135+ } else if len (q .high ) > 0 {
136+ data = q .high [0 ]
137+ q .high = q .high [1 :]
138+ } else if len (q .norm ) > 0 {
139+ data = q .norm [0 ]
140+ q .norm = q .norm [1 :]
141+ } else if len (q .low ) > 0 {
142+ data = q .low [0 ]
143+ q .low = q .low [1 :]
144+ } else {
168145 q .drain ()
169146 return nil , false
170147 }
171148
172- element := heap .Pop (& q .pq ).(* queueElement )
173- return element .Data , true
149+ return data , true
174150}
175151
176152// Process implements the Queue interface.
@@ -193,5 +169,10 @@ func (q *queue) Len() int {
193169 q .Lock ()
194170 defer q .Unlock ()
195171
196- return q .pq .Len ()
172+ qlen := len (q .low )
173+ qlen += len (q .norm )
174+ qlen += len (q .high )
175+ qlen += len (q .crit )
176+
177+ return qlen
197178}
0 commit comments