queue.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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 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. const minQueueLen = 16
  11. type Queue struct {
  12. buf []interface{}
  13. head, tail, count int
  14. }
  15. // New constructs and returns a new Queue
  16. func New() *Queue {
  17. return &Queue{buf: make([]interface{}, minQueueLen)}
  18. }
  19. // Length returns the number of elements currently stored in the queue
  20. func (q *Queue) Length() int {
  21. return q.count
  22. }
  23. func (q *Queue) resize() {
  24. newBuf := make([]interface{}, q.count*2)
  25. if q.tail > q.head {
  26. copy(newBuf, q.buf[q.head:q.tail])
  27. } else {
  28. copy(newBuf, q.buf[q.head:len(q.buf)])
  29. copy(newBuf[len(q.buf)-q.head:], q.buf[:q.tail])
  30. }
  31. q.head = 0
  32. q.tail = q.count
  33. q.buf = newBuf
  34. }
  35. // Add puts an element on the end of the queue
  36. func (q *Queue) Add(elem interface{}) {
  37. if q.count == len(q.buf) {
  38. q.resize()
  39. }
  40. q.buf[q.tail] = elem
  41. q.tail = (q.tail + 1) % len(q.buf)
  42. q.count++
  43. }
  44. // Peek returns the element at the head of the queue. If the queue is empty (Length == 0),
  45. // Peek does not panic, it simply returns garbage.
  46. func (q *Queue) Peek() interface{} {
  47. return q.buf[q.head]
  48. }
  49. // Remove removes the element from the front of the queue. If you actually want the element,
  50. // call Peek first. If the queue is empty (Length == 0), Remove will put the queue in a bad
  51. // state and all further operations will be undefined.
  52. func (q *Queue) Remove() {
  53. q.buf[q.head] = nil
  54. q.head = (q.head + 1) % len(q.buf)
  55. q.count--
  56. if len(q.buf) > minQueueLen && q.count*4 <= len(q.buf) {
  57. q.resize()
  58. }
  59. }