erigon-pulse/erigon-lib/common/ring/ring.go
a 436493350e
Sentinel refactor (#8296)
1. changes sentinel to use an http-like interface

2. moves hexutil, crypto/blake2b, metrics packages to erigon-lib
2023-10-22 01:17:18 +02:00

157 lines
2.3 KiB
Go

package ring
type Buffer[T any] struct {
buf []T
// real head is head-1, like this so nil ring is valid
head int
tail int
length int
}
func MakeBuffer[T any](length, capacity int) Buffer[T] {
if length > capacity {
panic("length must be less than capacity")
}
return Buffer[T]{
buf: make([]T, capacity),
tail: length,
length: length,
}
}
func NewBuffer[T any](length, capacity int) *Buffer[T] {
r := MakeBuffer[T](length, capacity)
return &r
}
func (r *Buffer[T]) grow() {
size := len(r.buf) * 2
if size == 0 {
size = 2
}
buf := make([]T, size)
copy(buf, r.buf[r.head:])
copy(buf[len(r.buf[r.head:]):], r.buf[:r.head])
r.head = 0
r.tail = r.length
r.buf = buf
}
func (r *Buffer[T]) incHead() {
// resize
if r.length == 0 {
panic("smashing detected")
}
r.length--
r.head++
if r.head == len(r.buf) {
r.head = 0
}
}
func (r *Buffer[T]) decHead() {
// resize
if r.length == len(r.buf) {
r.grow()
}
r.length++
r.head--
if r.head == -1 {
r.head = len(r.buf) - 1
}
}
func (r *Buffer[T]) incTail() {
// resize
if r.length == len(r.buf) {
r.grow()
}
r.length++
r.tail++
if r.tail == len(r.buf) {
r.tail = 0
}
}
func (r *Buffer[T]) decTail() {
// resize
if r.length == 0 {
panic("smashing detected")
}
r.length--
r.tail--
if r.tail == -1 {
r.tail = len(r.buf) - 1
}
}
func (r *Buffer[T]) tailSub1() int {
tail := r.tail - 1
if tail == -1 {
tail = len(r.buf) - 1
}
return tail
}
func (r *Buffer[T]) PopFront() (T, bool) {
if r.length == 0 {
return *new(T), false
}
front := r.buf[r.head]
r.buf[r.head] = *new(T)
r.incHead()
return front, true
}
func (r *Buffer[T]) PopBack() (T, bool) {
if r.length == 0 {
return *new(T), false
}
r.decTail()
back := r.buf[r.tail]
r.buf[r.tail] = *new(T)
return back, true
}
func (r *Buffer[T]) Clear() {
r.head = 0
r.tail = 0
r.length = 0
}
func (r *Buffer[T]) PushFront(value T) {
r.decHead()
r.buf[r.head] = value
}
func (r *Buffer[T]) PushBack(value T) {
r.incTail()
r.buf[r.tailSub1()] = value
}
func (r *Buffer[T]) Length() int {
return r.length
}
func (r *Buffer[T]) Capacity() int {
return len(r.buf)
}
func (r *Buffer[T]) Get(n int) T {
if n >= r.length {
panic("index out of range")
}
ptr := r.head + n
if ptr >= len(r.buf) {
ptr -= len(r.buf)
}
return r.buf[ptr]
}