ring.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package appsrv
  15. import (
  16. "sync"
  17. )
  18. type Ring struct {
  19. buffer []interface{}
  20. header, tail int
  21. lock *sync.Mutex
  22. }
  23. func NewRing(size int) *Ring {
  24. r := Ring{
  25. buffer: make([]interface{}, size+1),
  26. header: 0,
  27. tail: 0,
  28. lock: &sync.Mutex{},
  29. }
  30. return &r
  31. }
  32. func nextPointer(idx int, size int) int {
  33. idx = idx + 1
  34. if idx >= size {
  35. idx = 0
  36. }
  37. return idx
  38. }
  39. func (r *Ring) Push(val interface{}) bool {
  40. r.lock.Lock()
  41. defer r.lock.Unlock()
  42. if nextPointer(r.header, len(r.buffer)) == r.tail {
  43. return false
  44. }
  45. r.buffer[r.header] = val
  46. r.header = nextPointer(r.header, len(r.buffer))
  47. return true
  48. }
  49. func (r *Ring) Pop() interface{} {
  50. r.lock.Lock()
  51. defer r.lock.Unlock()
  52. if r.tail == r.header {
  53. return nil
  54. }
  55. ret := r.buffer[r.tail]
  56. r.buffer[r.tail] = nil
  57. r.tail = nextPointer(r.tail, len(r.buffer))
  58. return ret
  59. }
  60. func (r *Ring) Capacity() int {
  61. return len(r.buffer) - 1
  62. }
  63. func (r *Ring) Size() int {
  64. r.lock.Lock()
  65. defer r.lock.Unlock()
  66. if r.tail <= r.header {
  67. return r.header - r.tail
  68. } else {
  69. return len(r.buffer) - r.tail + r.header
  70. }
  71. }
  72. func (r *Ring) Range(proc func(obj interface{}) bool) {
  73. r.lock.Lock()
  74. defer r.lock.Unlock()
  75. for i := r.header; i != r.tail && i != r.header; i = nextPointer(i, len(r.buffer)) {
  76. cont := proc(r.buffer[i])
  77. if !cont {
  78. break
  79. }
  80. }
  81. }