Files
deep_go/lessons/allocator/pool_allocator/main.go

101 lines
2.1 KiB
Go
Raw Normal View History

package main
import (
"errors"
"fmt"
"unsafe"
)
type PoolAllocator struct {
objectPool []byte
freeObjects map[unsafe.Pointer]struct{}
objectSize int
}
func NewPoolAllocator(capacity int, objectSize int) (PoolAllocator, error) {
if capacity <= 0 || objectSize <= 0 || capacity%objectSize != 0 {
return PoolAllocator{}, errors.New("incorrect argumnets")
}
allocator := PoolAllocator{
objectPool: make([]byte, capacity),
freeObjects: make(map[unsafe.Pointer]struct{}, capacity/objectSize),
objectSize: objectSize,
}
allocator.resetMemoryState()
return allocator, nil
}
func (a *PoolAllocator) Allocate() (unsafe.Pointer, error) {
if len(a.freeObjects) == 0 {
// can increase capacity
return nil, errors.New("not enough memory")
}
var pointer unsafe.Pointer
for freePointer := range a.freeObjects {
pointer = freePointer
break
}
delete(a.freeObjects, pointer)
return pointer, nil
}
func (a *PoolAllocator) Deallocate(pointer unsafe.Pointer) error {
if pointer == nil {
return errors.New("incorrect pointer")
}
// potentionally incorrect pointer
a.freeObjects[pointer] = struct{}{}
return nil
}
func (a *PoolAllocator) Free() {
a.resetMemoryState()
}
func (a *PoolAllocator) resetMemoryState() {
for offset := 0; offset < len(a.objectPool); offset += a.objectSize {
pointer := unsafe.Pointer(&a.objectPool[offset])
a.freeObjects[pointer] = struct{}{}
}
}
func store[T any](pointer unsafe.Pointer, value T) {
*(*T)(pointer) = value
}
func load[T any](pointer unsafe.Pointer) T {
return *(*T)(pointer)
}
func main() {
const KB = 1 << 10
allocator, err := NewPoolAllocator(KB, 4)
if err != nil {
// handling...
}
defer allocator.Free()
pointer1, _ := allocator.Allocate()
pointer2, _ := allocator.Allocate()
store[int32](pointer1, 100)
store[int32](pointer2, 200)
value1 := load[int32](pointer1)
value2 := load[int32](pointer2)
fmt.Println("value1:", value1)
fmt.Println("value2:", value2)
fmt.Println("address1:", pointer1)
fmt.Println("address2:", pointer2)
allocator.Deallocate(pointer1)
allocator.Deallocate(pointer2)
}