Fix BitArray swap when using different allocators

Add unit test to ensure this works correctly.
This commit is contained in:
Wojtek Figat
2024-11-19 12:21:13 +01:00
parent 36cf859741
commit a7daf44330
2 changed files with 92 additions and 11 deletions

View File

@@ -90,12 +90,10 @@ public:
/// </summary>
/// <param name="other">The other collection to move.</param>
FORCE_INLINE BitArray(BitArray&& other) noexcept
: _count(0)
, _capacity(0)
{
_count = other._count;
_capacity = other._capacity;
other._count = 0;
other._capacity = 0;
_allocation.Swap(other._allocation);
Swap(other);
}
/// <summary>
@@ -130,11 +128,9 @@ public:
if (this != &other)
{
_allocation.Free();
_count = other._count;
_capacity = other._capacity;
other._count = 0;
other._capacity = 0;
_allocation.Swap(other._allocation);
_count = 0;
_capacity = 0;
Swap(other);
}
return *this;
}
@@ -337,9 +333,38 @@ public:
/// <param name="other">The other collection.</param>
void Swap(BitArray& other)
{
if IF_CONSTEXPR (AllocationType::HasSwap)
_allocation.Swap(other._allocation);
else
{
// Move to temp
const int32 oldItemsCapacity = ToItemCount(_capacity);
const int32 otherItemsCapacity = ToItemCount(other._capacity);
AllocationData oldAllocation;
if (oldItemsCapacity)
{
oldAllocation.Allocate(oldItemsCapacity);
Memory::MoveItems(oldAllocation.Get(), _allocation.Get(), oldItemsCapacity);
_allocation.Free();
}
// Move other to source
if (otherItemsCapacity)
{
_allocation.Allocate(otherItemsCapacity);
Memory::MoveItems(_allocation.Get(), other._allocation.Get(), otherItemsCapacity);
other._allocation.Free();
}
// Move temp to other
if (oldItemsCapacity)
{
other._allocation.Allocate(oldItemsCapacity);
Memory::MoveItems(other._allocation.Get(), oldAllocation.Get(), oldItemsCapacity);
}
}
::Swap(_count, other._count);
::Swap(_capacity, other._capacity);
_allocation.Swap(other._allocation);
}
public:

View File

@@ -7,6 +7,24 @@
#include "Engine/Core/Collections/Dictionary.h"
#include <ThirdParty/catch2/catch.hpp>
const bool TestBits[] = { true, false, true, false };
template<typename AllocationType = HeapAllocation>
void InitBitArray(BitArray<AllocationType>& array)
{
array.Add(TestBits, ARRAY_COUNT(TestBits));
}
template<typename AllocationType = HeapAllocation>
void CheckBitArray(const BitArray<AllocationType>& array)
{
CHECK(array.Count() == ARRAY_COUNT(TestBits));
for (int32 i = 0; i < ARRAY_COUNT(TestBits); i++)
{
CHECK(array[i] == TestBits[i]);
}
}
TEST_CASE("Array")
{
SECTION("Test Allocators")
@@ -84,6 +102,44 @@ TEST_CASE("BitArray")
}
}
SECTION("Test Move/Copy")
{
BitArray<> array1;
BitArray<FixedAllocation<4>> array2;
BitArray<InlinedAllocation<4>> array3;
BitArray<InlinedAllocation<2>> array4;
InitBitArray(array1);
InitBitArray(array2);
InitBitArray(array3);
InitBitArray(array4);
CheckBitArray(array1);
CheckBitArray(array2);
CheckBitArray(array3);
CheckBitArray(array4);
BitArray<> arrayClone1 = array1;
BitArray<FixedAllocation<4>> arrayClone2(array1);
BitArray<FixedAllocation<4>> arrayClone3(MoveTemp(array1));
BitArray<> arrayClone4(MoveTemp(array1));
BitArray<FixedAllocation<4>> arrayClone5 = MoveTemp(array2);
BitArray<InlinedAllocation<4>> arrayClone6 = MoveTemp(array3);
BitArray<InlinedAllocation<2>> arrayClone7 = MoveTemp(array4);
CheckBitArray(arrayClone1);
CheckBitArray(arrayClone2);
CheckBitArray(arrayClone4);
CheckBitArray(arrayClone5);
CheckBitArray(arrayClone6);
CheckBitArray(arrayClone7);
CHECK(array1.Count() == 0);
CHECK(array2.Count() == 0);
CHECK(array3.Count() == 0);
CHECK(array4.Count() == 0);
}
// Generate some random data for testing
BitArray<> testData;
testData.Resize(32);