83 lines
1.5 KiB
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()
|
|
}
|