herald.go/db/stack/stack.go
Jonathan Moody 8ac89195db Add element type param T to SlicedBacked[T]. Require T satisfy
constraints.Ordered to make BisectRight() statically type-safe.
2022-08-30 16:24:43 -05:00

102 lines
1.7 KiB
Go

package stack
// The db_stack package contains the implementation of a generic slice backed stack
// used for tracking various states in the hub, i.e. headers and txcounts
import (
"sync"
"github.com/lbryio/herald.go/internal"
"golang.org/x/exp/constraints"
)
type SliceBacked[T any] struct {
slice []T
len uint32
mut sync.RWMutex
}
func NewSliceBacked[T any](size int) *SliceBacked[T] {
return &SliceBacked[T]{
slice: make([]T, size),
len: 0,
mut: sync.RWMutex{},
}
}
func (s *SliceBacked[T]) Push(v T) {
s.mut.Lock()
defer s.mut.Unlock()
if s.len == uint32(len(s.slice)) {
s.slice = append(s.slice, v)
} else {
s.slice[s.len] = v
}
s.len++
}
func (s *SliceBacked[T]) Pop() T {
s.mut.Lock()
defer s.mut.Unlock()
if s.len == 0 {
var null T
return null
}
s.len--
return s.slice[s.len]
}
func (s *SliceBacked[T]) Get(i uint32) T {
s.mut.RLock()
defer s.mut.RUnlock()
if i >= s.len {
var null T
return null
}
return s.slice[i]
}
func (s *SliceBacked[T]) GetTip() T {
s.mut.RLock()
defer s.mut.RUnlock()
if s.len == 0 {
var null T
return null
}
return s.slice[s.len-1]
}
func (s *SliceBacked[T]) Len() uint32 {
s.mut.RLock()
defer s.mut.RUnlock()
return s.len
}
func (s *SliceBacked[T]) Cap() int {
s.mut.RLock()
defer s.mut.RUnlock()
return cap(s.slice)
}
func (s *SliceBacked[T]) GetSlice() []T {
// This is not thread safe so I won't bother with locking
return s.slice
}
func BisectRight[T constraints.Ordered](s *SliceBacked[T], searchKeys []T) []uint32 {
s.mut.RLock()
defer s.mut.RUnlock()
found := make([]uint32, len(searchKeys))
for i, k := range searchKeys {
found[i] = internal.BisectRight(s.slice[:s.Len()], k)
}
return found
}