consensus/utils/circular_buffer.go
DataHoarder 4ef60296f1
Updated to Go 1.21
* Replaced exp/slices and exp/maps with slices/maps implementation
* Replaced utils.Min/Max with min/max
* Introduced GOEXPERIMENT=loopvar on build steps
* Updated tests/docker-compose to go1.21-rc-alpine
* Updated nginx to 1.25
* Preallocate mined blocks on Sidechain
* Update edwards25519 version
2023-07-20 07:40:18 +02:00

86 lines
1.6 KiB
Go

package utils
import (
"slices"
"sync"
"sync/atomic"
)
type CircularBuffer[T comparable] struct {
buffer []T
index atomic.Uint32
lock sync.RWMutex
}
func NewCircularBuffer[T comparable](size int) *CircularBuffer[T] {
return &CircularBuffer[T]{
buffer: make([]T, size),
}
}
func (b *CircularBuffer[T]) Push(value T) {
b.lock.Lock()
defer b.lock.Unlock()
b.buffer[b.index.Add(1)%uint32(len(b.buffer))] = value
}
func (b *CircularBuffer[T]) Current() T {
b.lock.RLock()
defer b.lock.RUnlock()
return b.buffer[b.index.Load()%uint32(len(b.buffer))]
}
func (b *CircularBuffer[T]) Get(index uint32) T {
b.lock.RLock()
defer b.lock.RUnlock()
return b.buffer[index%uint32(len(b.buffer))]
}
func (b *CircularBuffer[T]) Replace(value, replace T) {
b.lock.Lock()
defer b.lock.Unlock()
for i, v := range b.buffer {
if value == v {
b.buffer[i] = replace
}
}
}
func (b *CircularBuffer[T]) PushUnique(value T) bool {
b.lock.Lock()
defer b.lock.Unlock()
if len(b.buffer) == 0 || slices.Contains(b.buffer, value) {
return false
}
b.buffer[b.index.Add(1)%uint32(len(b.buffer))] = value
return true
}
func (b *CircularBuffer[T]) Reverse() {
b.lock.Lock()
defer b.lock.Unlock()
for i, j := 0, len(b.buffer)-1; i < j; i, j = i+1, j-1 {
b.buffer[i], b.buffer[j] = b.buffer[j], b.buffer[i]
}
}
func (b *CircularBuffer[T]) Exists(value T) bool {
b.lock.RLock()
defer b.lock.RUnlock()
return slices.Contains(b.buffer, value)
}
func (b *CircularBuffer[T]) Slice() []T {
s := make([]T, len(b.buffer))
b.lock.RLock()
defer b.lock.RUnlock()
copy(s, b.buffer)
return s
}