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.