|
0 |
/*
|
|
1 |
Package queue provides a fast, ring-buffer queue based on the version suggested by Dariusz Górecki.
|
|
2 |
Using this instead of other, simpler, queue implementations (slice+append or linked list) provides
|
|
3 |
substantial memory and time benefits, and fewer GC pauses.
|
|
4 |
|
|
5 |
The queue implemented here is as fast as it is for two additional reasons: it is *not* thread-safe, and it
|
|
6 |
intentionally does not follow go best-practices regarding errors - if you make a mistake with this
|
|
7 |
queue (such as trying to remove an element from an empty queue) then who knows what will happen.
|
|
8 |
*/
|
|
9 |
package queue
|
|
10 |
|
|
11 |
const minQueueLen = 16
|
|
12 |
|
|
13 |
type Queue struct {
|
|
14 |
buf []interface{}
|
|
15 |
head, tail, count int
|
|
16 |
}
|
|
17 |
|
|
18 |
// New constructs and returns a new Queue
|
|
19 |
func New() *Queue {
|
|
20 |
return &Queue{buf: make([]interface{}, minQueueLen)}
|
|
21 |
}
|
|
22 |
|
|
23 |
// Length returns the number of elements currently stored in the queue
|
|
24 |
func (q *Queue) Length() int {
|
|
25 |
return q.count
|
|
26 |
}
|
|
27 |
|
|
28 |
func (q *Queue) resize() {
|
|
29 |
newBuf := make([]interface{}, q.count*2)
|
|
30 |
|
|
31 |
if q.tail > q.head {
|
|
32 |
copy(newBuf, q.buf[q.head:q.tail])
|
|
33 |
} else {
|
|
34 |
copy(newBuf, q.buf[q.head:len(q.buf)])
|
|
35 |
copy(newBuf[len(q.buf)-q.head:], q.buf[:q.tail])
|
|
36 |
}
|
|
37 |
|
|
38 |
q.head = 0
|
|
39 |
q.tail = q.count
|
|
40 |
q.buf = newBuf
|
|
41 |
}
|
|
42 |
|
|
43 |
// Add puts an element on the end of the queue
|
|
44 |
func (q *Queue) Add(elem interface{}) {
|
|
45 |
if q.count == len(q.buf) {
|
|
46 |
q.resize()
|
|
47 |
}
|
|
48 |
|
|
49 |
q.buf[q.tail] = elem
|
|
50 |
q.tail = (q.tail + 1) % len(q.buf)
|
|
51 |
q.count++
|
|
52 |
}
|
|
53 |
|
|
54 |
// Peek returns the element at the head of the queue. If the queue is empty (Length == 0),
|
|
55 |
// Peek does not panic, it simply returns garbage.
|
|
56 |
func (q *Queue) Peek() interface{} {
|
|
57 |
return q.buf[q.head]
|
|
58 |
}
|
|
59 |
|
|
60 |
// Remove removes the element from the front of the queue. If you actually want the element,
|
|
61 |
// call Peek first. If the queue is empty (Length == 0), Remove will put the queue in a bad
|
|
62 |
// state and all further operations will be undefined.
|
|
63 |
func (q *Queue) Remove() {
|
|
64 |
q.buf[q.head] = nil
|
|
65 |
q.head = (q.head + 1) % len(q.buf)
|
|
66 |
q.count--
|
|
67 |
if len(q.buf) > minQueueLen && q.count*4 <= len(q.buf) {
|
|
68 |
q.resize()
|
|
69 |
}
|
|
70 |
}
|