This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 52e43fe9 fix(memory): keep allocator ownership across Buffer.Reset
(#947)
52e43fe9 is described below
commit 52e43fe9b555061218fa58d890711bf0ed46fe76
Author: Minh Vu <[email protected]>
AuthorDate: Wed Jul 15 17:59:55 2026 +0200
fix(memory): keep allocator ownership across Buffer.Reset (#947)
---
arrow/memory/buffer.go | 15 +++++++++++++-
arrow/memory/buffer_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/arrow/memory/buffer.go b/arrow/memory/buffer.go
index 592da70c..8893d1b5 100644
--- a/arrow/memory/buffer.go
+++ b/arrow/memory/buffer.go
@@ -95,12 +95,25 @@ func (b *Buffer) Release() {
}
}
-// Reset resets the buffer for reuse.
+// Reset resets the buffer for reuse. If the buffer owns memory through an
+// allocator, the supplied data is copied into allocator-owned storage.
func (b *Buffer) Reset(buf []byte) {
if b.parent != nil {
b.parent.Release()
b.parent = nil
}
+
+ if b.mem != nil {
+ if len(buf) <= len(b.buf) {
+ copy(b.buf, buf)
+ b.Resize(len(buf))
+ return
+ }
+ b.Resize(len(buf))
+ copy(b.buf, buf)
+ return
+ }
+
b.buf = buf
b.length = len(buf)
}
diff --git a/arrow/memory/buffer_test.go b/arrow/memory/buffer_test.go
index f8dccf0b..549d57c4 100644
--- a/arrow/memory/buffer_test.go
+++ b/arrow/memory/buffer_test.go
@@ -17,12 +17,26 @@
package memory_test
import (
+ "bytes"
"testing"
"github.com/apache/arrow-go/v18/arrow/memory"
"github.com/stretchr/testify/assert"
)
+type movingAllocator struct{}
+
+func (*movingAllocator) Allocate(size int) []byte { return make([]byte, size) }
+
+func (*movingAllocator) Reallocate(size int, old []byte) []byte {
+ next := make([]byte, size)
+ copy(next, old)
+ clear(old)
+ return next
+}
+
+func (*movingAllocator) Free([]byte) {}
+
func TestNewResizableBuffer(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
@@ -49,11 +63,31 @@ func TestBufferReset(t *testing.T) {
defer mem.AssertSize(t, 0)
buf := memory.NewResizableBuffer(mem)
+ buf.Resize(64)
newBytes := []byte("some-new-bytes")
buf.Reset(newBytes)
assert.Equal(t, newBytes, buf.Bytes())
assert.Equal(t, len(newBytes), buf.Len())
+ assert.Equal(t, 64, mem.CurrentAlloc())
+
+ newBytes[0] = 'S'
+ assert.Equal(t, byte('s'), buf.Bytes()[0])
+
+ grownBytes := bytes.Repeat([]byte("g"), 96)
+ buf.Reset(grownBytes)
+ assert.Equal(t, grownBytes, buf.Bytes())
+ assert.Equal(t, 96, buf.Len())
+ assert.Equal(t, 128, mem.CurrentAlloc())
+
+ grownBytes[0] = 'G'
+ assert.Equal(t, byte('g'), buf.Bytes()[0])
+
+ buf.Reset(nil)
+ assert.Empty(t, buf.Bytes())
+ assert.Zero(t, mem.CurrentAlloc())
+
+ buf.Release()
}
func TestBufferSlice(t *testing.T) {
@@ -69,3 +103,18 @@ func TestBufferSlice(t *testing.T) {
assert.Equal(t, 1024, mem.CurrentAlloc())
slice.Release()
}
+
+func TestBufferResetFromOwnedSlice(t *testing.T) {
+ mem := memory.NewCheckedAllocator(&movingAllocator{})
+ defer mem.AssertSize(t, 0)
+
+ buf := memory.NewResizableBuffer(mem)
+ buf.Resize(128)
+ copy(buf.Bytes(), bytes.Repeat([]byte("0123456789abcdef"), 8))
+
+ want := bytes.Clone(buf.Bytes()[32:64])
+ buf.Reset(buf.Bytes()[32:64])
+ assert.Equal(t, want, buf.Bytes())
+
+ buf.Release()
+}