StableVector repetition fix.

This commit is contained in:
Metehan Tuncbilek
2024-10-09 20:17:21 +03:00
parent 0e34b90f67
commit 89ce60f869
2 changed files with 59 additions and 139 deletions

View File

@@ -14,7 +14,7 @@
namespace OpenVulkano
{
template<typename K, typename V, template<typename, typename> class Pair = std::pair,
template<typename> class Vec = std::vector, typename = std::enable_if_t<std::is_integral<K>::value>>
template<typename...> class Vec = std::vector, typename = std::enable_if_t<std::is_integral<K>::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];
}

View File

@@ -30,7 +30,7 @@ namespace OpenVulkano
*
* @throw Please know that this vector creates array gaps when you remove an element.
*/
template<typename T, size_t GROW_FACTOR = 2, size_t DEFAULT_CHUNK_SIZE = 32> class StableVector
template<typename T> 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 (&currentChunk->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 (&currentChunk->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<typename... Args> 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>(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>(args)...);
}
// Checks the first available gap and inserts. If no gap it works like emplace_back(Args&&... args)
template<typename... Args> 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 (&currentChunk->m_data[i]) T(std::forward<Args>(args)...);
currentChunk->m_occupiedIndices[i] = true;
currentChunk->m_size++;
currentChunk->m_gapCount--;
m_size++;
return;
}
}
}
currentChunk = currentChunk->m_next;
}
EmplaceBack(std::forward<Args>(args)...);
}
void Push(const T& value) { new (Insert()) T(value); }
void Push(T&& value) noexcept { new (Insert()) T(std::move(value)); }
template<typename... Args> void Emplace(Args&&... args) { new (Insert()) T(std::forward<Args>(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 = &currentChunk->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;
};
}