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 (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 (func (v *varLengthPoolArray [T ]) {
v .next = 0
}),
slicePool : NewPool (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 ()
if cap (*slc ) < knownMin {
*slc = make ([]T , 0 , knownMin )
}
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 ] {
slc := i .slc
if slc != nil {
*slc = append (*slc , items ...)
return i
}
arr := i .arr
if arr == nil {
arr = p .arrayPool .Allocate ()
i .arr = arr
}
if arr .next +len (items ) <= arraySize {
arr .next += copy (arr .arr [arr .next :], items )
} else {
slc = p .slicePool .Allocate ()
*slc = append (*slc , arr .arr [:arr .next ]...)
*slc = append (*slc , items ...)
i .slc = slc
}
return i
}
func (i VarLength [T ]) View () []T {
if slc := i .slc ; slc != nil {
return *i .slc
}
if arr := i .arr ; arr != nil {
return arr .arr [:arr .next ]
}
return nil
}
func (i VarLength [T ]) Cut (n int ) {
if slc := i .slc ; slc != nil {
*slc = (*slc )[:n ]
} else if arr := i .arr ; arr != nil {
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 .