go-zero/core/collection/ring.go

61 lines
951 B
Go
Raw Normal View History

2020-07-26 17:09:05 +08:00
package collection
import "sync"
// A Ring can be used as fixed size ring.
2020-07-26 17:09:05 +08:00
type Ring struct {
elements []any
2020-07-26 17:09:05 +08:00
index int
lock sync.RWMutex
2020-07-26 17:09:05 +08:00
}
// NewRing returns a Ring object with the given size n.
2020-07-26 17:09:05 +08:00
func NewRing(n int) *Ring {
2020-10-15 14:25:10 +08:00
if n < 1 {
panic("n should be greater than 0")
}
2020-07-26 17:09:05 +08:00
return &Ring{
elements: make([]any, n),
2020-07-26 17:09:05 +08:00
}
}
// Add adds v into r.
func (r *Ring) Add(v any) {
r.lock.Lock()
defer r.lock.Unlock()
2021-02-05 13:32:56 +08:00
2023-11-23 23:57:26 +08:00
rlen := len(r.elements)
r.elements[r.index%rlen] = v
2020-07-26 17:09:05 +08:00
r.index++
// prevent ring index overflow
2023-11-23 23:57:26 +08:00
if r.index >= rlen<<1 {
r.index -= rlen
}
2020-07-26 17:09:05 +08:00
}
// Take takes all items from r.
func (r *Ring) Take() []any {
r.lock.RLock()
defer r.lock.RUnlock()
2020-07-26 17:09:05 +08:00
var size int
var start int
2023-11-23 23:57:26 +08:00
rlen := len(r.elements)
2023-11-23 23:57:26 +08:00
if r.index > rlen {
size = rlen
start = r.index % rlen
2020-07-26 17:09:05 +08:00
} else {
size = r.index
}
elements := make([]any, size)
2020-07-26 17:09:05 +08:00
for i := 0; i < size; i++ {
2023-11-23 23:57:26 +08:00
elements[i] = r.elements[(start+i)%rlen]
2020-07-26 17:09:05 +08:00
}
return elements
}