Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cow_edgecases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,28 @@ func TestCOWAndNotResultReusedByXor(t *testing.T) {
require.True(t, c.Equals(BitmapOf(939524096, 939524097, 939524098, 939524099)))
require.NoError(t, c.Validate())
}

// Clear resets the bitmap to a new one, so copy-on-write is turned off.
// Xor and AndNot of a bitmap with itself also empty it, but keep the setting.
func TestClearResetsCopyOnWrite(t *testing.T) {
rb := BitmapOf(1, 2, 3)
rb.SetCopyOnWrite(true)
rb.Clear()
require.False(t, rb.GetCopyOnWrite())
rb.Add(4)
require.NoError(t, rb.Validate())

for _, op := range []func(*Bitmap){
func(b *Bitmap) { b.Xor(b) },
func(b *Bitmap) { b.AndNot(b) },
} {
b := BitmapOf(1, 2, 3, 100000)
b.SetCopyOnWrite(true)
op(b)
require.True(t, b.IsEmpty())
require.True(t, b.GetCopyOnWrite())
b.Add(5)
require.NoError(t, b.Validate())
require.True(t, b.Contains(5))
}
}
13 changes: 10 additions & 3 deletions roaring.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,12 @@ func New() *Bitmap {
}

// Clear resets the Bitmap to be logically empty, but may retain
// some memory allocations that may speed up future operations
// some memory allocations that may speed up future operations.
//
// Clear also turns copy-on-write off: after Clear, the bitmap behaves like
// a new Bitmap and GetCopyOnWrite returns false, whether copy-on-write was
// enabled with SetCopyOnWrite or set internally by FromBuffer. Call
// SetCopyOnWrite(true) after Clear to keep using copy-on-write.
func (rb *Bitmap) Clear() {
rb.highlowcontainer.clear()
}
Expand Down Expand Up @@ -1608,7 +1613,8 @@ main:
// Xor computes the symmetric difference between two bitmaps and stores the result in the current bitmap
func (rb *Bitmap) Xor(x2 *Bitmap) {
if rb == x2 {
rb.Clear()
// the result is empty; keep the copy-on-write setting, unlike Clear
rb.highlowcontainer.resize(0)
return
}
pos1 := 0
Expand Down Expand Up @@ -1702,7 +1708,8 @@ main:
// AndNot computes the difference between two bitmaps and stores the result in the current bitmap
func (rb *Bitmap) AndNot(x2 *Bitmap) {
if rb == x2 {
rb.Clear()
// the result is empty; keep the copy-on-write setting, unlike Clear
rb.highlowcontainer.resize(0)
return
}
pos1 := 0
Expand Down
6 changes: 5 additions & 1 deletion roaring64/roaring64.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,11 @@ func New() *Bitmap {
}

// Clear resets the Bitmap to be logically empty, but may retain
// some memory allocations that may speed up future operations
// some memory allocations that may speed up future operations.
//
// Clear also turns copy-on-write off: after Clear, the bitmap behaves like
// a new Bitmap and GetCopyOnWrite returns false. Call SetCopyOnWrite(true)
// after Clear to keep using copy-on-write.
func (rb *Bitmap) Clear() {
rb.highlowcontainer.clear()
}
Expand Down
21 changes: 21 additions & 0 deletions roaring64/roaring64cow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1797,3 +1797,24 @@ func TestOrCOWSharedContainer(t *testing.T) {
assert.False(t, rb2.Contains(1500),
"rb2 was corrupted: contains a value that was only added to rb1")
}

// Clear resets the bitmap to a new one, so copy-on-write is turned off.
func TestClearResetsCopyOnWrite64(t *testing.T) {
rb := BitmapOf(1, 2, 3, 1<<40)
rb.SetCopyOnWrite(true)
rb.Clear()
assert.False(t, rb.GetCopyOnWrite())
rb.Add(4)
assert.NoError(t, rb.Validate())

for _, op := range []func(*Bitmap){
func(b *Bitmap) { b.Xor(b) },
func(b *Bitmap) { b.AndNot(b) },
} {
b := BitmapOf(1, 2, 3, 1<<40)
b.SetCopyOnWrite(true)
op(b)
assert.True(t, b.IsEmpty())
assert.True(t, b.GetCopyOnWrite())
}
}
Loading