ring.go 951 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package collection
  2. import "sync"
  3. // A Ring can be used as fixed size ring.
  4. type Ring struct {
  5. elements []any
  6. index int
  7. lock sync.RWMutex
  8. }
  9. // NewRing returns a Ring object with the given size n.
  10. func NewRing(n int) *Ring {
  11. if n < 1 {
  12. panic("n should be greater than 0")
  13. }
  14. return &Ring{
  15. elements: make([]any, n),
  16. }
  17. }
  18. // Add adds v into r.
  19. func (r *Ring) Add(v any) {
  20. r.lock.Lock()
  21. defer r.lock.Unlock()
  22. rlen := len(r.elements)
  23. r.elements[r.index%rlen] = v
  24. r.index++
  25. // prevent ring index overflow
  26. if r.index >= rlen<<1 {
  27. r.index -= rlen
  28. }
  29. }
  30. // Take takes all items from r.
  31. func (r *Ring) Take() []any {
  32. r.lock.RLock()
  33. defer r.lock.RUnlock()
  34. var size int
  35. var start int
  36. rlen := len(r.elements)
  37. if r.index > rlen {
  38. size = rlen
  39. start = r.index % rlen
  40. } else {
  41. size = r.index
  42. }
  43. elements := make([]any, size)
  44. for i := 0; i < size; i++ {
  45. elements[i] = r.elements[(start+i)%rlen]
  46. }
  47. return elements
  48. }