diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 1b601c72f..0a748f4bd 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -90,12 +90,10 @@ public: /// /// The other collection to move. 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); } /// @@ -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: /// The other collection. 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: diff --git a/Source/Engine/Tests/TestCollections.cpp b/Source/Engine/Tests/TestCollections.cpp index c54e98c15..f9b0e47ca 100644 --- a/Source/Engine/Tests/TestCollections.cpp +++ b/Source/Engine/Tests/TestCollections.cpp @@ -7,6 +7,24 @@ #include "Engine/Core/Collections/Dictionary.h" #include +const bool TestBits[] = { true, false, true, false }; + +template +void InitBitArray(BitArray& array) +{ + array.Add(TestBits, ARRAY_COUNT(TestBits)); +} + +template +void CheckBitArray(const BitArray& 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> array2; + BitArray> array3; + BitArray> array4; + + InitBitArray(array1); + InitBitArray(array2); + InitBitArray(array3); + InitBitArray(array4); + + CheckBitArray(array1); + CheckBitArray(array2); + CheckBitArray(array3); + CheckBitArray(array4); + + BitArray<> arrayClone1 = array1; + BitArray> arrayClone2(array1); + BitArray> arrayClone3(MoveTemp(array1)); + BitArray<> arrayClone4(MoveTemp(array1)); + BitArray> arrayClone5 = MoveTemp(array2); + BitArray> arrayClone6 = MoveTemp(array3); + BitArray> 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);