87 lines
1.6 KiB
Go
87 lines
1.6 KiB
Go
package pointer
|
|
|
|
import (
|
|
"runtime"
|
|
"unsafe"
|
|
|
|
"git.brut.systems/judah/xx/mem"
|
|
)
|
|
|
|
type Pinned[T any] struct {
|
|
base unsafe.Pointer
|
|
pinner runtime.Pinner
|
|
}
|
|
|
|
func Pin[T any](ptr *T) (r Pinned[T]) {
|
|
r.pinner.Pin(ptr)
|
|
r.base = unsafe.Pointer(ptr)
|
|
return
|
|
}
|
|
|
|
func Cast[TOut, TIn any](p Pinned[TIn]) Pinned[TOut] {
|
|
return Pinned[TOut]{
|
|
base: unsafe.Pointer(p.base),
|
|
pinner: p.pinner,
|
|
}
|
|
}
|
|
|
|
func (p Pinned[T]) Unpin() {
|
|
p.pinner.Unpin()
|
|
p.base = nil
|
|
}
|
|
|
|
func (p Pinned[T]) Pointer() unsafe.Pointer {
|
|
return p.base
|
|
}
|
|
|
|
func (p Pinned[T]) Address() uintptr {
|
|
return uintptr(p.base)
|
|
}
|
|
|
|
func (p Pinned[T]) Nil() bool {
|
|
return p.base == nil
|
|
}
|
|
|
|
func (p Pinned[T]) Add(amount uintptr) Pinned[T] {
|
|
return Pinned[T]{
|
|
base: unsafe.Pointer(uintptr(p.base) + amount),
|
|
pinner: p.pinner,
|
|
}
|
|
}
|
|
|
|
func (p Pinned[T]) Sub(amount uintptr) Pinned[T] {
|
|
return Pinned[T]{
|
|
base: unsafe.Pointer(uintptr(p.base) - amount),
|
|
pinner: p.pinner,
|
|
}
|
|
}
|
|
|
|
func (p Pinned[T]) Aligned() bool {
|
|
return mem.Aligned(uintptr(p.base), mem.AlignOf[T]())
|
|
}
|
|
|
|
func (p Pinned[T]) AlignForward() Pinned[T] {
|
|
return Pinned[T]{
|
|
base: unsafe.Pointer(mem.AlignForward(uintptr(p.base), mem.AlignOf[T]())),
|
|
pinner: p.pinner,
|
|
}
|
|
}
|
|
|
|
func (p Pinned[T]) AlignBackward() Pinned[T] {
|
|
return Pinned[T]{
|
|
base: unsafe.Pointer(mem.AlignBackward(uintptr(p.base), mem.AlignOf[T]())),
|
|
pinner: p.pinner,
|
|
}
|
|
}
|
|
|
|
func (p Pinned[T]) Load() T {
|
|
return *(*T)(p.base)
|
|
}
|
|
|
|
func (p Pinned[T]) Store(value T) {
|
|
*(*T)(p.base) = value
|
|
}
|
|
|
|
func (p Pinned[T]) Nth(index int) T {
|
|
return p.Add(uintptr(index) * mem.SizeOf[T]()).Load()
|
|
}
|