From 430dea5b7f70296289e57b8f5ea966b601645b7f Mon Sep 17 00:00:00 2001 From: Sven Anderson Date: Sat, 16 Jan 2021 21:07:12 +0100 Subject: [PATCH] cutil: add SyncBuffer abstraction layer to PtrGuard In order to be able to swich on and off PtrGuard usage, SyncBuffer implements a typical usage pattern of PtrGuard, that is a data buffer referenced from inside a C allocated struct, in two ways: 1) using a PtrGuard to dierctly store a pointer to the Go buffer in C memory, or 2) allocating a C buffer of same size and syncing data back with C.memcpy(). The implementation can be chosen with the with_ptrguard build tag. Signed-off-by: Sven Anderson --- internal/cutil/sync_buffer.go | 28 +++++++++++++++++++++ internal/cutil/sync_buffer_memcpy.go | 37 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 internal/cutil/sync_buffer.go create mode 100644 internal/cutil/sync_buffer_memcpy.go diff --git a/internal/cutil/sync_buffer.go b/internal/cutil/sync_buffer.go new file mode 100644 index 0000000..9fdc38e --- /dev/null +++ b/internal/cutil/sync_buffer.go @@ -0,0 +1,28 @@ +// +build ptrguard + +package cutil + +import ( + "unsafe" +) + +// SyncBuffer is a C buffer connected to a data slice +type SyncBuffer struct { + pg *PtrGuard +} + +// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr +func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer { + var v SyncBuffer + v.pg = NewPtrGuard(cPtr, unsafe.Pointer(&data[0])) + return &v +} + +// Release releases the C buffer and nulls its stored pointer +func (v *SyncBuffer) Release() { + v.pg.Release() +} + +// Sync asserts that changes in the C buffer are available in the data +// slice +func (v *SyncBuffer) Sync() {} diff --git a/internal/cutil/sync_buffer_memcpy.go b/internal/cutil/sync_buffer_memcpy.go new file mode 100644 index 0000000..137ae62 --- /dev/null +++ b/internal/cutil/sync_buffer_memcpy.go @@ -0,0 +1,37 @@ +// +build !ptrguard + +package cutil + +// SyncBuffer is a C buffer connected to a data slice +type SyncBuffer struct { + data []byte + cPtr *CPtr +} + +// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr +func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer { + var v SyncBuffer + v.data = data + v.cPtr = (*CPtr)(cPtr) + *v.cPtr = CBytes(data) + return &v +} + +// Release releases the C buffer and nulls its stored pointer +func (v *SyncBuffer) Release() { + if v.cPtr != nil { + Free(*v.cPtr) + *v.cPtr = nil + v.cPtr = nil + } + v.data = nil +} + +// Sync asserts that changes in the C buffer are available in the data +// slice +func (v *SyncBuffer) Sync() { + if v.cPtr == nil { + return + } + Memcpy(CPtr(&v.data[0]), CPtr(*v.cPtr), SizeT(len(v.data))) +}