Documentation
¶
Overview ¶
Package ptrguard allows to pin a Go object (in memory allocated by the Go runtime), so that it will not be touched by the garbage collector until it is unpinned again.
Example (CAllocatedIovec) ¶
Example how to use PtrGuard with a C allocated iovec array.
package main
import (
"fmt"
"math"
"github.com/ansiwen/ptrguard"
C "github.com/ansiwen/ptrguard/internal/testhelper"
)
func main() {
var buffers [][]byte
for i := 2; i < 12; i += 3 {
buffers = append(buffers, make([]byte, i))
}
numberOfBuffers := len(buffers)
cPtr := C.Malloc(C.SizeOfIovec * uintptr(len(buffers)))
defer C.Free(cPtr)
// This is a trick to create a slice on top of the C allocated array, for
// easier and safer access.
iovec := (*[math.MaxInt32]C.Iovec)(cPtr)[:numberOfBuffers:numberOfBuffers]
var pinner ptrguard.Pinner
defer pinner.Unpin()
for i := range iovec {
bufferPtr := &buffers[i][0]
pinner.Pin(bufferPtr).Store(&iovec[i].Base)
iovec[i].Len = C.Int(len(buffers[i]))
}
C.FillBuffersWithX(&iovec[0], len(iovec))
for i := range buffers {
fmt.Println(string(buffers[i]))
}
}
Output: XX XXXXX XXXXXXXX XXXXXXXXXXX
Example (GoAllocatedIovec) ¶
Example how to use PtrGuard with a Go allocated iovec slice.
package main
import (
"fmt"
"unsafe"
"github.com/ansiwen/ptrguard"
C "github.com/ansiwen/ptrguard/internal/testhelper"
)
func main() {
var buffers [][]byte
for i := 2; i < 12; i += 3 {
buffers = append(buffers, make([]byte, i))
}
iovec := make([]C.Iovec, len(buffers))
var pinner ptrguard.Pinner
defer pinner.Unpin()
for i := range iovec {
bufferPtr := &buffers[i][0]
pinner.Pin(bufferPtr)
iovec[i].Base = unsafe.Pointer(bufferPtr)
iovec[i].Len = C.Int(len(buffers[i]))
}
ptrguard.NoCheck(func() {
C.FillBuffersWithX(&iovec[0], len(iovec))
})
for i := range buffers {
fmt.Println(string(buffers[i]))
}
}
Output: XX XXXXX XXXXXXXX XXXXXXXXXXX
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NoCheck ¶
func NoCheck(f func())
NoCheck temporarily disables cgocheck, which allows passing Go memory containing pinned Go pointers to a C function. Since this is a global setting, and if you are making C calls in parallel, theoretically it could happen that cgocheck is also disabled for some other C calls. If this is an issue, it is also possible to shadow the cgocheck call instead with this code line
_cgoCheckPointer := func(interface{}, interface{}) {}
right before the C function call.
Types ¶
type Pinned ¶ added in v0.4.0
type Pinned struct {
// contains filtered or unexported fields
}
Pinned pointer that can be stored with the Store() method.
type Pinner ¶
type Pinner struct {
// contains filtered or unexported fields
}
Pinner can pin Go objects (in memory allocated by Go runtime) with the Pin() method. A pinned pointer to these objects can be stored in C memory (allocated by malloc) with the `Store()` method. All pinned objects of a Pinner can be unpinned with the `Unpin()` method.
func (*Pinner) Pin ¶ added in v0.4.0
Pin the Go object referenced by pointer and return a Pinned value. The pointer must be a pointer of any type or unsafe.Pointer, otherwise Pin() will panic. The object will not be touched by the garbage collector until the `Unpin()` method is called. Therefore pinned pointers to this object can be directly stored in C memory with the `Store()` method or can be contained in Go memory passed to C functions, which usually violates the pointer passing rules[1].
func (*Pinner) Unpin ¶ added in v0.4.0
func (p *Pinner) Unpin()
Unpin all pinned objects of the Pinner and zero all memory where the pointer has been stored. Whenever Pin() has been called at least once on a Pinner, Unpin() must be called afterwards on the same Pinner, or the garbage collector thread will panic.