DataHoarder
4ef60296f1
* 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
85 lines
1.6 KiB
Go
85 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
|
|
}
|