package wazevoapi
const poolPageSize = 128
type Pool [T any ] struct {
pages []*[poolPageSize ]T
resetFn func (*T )
allocated, index int
}
func NewPool [T any ](resetFn func (*T )) Pool [T ] {
var ret Pool [T ]
ret .resetFn = resetFn
ret .Reset ()
return ret
}
func (p *Pool [T ]) Allocated () int {
return p .allocated
}
func (p *Pool [T ]) Allocate () *T {
if p .index == poolPageSize {
if len (p .pages ) == cap (p .pages ) {
p .pages = append (p .pages , new ([poolPageSize ]T ))
} else {
i := len (p .pages )
p .pages = p .pages [:i +1 ]
if p .pages [i ] == nil {
p .pages [i ] = new ([poolPageSize ]T )
}
}
p .index = 0
}
ret := &p .pages [len (p .pages )-1 ][p .index ]
if p .resetFn != nil {
p .resetFn (ret )
}
p .index ++
p .allocated ++
return ret
}
func (p *Pool [T ]) View (i int ) *T {
page , index := i /poolPageSize , i %poolPageSize
return &p .pages [page ][index ]
}
func (p *Pool [T ]) Reset () {
p .pages = p .pages [:0 ]
p .index = poolPageSize
p .allocated = 0
}
type IDedPool [T any ] struct {
pool Pool [T ]
idToItems []*T
maxIDEncountered int
}
func NewIDedPool [T any ](resetFn func (*T )) IDedPool [T ] {
return IDedPool [T ]{pool : NewPool [T ](resetFn ), maxIDEncountered : -1 }
}
func (p *IDedPool [T ]) GetOrAllocate (id int ) *T {
if p .maxIDEncountered < id {
p .maxIDEncountered = id
}
if id >= len (p .idToItems ) {
p .idToItems = append (p .idToItems , make ([]*T , id -len (p .idToItems )+1 )...)
}
if p .idToItems [id ] == nil {
p .idToItems [id ] = p .pool .Allocate ()
}
return p .idToItems [id ]
}
func (p *IDedPool [T ]) Get (id int ) *T {
if id >= len (p .idToItems ) {
return nil
}
return p .idToItems [id ]
}
func (p *IDedPool [T ]) Reset () {
p .pool .Reset ()
for i := 0 ; i <= p .maxIDEncountered ; i ++ {
p .idToItems [i ] = nil
}
p .maxIDEncountered = -1
}
func (p *IDedPool [T ]) MaxIDEncountered () int {
return p .maxIDEncountered
}
const arraySize = 8
type (
VarLengthPool [T any ] struct {
arrayPool Pool [varLengthPoolArray [T ]]
slicePool Pool [[]T ]
}
varLengthPoolArray[T any ] struct {
arr [arraySize ]T
next int
}
)
type VarLength [T any ] struct {
arr *varLengthPoolArray [T ]
slc *[]T
}
func NewVarLengthPool [T any ]() VarLengthPool [T ] {
return VarLengthPool [T ]{
arrayPool : NewPool [varLengthPoolArray [T ]](func (v *varLengthPoolArray [T ]) {
v .next = 0
}),
slicePool : NewPool [[]T ](func (i *[]T ) {
*i = (*i )[:0 ]
}),
}
}
func NewNilVarLength [T any ]() VarLength [T ] {
return VarLength [T ]{}
}
func (p *VarLengthPool [T ]) Allocate (knownMin int ) VarLength [T ] {
if knownMin <= arraySize {
arr := p .arrayPool .Allocate ()
return VarLength [T ]{arr : arr }
}
slc := p .slicePool .Allocate ()
return VarLength [T ]{slc : slc }
}
func (p *VarLengthPool [T ]) Reset () {
p .arrayPool .Reset ()
p .slicePool .Reset ()
}
func (i VarLength [T ]) Append (p *VarLengthPool [T ], items ...T ) VarLength [T ] {
if i .slc != nil {
*i .slc = append (*i .slc , items ...)
return i
}
if i .arr == nil {
i .arr = p .arrayPool .Allocate ()
}
arr := i .arr
if arr .next +len (items ) <= arraySize {
for _ , item := range items {
arr .arr [arr .next ] = item
arr .next ++
}
} else {
slc := p .slicePool .Allocate ()
for ptr := 0 ; ptr < arr .next ; ptr ++ {
*slc = append (*slc , arr .arr [ptr ])
}
i .slc = slc
*i .slc = append (*i .slc , items ...)
}
return i
}
func (i VarLength [T ]) View () []T {
if i .slc != nil {
return *i .slc
} else if i .arr != nil {
arr := i .arr
return arr .arr [:arr .next ]
}
return nil
}
func (i VarLength [T ]) Cut (n int ) {
if i .slc != nil {
*i .slc = (*i .slc )[:n ]
} else if i .arr != nil {
i .arr .next = n
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .