queue.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. Package queue provides a fast, ring-buffer queue based on the version suggested by Dariusz Górecki.
  3. Using this instead of other, simpler, queue implementations (slice+append or linked list) provides
  4. substantial memory and time benefits, and fewer GC pauses.
  5. The queue implemented here is as fast as it is for an additional reason: it is *not* thread-safe.
  6. */
  7. package queue
  8. const minQueueLen = 16
  9. // Queue represents a single instance of the queue data structure.
  10. type Queue struct {
  11. buf []interface{}
  12. head, tail, count int
  13. }
  14. // New constructs and returns a new Queue.
  15. func New() *Queue {
  16. return &Queue{
  17. buf: make([]interface{}, minQueueLen),
  18. }
  19. }
  20. // Length returns the number of elements currently stored in the queue.
  21. func (q *Queue) Length() int {
  22. return q.count
  23. }
  24. // resizes the queue to fit exactly twice its current contents
  25. // this can result in shrinking if the queue is less than half-full
  26. func (q *Queue) resize() {
  27. newBuf := make([]interface{}, q.count*2)
  28. if q.tail > q.head {
  29. copy(newBuf, q.buf[q.head:q.tail])
  30. } else {
  31. n := copy(newBuf, q.buf[q.head:])
  32. copy(newBuf[n:], q.buf[:q.tail])
  33. }
  34. q.head = 0
  35. q.tail = q.count
  36. q.buf = newBuf
  37. }
  38. // Add puts an element on the end of the queue.
  39. func (q *Queue) Add(elem interface{}) {
  40. if q.count == len(q.buf) {
  41. q.resize()
  42. }
  43. q.buf[q.tail] = elem
  44. q.tail = (q.tail + 1) % len(q.buf)
  45. q.count++
  46. }
  47. // Peek returns the element at the head of the queue. This call panics
  48. // if the queue is empty.
  49. func (q *Queue) Peek() interface{} {
  50. if q.count <= 0 {
  51. panic("queue: Peek() called on empty queue")
  52. }
  53. return q.buf[q.head]
  54. }
  55. // Get returns the element at index i in the queue. If the index is
  56. // invalid, the call will panic. This method accepts both positive and
  57. // negative index values. Index 0 refers to the first element, and
  58. // index -1 refers to the last.
  59. func (q *Queue) Get(i int) interface{} {
  60. // If indexing backwards, convert to positive index.
  61. if i < 0 {
  62. i += q.count
  63. }
  64. if i < 0 || i >= q.count {
  65. panic("queue: Get() called with index out of range")
  66. }
  67. return q.buf[(q.head+i)%len(q.buf)]
  68. }
  69. // Remove removes the element from the front of the queue. If you actually
  70. // want the element, call Peek first. This call panics if the queue is empty.
  71. func (q *Queue) Remove() {
  72. if q.count <= 0 {
  73. panic("queue: Remove() called on empty queue")
  74. }
  75. q.buf[q.head] = nil
  76. q.head = (q.head + 1) % len(q.buf)
  77. q.count--
  78. if len(q.buf) > minQueueLen && q.count*4 == len(q.buf) {
  79. q.resize()
  80. }
  81. }