queue.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (c) 2013-2017, Peter H. Froehlich. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license
  3. // that can be found in the LICENSE file.
  4. // Package queue implements a double-ended queue (aka "deque") on top
  5. // of a slice. All operations are (amortized) constant time.
  6. // Benchmarks compare favorably to container/list as well as to Go's
  7. // channels.
  8. package queue
  9. import (
  10. "bytes"
  11. "fmt"
  12. )
  13. // Queue represents a double-ended queue.
  14. // The zero value for Queue is an empty queue ready to use.
  15. type Queue struct {
  16. // PushBack writes to rep[back] and then increments
  17. // back; PushFront decrements front and then writes
  18. // to rep[front]; len(rep) must be a power of two;
  19. // gotta love those invariants.
  20. rep []interface{}
  21. front int
  22. back int
  23. length int
  24. }
  25. // New returns an initialized empty queue.
  26. func New() *Queue {
  27. return new(Queue).Init()
  28. }
  29. // Init initializes or clears queue q.
  30. func (q *Queue) Init() *Queue {
  31. q.rep = make([]interface{}, 1)
  32. // I considered reusing the existing slice if all a client does
  33. // is re-initialize the queue. The problem is that the current
  34. // queue might be huge, but the next one might not grow much. So
  35. // we'd hold on to a huge chunk of memory for just a few elements
  36. // and nobody can do anything. Making a new slice and letting the
  37. // GC take care of the old one seems like a better tradeoff.
  38. q.front, q.back, q.length = 0, 0, 0
  39. return q
  40. }
  41. // lazyInit lazily initializes a zero Queue value.
  42. //
  43. // I am mostly doing this because container/list does the same thing.
  44. // Personally I think it's a little wasteful because every single
  45. // PushFront/PushBack is going to pay the overhead of calling this.
  46. // But that's the price for making zero values useful immediately.
  47. func (q *Queue) lazyInit() {
  48. if q.rep == nil {
  49. q.Init()
  50. }
  51. }
  52. // Len returns the number of elements of queue q.
  53. func (q *Queue) Len() int {
  54. return q.length
  55. }
  56. // empty returns true if the queue q has no elements.
  57. func (q *Queue) empty() bool {
  58. return q.length == 0
  59. }
  60. // full returns true if the queue q is at capacity.
  61. func (q *Queue) full() bool {
  62. return q.length == len(q.rep)
  63. }
  64. // sparse returns true if the queue q has excess capacity.
  65. func (q *Queue) sparse() bool {
  66. return 1 < q.length && q.length < len(q.rep)/4
  67. }
  68. // grow doubles the size of queue q's underlying slice.
  69. func (q *Queue) grow() {
  70. bigger := make([]interface{}, len(q.rep)*2)
  71. // Kudos to Rodrigo Moraes, see https://gist.github.com/moraes/2141121
  72. // Kudos to Dariusz Górecki, see https://github.com/eapache/queue/commit/334cc1b02398be651373851653017e6cbf588f9e
  73. n := copy(bigger, q.rep[q.front:])
  74. copy(bigger[n:], q.rep[:q.back])
  75. // The above replaced the "obvious" for loop and is a bit tricky.
  76. // First note that q.front == q.back if we're full; if that wasn't
  77. // true, things would be more complicated. Second recall that for
  78. // a slice [lo:hi] the lo bound is inclusive whereas the hi bound
  79. // is exclusive. If that doesn't convince you that the above works
  80. // maybe drawing out some pictures for a concrete example will?
  81. q.rep = bigger
  82. q.front = 0
  83. q.back = q.length
  84. }
  85. // lazyGrow grows the underlying slice if necessary.
  86. func (q *Queue) lazyGrow() {
  87. if q.full() {
  88. q.grow()
  89. }
  90. }
  91. // shrink halves the size of queue q's underlying slice.
  92. func (q *Queue) shrink() {
  93. smaller := make([]interface{}, len(q.rep)/2)
  94. if q.front < q.back {
  95. copy(smaller, q.rep[q.front:q.back])
  96. } else {
  97. n := copy(smaller, q.rep[q.front:])
  98. copy(smaller[n:], q.rep[:q.back])
  99. }
  100. q.rep = smaller
  101. q.front = 0
  102. q.back = q.length
  103. }
  104. // lazyShrink shrinks the underlying slice if advisable.
  105. func (q *Queue) lazyShrink() {
  106. if q.sparse() {
  107. q.shrink()
  108. }
  109. }
  110. // String returns a string representation of queue q formatted
  111. // from front to back.
  112. func (q *Queue) String() string {
  113. var result bytes.Buffer
  114. result.WriteString("[")
  115. j := q.front
  116. for i := 0; i < q.length; i++ {
  117. result.WriteString(fmt.Sprintf("%v", q.rep[j]))
  118. if i < q.length-1 {
  119. result.WriteRune(' ')
  120. }
  121. j = q.inc(j)
  122. }
  123. result.WriteString("]")
  124. return result.String()
  125. }
  126. // inc returns the next integer position wrapping around queue q.
  127. func (q *Queue) inc(i int) int {
  128. return (i + 1) & (len(q.rep) - 1) // requires l = 2^n
  129. }
  130. // dec returns the previous integer position wrapping around queue q.
  131. func (q *Queue) dec(i int) int {
  132. return (i - 1) & (len(q.rep) - 1) // requires l = 2^n
  133. }
  134. // Front returns the first element of queue q or nil.
  135. func (q *Queue) Front() interface{} {
  136. if q.empty() {
  137. return nil
  138. }
  139. return q.rep[q.front]
  140. }
  141. // Back returns the last element of queue q or nil.
  142. func (q *Queue) Back() interface{} {
  143. if q.empty() {
  144. return nil
  145. }
  146. return q.rep[q.dec(q.back)]
  147. }
  148. // PushFront inserts a new value v at the front of queue q.
  149. func (q *Queue) PushFront(v interface{}) {
  150. q.lazyInit()
  151. q.lazyGrow()
  152. q.front = q.dec(q.front)
  153. q.rep[q.front] = v
  154. q.length++
  155. }
  156. // PushBack inserts a new value v at the back of queue q.
  157. func (q *Queue) PushBack(v interface{}) {
  158. q.lazyInit()
  159. q.lazyGrow()
  160. q.rep[q.back] = v
  161. q.back = q.inc(q.back)
  162. q.length++
  163. }
  164. // PopFront removes and returns the first element of queue q or nil.
  165. func (q *Queue) PopFront() interface{} {
  166. if q.empty() {
  167. return nil
  168. }
  169. v := q.rep[q.front]
  170. q.rep[q.front] = nil // be nice to GC
  171. q.front = q.inc(q.front)
  172. q.length--
  173. q.lazyShrink()
  174. return v
  175. }
  176. // PopBack removes and returns the last element of queue q or nil.
  177. func (q *Queue) PopBack() interface{} {
  178. if q.empty() {
  179. return nil
  180. }
  181. q.back = q.dec(q.back)
  182. v := q.rep[q.back]
  183. q.rep[q.back] = nil // be nice to GC
  184. q.length--
  185. q.lazyShrink()
  186. return v
  187. }