queue.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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{buf: make([]interface{}, minQueueLen)}
  17. }
  18. // Length returns the number of elements currently stored in the queue.
  19. func (q *Queue) Length() int {
  20. return q.count
  21. }
  22. func (q *Queue) resize() {
  23. newBuf := make([]interface{}, q.count*2)
  24. if q.tail > q.head {
  25. copy(newBuf, q.buf[q.head:q.tail])
  26. } else {
  27. copy(newBuf, q.buf[q.head:len(q.buf)])
  28. copy(newBuf[len(q.buf)-q.head:], q.buf[:q.tail])
  29. }
  30. q.head = 0
  31. q.tail = q.count
  32. q.buf = newBuf
  33. }
  34. // Add puts an element on the end of the queue.
  35. func (q *Queue) Add(elem interface{}) {
  36. if q.count == len(q.buf) {
  37. q.resize()
  38. }
  39. q.buf[q.tail] = elem
  40. q.tail = (q.tail + 1) % len(q.buf)
  41. q.count++
  42. }
  43. // Peek returns the element at the head of the queue. This call panics
  44. // if the queue is empty.
  45. func (q *Queue) Peek() interface{} {
  46. if q.Length() <= 0 {
  47. panic("queue: empty queue")
  48. }
  49. return q.buf[q.head]
  50. }
  51. // Get returns the element at index i in the queue. If the index is
  52. // invalid, the call will panic.
  53. func (q *Queue) Get(i int) interface{} {
  54. if i >= q.Length() || i < 0 {
  55. panic("queue: index out of range")
  56. }
  57. modi := (q.head + i) % len(q.buf)
  58. return q.buf[modi]
  59. }
  60. // Remove removes the element from the front of the queue. If you actually
  61. // want the element, call Peek first. This call panics if the queue is empty.
  62. func (q *Queue) Remove() {
  63. if q.Length() <= 0 {
  64. panic("queue: empty queue")
  65. }
  66. q.buf[q.head] = nil
  67. q.head = (q.head + 1) % len(q.buf)
  68. q.count--
  69. if len(q.buf) > minQueueLen && q.count*4 <= len(q.buf) {
  70. q.resize()
  71. }
  72. }