StableVector review fix. No working iterators.

This commit is contained in:
Metehan Tuncbilek
2024-10-08 11:15:31 +03:00
parent 7b40d001ec
commit 6f981682f8
2 changed files with 173 additions and 186 deletions

View File

@@ -191,7 +191,7 @@ namespace OpenVulkano
protected: protected:
void MoveToNextChunk() void MoveToNextChunk()
{ {
while (m_chunk && (m_index > m_chunk->m_size || !m_chunk->m_occupiedIndices[m_index])) while (m_chunk && !m_chunk->m_occupiedIndices[m_index])
{ {
if (m_index >= m_chunk->m_size) if (m_index >= m_chunk->m_size)
{ {
@@ -204,11 +204,10 @@ namespace OpenVulkano
} }
} }
if (m_chunk && m_index >= m_chunk->m_size) if (m_chunk && m_index > m_chunk->m_size)
{ {
m_chunk = m_chunk->m_next; m_chunk = m_chunk->m_next;
m_index = 0; m_index = 0;
MoveToNextChunk();
} }
} }
@@ -220,26 +219,26 @@ namespace OpenVulkano
}; };
public: public:
StableVector() : m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) StableVector() : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = Grow(DEFAULT_CHUNK_SIZE); m_firstChunk = Grow(DEFAULT_CHUNK_SIZE);
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = DEFAULT_CHUNK_SIZE; m_capacity = DEFAULT_CHUNK_SIZE;
} }
StableVector(size_t size) : m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) StableVector(size_t size) : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = Grow(size); m_firstChunk = Grow(size);
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = size; m_capacity = size;
} }
StableVector(size_t size, const T& value) StableVector(size_t size, const T& value)
: m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = Grow(size); m_firstChunk = Grow(size);
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = size; m_capacity = size;
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
{ {
@@ -248,11 +247,11 @@ namespace OpenVulkano
} }
StableVector(std::initializer_list<T> list) StableVector(std::initializer_list<T> list)
: m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = Grow(list.size()); m_firstChunk = Grow(list.size());
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = list.size(); m_capacity = list.size();
for (const T& value: list) for (const T& value: list)
{ {
@@ -261,11 +260,11 @@ namespace OpenVulkano
} }
StableVector(const StableVector<T>& copy) StableVector(const StableVector<T>& copy)
: m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = Grow(copy.m_Capacity); // One big chunk to make Stable contiguous. m_firstChunk = Grow(copy.m_capacity); // One big chunk to make Stable contiguous.
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = copy.m_Capacity; m_capacity = copy.m_capacity;
for (size_t i = 0; i < copy.Size(); i++) for (size_t i = 0; i < copy.Size(); i++)
{ {
@@ -274,22 +273,22 @@ namespace OpenVulkano
} }
StableVector(StableVector<T>&& move) noexcept StableVector(StableVector<T>&& move) noexcept
: m_FirstChunk(nullptr), m_LastChunk(nullptr), m_Size(0), m_Capacity(0) : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0)
{ {
m_FirstChunk = move.m_FirstChunk; m_firstChunk = move.m_firstChunk;
m_LastChunk = move.m_LastChunk; m_lastChunk = move.m_lastChunk;
m_Size = move.m_Size; m_size = move.m_size;
m_Capacity = move.m_Capacity; m_capacity = move.m_capacity;
move.m_FirstChunk = nullptr; move.m_firstChunk = nullptr;
move.m_LastChunk = nullptr; move.m_lastChunk = nullptr;
move.m_Size = 0; move.m_size = 0;
move.m_Capacity = 0; move.m_capacity = 0;
} }
~StableVector() ~StableVector()
{ {
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
VectorChunk* temp = currentChunk; VectorChunk* temp = currentChunk;
@@ -300,50 +299,44 @@ namespace OpenVulkano
void PushBack(const T& value) void PushBack(const T& value)
{ {
if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
{ {
VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
m_LastChunk->m_next = newChunk; m_lastChunk->m_next = newChunk;
newChunk->m_prev = m_LastChunk; newChunk->m_prev = m_lastChunk;
m_LastChunk = newChunk; m_lastChunk = newChunk;
} }
new (&m_LastChunk->m_data[m_LastChunk->m_nextIndex]) T(value); new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(value);
m_LastChunk->m_occupiedIndices[m_LastChunk->m_nextIndex] = true; m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true;
m_LastChunk->m_nextIndex++; m_lastChunk->m_nextIndex++;
m_LastChunk->m_size++; m_lastChunk->m_size++;
m_Size++; m_size++;
} }
/// std version of push_back(const T& value)
void push_back(const T& value) { PushBack(value); }
void PushBack(T&& value) noexcept void PushBack(T&& value) noexcept
{ {
if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
{ {
VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
m_LastChunk->m_next = newChunk; m_lastChunk->m_next = newChunk;
newChunk->m_prev = m_LastChunk; newChunk->m_prev = m_lastChunk;
m_LastChunk = newChunk; m_lastChunk = newChunk;
} }
new (&m_LastChunk->m_data[m_LastChunk->m_nextIndex]) T(std::move(value)); 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_occupiedIndices[m_lastChunk->m_nextIndex] = true;
m_LastChunk->m_nextIndex++; m_lastChunk->m_nextIndex++;
m_LastChunk->m_size++; m_lastChunk->m_size++;
m_Size++; m_size++;
} }
/// std version of push_back(T&& value)
void push_back(T&& value) { PushBack(value); }
// Checks the first available gap and inserts. If no gap it works like push_back(const T& value) // Checks the first available gap and inserts. If no gap it works like push_back(const T& value)
void Push(const T& value) void Push(const T& value)
{ {
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
@@ -356,7 +349,7 @@ namespace OpenVulkano
currentChunk->m_occupiedIndices[i] = true; currentChunk->m_occupiedIndices[i] = true;
currentChunk->m_size++; currentChunk->m_size++;
currentChunk->m_gapCount--; currentChunk->m_gapCount--;
m_Size++; m_size++;
return; return;
} }
} }
@@ -369,7 +362,7 @@ namespace OpenVulkano
// Checks the first available gap and inserts. If no gap it works like push_back(T&& value) // Checks the first available gap and inserts. If no gap it works like push_back(T&& value)
void Push(T&& value) noexcept void Push(T&& value) noexcept
{ {
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
@@ -382,7 +375,7 @@ namespace OpenVulkano
currentChunk->m_occupiedIndices[i] = true; currentChunk->m_occupiedIndices[i] = true;
currentChunk->m_size++; currentChunk->m_size++;
currentChunk->m_gapCount--; currentChunk->m_gapCount--;
m_Size++; m_size++;
return; return;
} }
} }
@@ -396,29 +389,26 @@ namespace OpenVulkano
template<typename... Args> void EmplaceBack(Args&&... args) template<typename... Args> void EmplaceBack(Args&&... args)
{ {
if (m_LastChunk->m_nextIndex == m_LastChunk->m_capacity) if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
{ {
VectorChunk* newChunk = Grow(m_LastChunk->m_capacity * GROW_FACTOR); VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
m_Capacity += m_LastChunk->m_capacity * GROW_FACTOR; m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
m_LastChunk->m_next = newChunk; m_lastChunk->m_next = newChunk;
newChunk->m_prev = m_LastChunk; newChunk->m_prev = m_lastChunk;
m_LastChunk = newChunk; m_lastChunk = newChunk;
} }
new (&m_LastChunk->m_data[m_LastChunk->m_nextIndex]) T(std::forward<Args>(args)...); 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_occupiedIndices[m_lastChunk->m_nextIndex] = true;
m_LastChunk->m_nextIndex++; m_lastChunk->m_nextIndex++;
m_LastChunk->m_size++; m_lastChunk->m_size++;
m_Size++; m_size++;
} }
/// std version of emplace_back
template<typename... Args> void emplace_back(Args&&... args) { EmplaceBack(std::forward<Args>(args)...); }
// Checks the first available gap and inserts. If no gap it works like emplace_back(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) template<typename... Args> void Emplace(Args&&... args)
{ {
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
@@ -431,7 +421,7 @@ namespace OpenVulkano
currentChunk->m_occupiedIndices[i] = true; currentChunk->m_occupiedIndices[i] = true;
currentChunk->m_size++; currentChunk->m_size++;
currentChunk->m_gapCount--; currentChunk->m_gapCount--;
m_Size++; m_size++;
return; return;
} }
} }
@@ -445,56 +435,47 @@ namespace OpenVulkano
void PopBack() void PopBack()
{ {
if (m_Size == 0) if (m_size == 0)
{ {
return; // return? or make return; // return? or make
} }
if (m_LastChunk->m_nextIndex == -1) if (m_lastChunk->m_nextIndex == -1)
{ {
VectorChunk* temp = m_LastChunk; VectorChunk* temp = m_lastChunk;
m_LastChunk = m_LastChunk->m_prev; m_lastChunk = m_lastChunk->m_prev;
m_LastChunk->m_next = nullptr; m_lastChunk->m_next = nullptr;
temp->~VectorChunk(); temp->~VectorChunk();
::operator delete(temp); ::operator delete(temp);
} }
m_LastChunk->m_data[m_LastChunk->m_nextIndex - 1].~T(); m_lastChunk->m_data[m_lastChunk->m_nextIndex - 1].~T();
m_LastChunk->m_occupiedIndices[m_LastChunk->m_nextIndex - 1] = false; m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex - 1] = false;
m_LastChunk->m_nextIndex--; m_lastChunk->m_nextIndex--;
m_LastChunk->m_size--; m_lastChunk->m_size--;
m_Size--; m_size--;
} }
/// std version of pop_back
void pop_back() { PopBack(); }
constexpr T& Back() const constexpr T& Back() const
{ {
if (m_Size == 0) if (m_size == 0)
{ {
throw std::out_of_range("Index out of range"); throw std::out_of_range("Index out of range");
} }
return m_LastChunk->m_data[m_LastChunk->GetLastOccupiedIndex()]; return m_lastChunk->m_data[m_lastChunk->GetLastOccupiedIndex()];
} }
/// std version of back
constexpr T& back() const { return Back(); }
constexpr T& Front() const constexpr T& Front() const
{ {
if (m_Size == 0) if (m_size == 0)
{ {
throw std::out_of_range("Index out of range"); throw std::out_of_range("Index out of range");
} }
return m_FirstChunk->m_data[0]; return m_firstChunk->m_data[0];
} }
/// std version of front
constexpr T& front() const { return Front(); }
void Remove(size_t index) void Remove(size_t index)
{ {
auto handle = FindChunk(index); auto handle = FindChunk(index);
@@ -513,61 +494,30 @@ namespace OpenVulkano
handle.first->m_occupiedIndices[realIndex] = false; handle.first->m_occupiedIndices[realIndex] = false;
handle.first->m_size--; handle.first->m_size--;
handle.first->m_gapCount++; handle.first->m_gapCount++;
m_Size--; m_size--;
} }
// Temporary non correct solution. (DONT MIND THIS ERASE) void Remove(const Iterator& it) { Remove(it.GetIndex()); }
void erase(Iterator it)
T& operator[](size_t index) noexcept
{ {
size_t index = 0;
VectorChunk* currentChunk = m_FirstChunk;
while (currentChunk)
{
if (index + currentChunk->m_size > it.GetIndex())
{
size_t realIndex = currentChunk->GetRealIndex(it.GetIndex());
currentChunk->m_data[realIndex].~T();
currentChunk->m_occupiedIndices[realIndex] = false;
currentChunk->m_size--;
currentChunk->m_gapCount++;
m_Size--;
return;
}
index += currentChunk->m_size;
currentChunk = currentChunk->m_next;
}
}
T& operator[](size_t index) noexcept { return At(index); }
T& At(size_t index)
{
if (index >= m_Size) [[unlikely]]
{
throw std::out_of_range("Index out of range");
}
auto handle = FindChunk(index); auto handle = FindChunk(index);
return handle.first->GetAlignedData(handle.second); return handle.first->GetAlignedData(handle.second);
} }
bool Contains(size_t index) noexcept T& At(size_t index)
{ {
if (index >= m_Size) if (index >= m_size) [[unlikely]]
{ {
return false; throw std::out_of_range("Index out of range");
} }
auto handle = FindChunk(index); return operator[](index);
return handle.first->m_occupiedIndices[handle.second];
} }
/// std version of contains
bool contains(size_t index) noexcept { return Contains(index); }
void Clear() void Clear()
{ {
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
VectorChunk* nextChunk = currentChunk->m_next; VectorChunk* nextChunk = currentChunk->m_next;
@@ -575,35 +525,37 @@ namespace OpenVulkano
currentChunk = nextChunk; currentChunk = nextChunk;
} }
m_FirstChunk = Grow(DEFAULT_CHUNK_SIZE); m_firstChunk = Grow(DEFAULT_CHUNK_SIZE);
m_LastChunk = m_FirstChunk; m_lastChunk = m_firstChunk;
m_Capacity = DEFAULT_CHUNK_SIZE; m_capacity = DEFAULT_CHUNK_SIZE;
m_Size = 0; m_size = 0;
} }
/// std version of clear /// std version of clear
size_t Size() const noexcept { return m_size; }
size_t Capacity() const noexcept { return m_capacity; }
bool Empty() const noexcept { return m_size == 0; }
Iterator begin() { return Iterator(m_firstChunk, 0); }
Iterator end() { return Iterator(m_lastChunk, m_lastChunk->m_nextIndex - 1); }
const Iterator& cbegin() { return Iterator(m_firstChunk, 0); }
const Iterator& cend() { return Iterator(m_lastChunk, m_lastChunk->m_nextIndex - 1); }
//region std aliases
void push_back(const T& value) { PushBack(value); }
void push_back(T&& value) { PushBack(std::move(value)); }
template<typename... Args> void emplace_back(Args&&... args) { EmplaceBack(std::forward<Args>(args)...); }
void pop_back() { PopBack(); }
T& back() { return Back(); }
T& front() { return Front(); }
bool empty() const noexcept { return Empty(); }
void clear() { Clear(); } void clear() { Clear(); }
void erase(const Iterator& it) { Remove(it.GetIndex()); }
/// std version of at size_t size() const noexcept { return Size(); }
T& at(size_t index) { return At(index); } size_t capacity() const noexcept { return Capacity(); }
//endregion
size_t Size() const noexcept { return m_Size; }
/// std version of size
size_t size() const noexcept { return m_Size; }
size_t Capacity() const noexcept { return m_Capacity; }
/// std version of capacity
size_t capacity() const noexcept { return m_Capacity; }
bool Empty() const noexcept { return m_Size == 0; }
/// std version of empty
bool empty() const noexcept { return m_Size == 0; }
Iterator begin() { return Iterator(m_FirstChunk, 0); }
Iterator end() { return Iterator(m_LastChunk, m_LastChunk->m_nextIndex - 1); }
const Iterator& cbegin() { return Iterator(m_FirstChunk, 0); }
const Iterator& cend() { return Iterator(m_LastChunk, m_LastChunk->m_nextIndex - 1); }
protected: protected:
VectorChunk* Grow(size_t requestSize) VectorChunk* Grow(size_t requestSize)
@@ -618,7 +570,7 @@ namespace OpenVulkano
std::pair<VectorChunk*, size_t> FindChunk(size_t index) std::pair<VectorChunk*, size_t> FindChunk(size_t index)
{ {
size_t leftIndex = index; size_t leftIndex = index;
VectorChunk* currentChunk = m_FirstChunk; VectorChunk* currentChunk = m_firstChunk;
while (currentChunk) while (currentChunk)
{ {
if (leftIndex < currentChunk->m_size) if (leftIndex < currentChunk->m_size)
@@ -634,10 +586,10 @@ namespace OpenVulkano
} }
private: private:
VectorChunk* m_FirstChunk; VectorChunk* m_firstChunk;
VectorChunk* m_LastChunk; VectorChunk* m_lastChunk;
size_t m_Size; size_t m_size;
size_t m_Capacity; size_t m_capacity;
}; };
} }

