ring.go 1019 B

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