From 89ce60f86938a74c87c3aeca34db212f3d02c77f Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Wed, 9 Oct 2024 20:17:21 +0300 Subject: [PATCH] StableVector repetition fix. --- .../Data/Containers/BinSearchArrayMap.hpp | 4 +- .../Data/Containers/StableVector.hpp | 194 +++++------------- 2 files changed, 59 insertions(+), 139 deletions(-) diff --git a/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp index d6ff994..1439fc2 100644 --- a/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp +++ b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp @@ -14,7 +14,7 @@ namespace OpenVulkano { template class Pair = std::pair, - template class Vec = std::vector, typename = std::enable_if_t::value>> + template class Vec = std::vector, typename = std::enable_if_t::value>> class BinSearchArrayMap { public: @@ -59,7 +59,7 @@ namespace OpenVulkano std::streamsize index = FindIndexInVector(key); if (index < 0) { - std::runtime_error("Key not found"); + throw std::runtime_error("Key not found"); } return m_data[index]; } diff --git a/openVulkanoCpp/Data/Containers/StableVector.hpp b/openVulkanoCpp/Data/Containers/StableVector.hpp index 0957deb..77662a8 100644 --- a/openVulkanoCpp/Data/Containers/StableVector.hpp +++ b/openVulkanoCpp/Data/Containers/StableVector.hpp @@ -30,7 +30,7 @@ namespace OpenVulkano * * @throw Please know that this vector creates array gaps when you remove an element. */ - template class StableVector + template class StableVector { struct VectorChunk { @@ -174,10 +174,7 @@ namespace OpenVulkano return m_chunk == other.m_chunk && m_index == other.m_index; } - bool operator!=(const Iterator& other) const - { - return m_chunk != other.m_chunk || m_index != other.m_index; - } + bool operator!=(const Iterator& other) const { return !(*this == other); } std::streamsize GetIndex() const { return m_chunk->GetRealIndex(m_index); } VectorChunk* GetChunk() const { return m_chunk; } @@ -285,143 +282,17 @@ namespace OpenVulkano } } - void PushBack(const T& value) - { - if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity) - { - VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR); - m_capacity += m_lastChunk->m_capacity * GROW_FACTOR; - m_lastChunk->m_next = newChunk; - newChunk->m_prev = m_lastChunk; - m_lastChunk = newChunk; - } - - new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(value); - m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true; - m_lastChunk->m_nextIndex++; - m_lastChunk->m_size++; - m_size++; - } - - void PushBack(T&& value) noexcept - { - if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity) - { - VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR); - m_capacity += m_lastChunk->m_capacity * GROW_FACTOR; - m_lastChunk->m_next = newChunk; - newChunk->m_prev = m_lastChunk; - m_lastChunk = newChunk; - } - - new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(std::move(value)); - m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true; - m_lastChunk->m_nextIndex++; - m_lastChunk->m_size++; - m_size++; - } - - // Checks the first available gap and inserts. If no gap it works like push_back(const T& value) - void Push(const T& value) - { - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap - { - for (size_t i = 0; i < currentChunk->m_capacity; i++) - { - if (!currentChunk->m_occupiedIndices[i]) - { - new (¤tChunk->m_data[i]) T(value); - currentChunk->m_occupiedIndices[i] = true; - currentChunk->m_size++; - currentChunk->m_gapCount--; - m_size++; - return; - } - } - } - - currentChunk = currentChunk->m_next; - } - - PushBack(value); - } - - // Checks the first available gap and inserts. If no gap it works like push_back(T&& value) - void Push(T&& value) noexcept - { - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap - { - for (size_t i = 0; i < currentChunk->m_capacity; i++) - { - if (!currentChunk->m_occupiedIndices[i]) - { - new (¤tChunk->m_data[i]) T(std::move(value)); - currentChunk->m_occupiedIndices[i] = true; - currentChunk->m_size++; - currentChunk->m_gapCount--; - m_size++; - return; - } - } - } - - currentChunk = currentChunk->m_next; - } - - PushBack(std::move(value)); - } + void PushBack(const T& value) { new (InsertBack()) T(value); } + void PushBack(T&& value) noexcept { new (InsertBack()) T(std::move(value)); } template void EmplaceBack(Args&&... args) { - if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity) - { - VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR); - m_capacity += m_lastChunk->m_capacity * GROW_FACTOR; - m_lastChunk->m_next = newChunk; - newChunk->m_prev = m_lastChunk; - m_lastChunk = newChunk; - } - - new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(std::forward(args)...); - m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true; - m_lastChunk->m_nextIndex++; - m_lastChunk->m_size++; - m_size++; + new (InsertBack()) T(std::forward(args)...); } - // Checks the first available gap and inserts. If no gap it works like emplace_back(Args&&... args) - template void Emplace(Args&&... args) - { - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap - { - for (size_t i = 0; i < currentChunk->m_capacity; i++) - { - if (!currentChunk->m_occupiedIndices[i]) - { - new (¤tChunk->m_data[i]) T(std::forward(args)...); - currentChunk->m_occupiedIndices[i] = true; - currentChunk->m_size++; - currentChunk->m_gapCount--; - m_size++; - return; - } - } - } - - currentChunk = currentChunk->m_next; - } - - EmplaceBack(std::forward(args)...); - } + void Push(const T& value) { new (Insert()) T(value); } + void Push(T&& value) noexcept { new (Insert()) T(std::move(value)); } + template void Emplace(Args&&... args) { new (Insert()) T(std::forward(args)...); } void PopBack() { @@ -580,11 +451,60 @@ namespace OpenVulkano throw std::out_of_range("Index out of range"); } + T* InsertBack() + { + if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity) + { + VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR); + m_capacity += m_lastChunk->m_capacity * GROW_FACTOR; + m_lastChunk->m_next = newChunk; + newChunk->m_prev = m_lastChunk; + m_lastChunk = newChunk; + } + + m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true; + m_lastChunk->m_size++; + m_lastChunk->m_gapCount++; + m_size++; + return &m_lastChunk->m_data[m_lastChunk->m_nextIndex++]; + } + + T* Insert() + { + T* target = nullptr; + VectorChunk* currentChunk = m_firstChunk; + while (currentChunk) + { + if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap + { + for (size_t i = 0; i < currentChunk->m_capacity; i++) + { + if (!currentChunk->m_occupiedIndices[i]) + { + target = ¤tChunk->m_data[i]; + currentChunk->m_occupiedIndices[i] = true; + currentChunk->m_size++; + currentChunk->m_gapCount--; + m_size++; + return target; + } + } + } + + currentChunk = currentChunk->m_next; + } + + return InsertBack(); + } + private: VectorChunk* m_firstChunk; VectorChunk* m_lastChunk; size_t m_size; size_t m_capacity; + + static inline constexpr size_t DEFAULT_CHUNK_SIZE = 32; + static inline constexpr size_t GROW_FACTOR = 2; }; }