View File

@@ -45,18 +45,17 @@ TEST_CASE("BinSearchArrayMap With Default")
map.Remove(16); map.Remove(16);
map.Remove(23); map.Remove(23);
map.Remove(48); map.Remove(48);
}
}
TEST_CASE("BinSearchArrayMap With StableVector") REQUIRE(map.Size() == 47);
{ }
SECTION("Insert")
SECTION("Emplace")
{ {
BinSearchArrayMap<int, std::string, std::pair, StableVector> map; BinSearchArrayMap<int, std::string> map;
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
map.Insert(i, std::to_string(i)); map.Emplace(i, std::to_string(i));
} }
REQUIRE(map.Size() == 50); REQUIRE(map.Size() == 50);
@@ -65,7 +64,39 @@ TEST_CASE("BinSearchArrayMap With StableVector")
REQUIRE(map.Get(48) == "48"); REQUIRE(map.Get(48) == "48");
} }
SECTION("Remove") SECTION("FindPair")
{
BinSearchArrayMap<int, std::string> map;
for (int i = 0; i < 50; i++)
{
map.Insert(i, std::to_string(i));
}
auto pair = map.FindPair(16);
REQUIRE(pair.first == 16);
REQUIRE(pair.second == "16");
}
}
TEST_CASE("BinSearchArrayMap With StableVector")
{
//SECTION("Insert")
//{
// BinSearchArrayMap<int, std::string, std::pair, StableVector> map;
// for (int i = 0; i < 50; i++)
// {
// map.Insert(i, std::to_string(i));
// }
// REQUIRE(map.Size() == 50);
// REQUIRE(map.Get(16) == "16");
// REQUIRE(map.Get(23) == "23");
// REQUIRE(map.Get(48) == "48");
//}
/*SECTION("Remove")
{ {
BinSearchArrayMap<int, std::string, std::pair, StableVector> map; BinSearchArrayMap<int, std::string, std::pair, StableVector> map;
@@ -78,10 +109,14 @@ TEST_CASE("BinSearchArrayMap With StableVector")
map.Remove(23); map.Remove(23);
map.Remove(48); map.Remove(48);
printf("ARRAY WITH STABLE VECTOR\n"); for (int i = 0; i < map.Size(); i++)
for (int i = 0; i < 50; i++)
{ {
printf("index: %d, value: %s\n", i, map[i].c_str()); if (i == 16 || i == 23 || i == 48)
{
continue;
}
printf("i: %d, value: %s\n", i, map[i].c_str());
} }
} }*/
} }