queue.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. // minQueueLen is smallest capacity that queue may have.
  9. // Must be power of 2 for bitwise modulus: x % n == x & (n - 1).
  10. const minQueueLen = 16
  11. // Queue represents a single instance of the queue data structure.
  12. type Queue struct {
  13. buf []interface{}
  14. head, tail, count int
  15. }
  16. // New constructs and returns a new Queue.
  17. func New() *Queue {
  18. return &Queue{
  19. buf: make([]interface{}, minQueueLen),
  20. }
  21. }
  22. // Length returns the number of elements currently stored in the queue.
  23. func (q *Queue) Length() int {
  24. return q.count
  25. }
  26. // resizes the queue to fit exactly twice its current contents
  27. // this can result in shrinking if the queue is less than half-full
  28. func (q *Queue) resize() {
  29. newBuf := make([]interface{}, q.count<<1)
  30. if q.tail > q.head {
  31. copy(newBuf, q.buf[q.head:q.tail])
  32. } else {
  33. n := copy(newBuf, q.buf[q.head:])
  34. copy(newBuf[n:], q.buf[:q.tail])
  35. }
  36. q.head = 0
  37. q.tail = q.count
  38. q.buf = newBuf
  39. }
  40. // Add puts an element on the end of the queue.
  41. func (q *Queue) Add(elem interface{}) {
  42. if q.count == len(q.buf) {
  43. q.resize()
  44. }
  45. q.buf[q.tail] = elem
  46. // bitwise modulus
  47. q.tail = (q.tail + 1) & (len(q.buf) - 1)
  48. q.count++
  49. }
  50. // Peek returns the element at the head of the queue. This call panics
  51. // if the queue is empty.
  52. func (q *Queue) Peek() interface{} {
  53. if q.count <= 0 {
  54. panic("queue: Peek() called on empty queue")
  55. }
  56. return q.buf[q.head]
  57. }
  58. // Get returns the element at index i in the queue. If the index is
  59. // invalid, the call will panic. This method accepts both positive and
  60. // negative index values. Index 0 refers to the first element, and
  61. // index -1 refers to the last.
  62. func (q *Queue) Get(i int) interface{} {
  63. // If indexing backwards, convert to positive index.
  64. if i < 0 {
  65. i += q.count
  66. }
  67. if i < 0 || i >= q.count {
  68. panic("queue: Get() called with index out of range")
  69. }
  70. // bitwise modulus
  71. return q.buf[(q.head+i)&(len(q.buf)-1)]
  72. }
  73. // Remove removes and returns the element from the front of the queue. If the
  74. // queue is empty, the call will panic.
  75. func (q *Queue) Remove() interface{} {
  76. if q.count <= 0 {
  77. panic("queue: Remove() called on empty queue")
  78. }
  79. ret := q.buf[q.head]
  80. q.buf[q.head] = nil
  81. // bitwise modulus
  82. q.head = (q.head + 1) & (len(q.buf) - 1)
  83. q.count--
  84. // Resize down if buffer 1/4 full.
  85. if len(q.buf) > minQueueLen && (q.count<<2) == len(q.buf) {
  86. q.resize()
  87. }
  88. return ret
  89. }