Skip to content

Commit 47b9860

Browse files
committed
updated the implementation
1 parent e35a601 commit 47b9860

2 files changed

Lines changed: 50 additions & 69 deletions

File tree

queue.go

Lines changed: 48 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,26 @@
55
package queue
66

77
import (
8-
"container/heap"
98
"sync"
109
)
1110

11+
type QueuePriority int
12+
1213
// The priority levels for the priority Queue.
1314
const (
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.
2122
type 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-
8645
type 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.
9355
func 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

13096
func (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
}

queue_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ loop:
9292
func TestNext(t *testing.T) {
9393
q := NewQueue()
9494
values := []string{"test1", "test2", "test3", "test4"}
95-
priorities := []int{30, 5, 90, 75}
95+
priorities := []QueuePriority{PriorityNormal, PriorityLow, PriorityCritical, PriorityHigh}
9696
expected := []string{"test3", "test4", "test1", "test2"}
9797

9898
for i, v := range values {
@@ -183,7 +183,7 @@ func BenchmarkAppendPriority(b *testing.B) {
183183

184184
values := []struct {
185185
token string
186-
priority int
186+
priority QueuePriority
187187
}{
188188
{"valueLow", PriorityLow},
189189
{"valueNormal", PriorityNormal},

0 commit comments

Comments
 (0)