87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package arena
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"git.brut.systems/judah/xx/mem"
|
|
)
|
|
|
|
// New returns a pointer to an Arena allocated value of type T.
|
|
// If allocation fails, New will panic.
|
|
//
|
|
// Note: Accessing the returned value after calling Reset is unsafe and may result in a fault.
|
|
func New[T any](arena Arena) *T {
|
|
ptr, err := arena(ACTION_ALLOC, mem.Sizeof[T](), mem.Alignof[T](), nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return (*T)(ptr)
|
|
}
|
|
|
|
// MakeSlice creates an Arena allocated []T with the given capacity and length.
|
|
// If allocation fails, MakeSlice will panic.
|
|
//
|
|
// Note: Accessing the returned slice after calling Reset is unsafe and may result in a fault.
|
|
func MakeSlice[T any](arena Arena, len, cap int) []T {
|
|
ptr, err := arena(ACTION_ALLOC, mem.Sizeof[T]()*uintptr(len), mem.Alignof[T](), nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return unsafe.Slice((*T)(ptr), cap)[:len]
|
|
}
|
|
|
|
// Reset restores an Arena to its initial state.
|
|
//
|
|
// Note: Accessing memory returned by an Arena after calling Reset is unsafe and may result in a fault.
|
|
func Reset(arena Arena) {
|
|
if _, err := arena(ACTION_RESET, 0, 0, nil); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Save returns the restorable state of an Arena.
|
|
// The returned value is internal to the particular Arena and should not be modified.
|
|
func Save(arena Arena) (watermark uintptr) {
|
|
if _, err := arena(ACTION_SAVE, 0, 0, &watermark); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Restore restores an Arena to a previously saved state.
|
|
func Restore(arena Arena, watermark uintptr) {
|
|
if _, err := arena(ACTION_RESTORE, 0, 0, &watermark); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Arena represents a memory allocator.
|
|
type Arena func(a Action, size, align uintptr, watermark *uintptr) (unsafe.Pointer, error)
|
|
|
|
// Action is a list of distinct events an Arena may respond to.
|
|
type Action int
|
|
|
|
const (
|
|
ACTION_ALLOC Action = iota
|
|
ACTION_RESET
|
|
ACTION_SAVE
|
|
ACTION_RESTORE
|
|
)
|
|
|
|
func (a Action) String() string {
|
|
switch a {
|
|
case ACTION_ALLOC:
|
|
return "ALLOC"
|
|
case ACTION_RESET:
|
|
return "RESET"
|
|
case ACTION_SAVE:
|
|
return "SAVE"
|
|
case ACTION_RESTORE:
|
|
return "RESTORE"
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|