queue.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // mgo - MongoDB driver for Go
  2. //
  3. // Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
  4. //
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // 1. Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // 2. Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. package mgo
  27. type queue struct {
  28. elems []interface{}
  29. nelems, popi, pushi int
  30. }
  31. func (q *queue) Len() int {
  32. return q.nelems
  33. }
  34. func (q *queue) Push(elem interface{}) {
  35. //debugf("Pushing(pushi=%d popi=%d cap=%d): %#v\n",
  36. // q.pushi, q.popi, len(q.elems), elem)
  37. if q.nelems == len(q.elems) {
  38. q.expand()
  39. }
  40. q.elems[q.pushi] = elem
  41. q.nelems++
  42. q.pushi = (q.pushi + 1) % len(q.elems)
  43. //debugf(" Pushed(pushi=%d popi=%d cap=%d): %#v\n",
  44. // q.pushi, q.popi, len(q.elems), elem)
  45. }
  46. func (q *queue) Pop() (elem interface{}) {
  47. //debugf("Popping(pushi=%d popi=%d cap=%d)\n",
  48. // q.pushi, q.popi, len(q.elems))
  49. if q.nelems == 0 {
  50. return nil
  51. }
  52. elem = q.elems[q.popi]
  53. q.elems[q.popi] = nil // Help GC.
  54. q.nelems--
  55. q.popi = (q.popi + 1) % len(q.elems)
  56. //debugf(" Popped(pushi=%d popi=%d cap=%d): %#v\n",
  57. // q.pushi, q.popi, len(q.elems), elem)
  58. return elem
  59. }
  60. func (q *queue) expand() {
  61. curcap := len(q.elems)
  62. var newcap int
  63. if curcap == 0 {
  64. newcap = 8
  65. } else if curcap < 1024 {
  66. newcap = curcap * 2
  67. } else {
  68. newcap = curcap + (curcap / 4)
  69. }
  70. elems := make([]interface{}, newcap)
  71. if q.popi == 0 {
  72. copy(elems, q.elems)
  73. q.pushi = curcap
  74. } else {
  75. newpopi := newcap - (curcap - q.popi)
  76. copy(elems, q.elems[:q.popi])
  77. copy(elems[newpopi:], q.elems[q.popi:])
  78. q.popi = newpopi
  79. }
  80. for i := range q.elems {
  81. q.elems[i] = nil // Help GC.
  82. }
  83. q.elems = elems
  84. }