xx/alloc/alloc.go
2025-12-12 17:11:22 -07:00

78 lines
1.7 KiB
Go

package alloc
import (
"unsafe"
"git.brut.systems/judah/xx/mem"
)
// New returns a pointer to an Allocator allocated value of type T.
//
// Note: If allocation fails, New will panic.
func New[T any](alloc Allocator) *T {
ptr, err := alloc(ActionAlloc, mem.SizeOf[T](), mem.AlignOf[T](), nil)
if err != nil {
panic(err)
}
return (*T)(ptr)
}
// Reset restores an Allocator to its initial state.
//
// Note: Use of memory allocated by an Allocator after calling Reset is unsafe.
func Reset(alloc Allocator) {
if _, err := alloc(ActionReset, 0, 0, nil); err != nil {
panic(err)
}
}
// Save returns the current state of an Allocator.
//
// Note: The value returned is internal to the particular Allocator Save was called on.
// The value should not be modified.
func Save(alloc Allocator) (watermark uintptr) {
if _, err := alloc(ActionSave, 0, 0, &watermark); err != nil {
panic(err)
}
return
}
// Restore restores an Allocator to a previously saved state.
func Restore(alloc Allocator, watermark uintptr) {
if _, err := alloc(ActionRestore, 0, 0, &watermark); err != nil {
panic(err)
}
}
// Allocator represents a memory allocator.
type Allocator func(a Action, size, align uintptr, watermark *uintptr) (unsafe.Pointer, error)
// Action is a list of distinct events an Allocator may respond to.
type Action int
const (
ActionAlloc Action = iota
ActionReset
ActionSave
ActionRestore
ActionReport
)
func (a Action) String() string {
switch a {
case ActionAlloc:
return "Alloc"
case ActionReset:
return "Reset"
case ActionSave:
return "Save"
case ActionRestore:
return "Restore"
case ActionReport:
return "Report"
default:
panic("unreachable")
}
}