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() }