xx/stable/pointer.go

83 lines
1.5 KiB
Go

package stable
import (
"runtime"
"unsafe"
"git.brut.systems/judah/xx/mem"
)
type Pointer[T any] struct {
base unsafe.Pointer
pinner runtime.Pinner
}
func PointerPin[T any](ptr *T) (r Pointer[T]) {
r.pinner.Pin(ptr)
r.base = unsafe.Pointer(ptr)
return
}
func PointerCast[TOut, TIn any](p Pointer[TIn]) Pointer[TOut] {
return Pointer[TOut]{
base: unsafe.Pointer(p.base),
pinner: p.pinner,
}
}
func (p Pointer[T]) Unpin() {
p.pinner.Unpin()
p.base = nil
}
func (p Pointer[T]) Pointer() unsafe.Pointer {
return p.base
}
func (p Pointer[T]) Address() uintptr {
return uintptr(p.base)
}
func (p Pointer[T]) Nil() bool {
return p.base == nil
}
func (p Pointer[T]) Add(amount uintptr) Pointer[T] {
return Pointer[T]{
base: unsafe.Pointer(uintptr(p.base) + amount),
pinner: p.pinner,
}
}
func (p Pointer[T]) Sub(amount uintptr) Pointer[T] {
return Pointer[T]{
base: unsafe.Pointer(uintptr(p.base) - amount),
pinner: p.pinner,
}
}
func (p Pointer[T]) AlignForward(alignment uintptr) Pointer[T] {
return Pointer[T]{
base: unsafe.Pointer(mem.AlignForward(uintptr(p.base), alignment)),
pinner: p.pinner,
}
}
func (p Pointer[T]) AlignBackward(alignment uintptr) Pointer[T] {
return Pointer[T]{
base: unsafe.Pointer(mem.AlignBackward(uintptr(p.base), alignment)),
pinner: p.pinner,
}
}
func (p Pointer[T]) Load() T {
return *(*T)(p.base)
}
func (p Pointer[T]) Store(value T) {
*(*T)(p.base) = value
}
func (p Pointer[T]) Nth(index int) T {
return p.Add(uintptr(index) * mem.SizeOf[T]()).Load()
}