delve/vendor/github.com/aquasecurity/libbpfgo/helpers/rwArray.go
2021-07-31 17:16:26 +02:00

75 lines
1.5 KiB
Go

package helpers
import (
"sync"
)
type slot struct {
value interface{}
used bool
}
// RWArray allows for multiple concurrent readers but
// only a single writer. The writers lock a mutex while the readers
// are lock free.
// It is implemented as an array of slots where each slot holds a
// value (of type interface{}) and a boolean marker to indicate if it's
// in use or not. The insertion (Put) performs a linear probe
// looking for an available slot as indicated by the in-use marker.
// While probing, it is not touching the value itself, as it's
// being read without a lock by the readers.
type RWArray struct {
slots []slot
mux sync.Mutex
}
func NewRWArray(capacity uint) RWArray {
return RWArray{
slots: make([]slot, capacity),
}
}
func (a *RWArray) Put(v interface{}) int {
a.mux.Lock()
defer a.mux.Unlock()
limit := len(a.slots)
for i := 0; i < limit; i++ {
if !a.slots[i].used {
a.slots[i].value = v
a.slots[i].used = true
return i
}
}
return -1
}
func (a *RWArray) Remove(index uint) {
a.mux.Lock()
defer a.mux.Unlock()
if int(index) >= len(a.slots) {
return
}
a.slots[index].value = nil
a.slots[index].used = false
}
func (a *RWArray) Get(index uint) interface{} {
if int(index) >= len(a.slots) {
return nil
}
// N.B. If slot[index].used == false, this is technically
// a race since Put() might be putting the value in there
// at the same time.
return a.slots[index].value
}
func (a *RWArray) Capacity() uint {
return uint(len(a.slots))
}