aboutsummaryrefslogtreecommitdiffstats
path: root/include/api-test/freelist.hpp
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2023-03-05 21:00:21 +0100
committerladevieq <ladevie.quentin@gmail.com>2023-03-05 21:00:21 +0100
commita87ad2eac867b77a75e05ad48bb3ee622e5735d3 (patch)
tree95e75fa21b0d4000d32eeb127c9d68a83218846d /include/api-test/freelist.hpp
parent290e4c3c33f9af401c0565b840de3514d199faf5 (diff)
Change freelist implementation
Diffstat (limited to 'include/api-test/freelist.hpp')
-rw-r--r--include/api-test/freelist.hpp115
1 files changed, 86 insertions, 29 deletions
diff --git a/include/api-test/freelist.hpp b/include/api-test/freelist.hpp
index 3cdd55d..e9df734 100644
--- a/include/api-test/freelist.hpp
+++ b/include/api-test/freelist.hpp
@@ -3,61 +3,118 @@
#include <vector>
#include <cassert>
+#include "handle.hpp"
+
static constexpr uint32_t default_element_count = 1024U;
template<typename T, const size_t initial_size = default_element_count>
class freelist {
public:
- freelist()
- : free(initial_size),
- items(initial_size) {
- std::iota(free.rbegin(), free.rend(), 0);
+
+ freelist() {
+ auto next_free = 0U;
+ elements.reserve(initial_size);
+ for (auto id { 0U }; id < initial_size; id++) {
+ elements.push_back(
+ {
+ .next_free = static_cast<uint32_t>(++next_free % initial_size),
+ }
+ );
+ }
+
+ elements.back().next_free = -1U;
}
- uint32_t add(const T& item) {
- const auto id = free.back();
- free.pop_back();
+ handle<T> add(const T& item) {
+ auto id = elements[0U].next_free;
+
+ if (id != -1U) {
+ auto& element = elements[id];
- items[id] = std::move(item);
+ elements[0U].next_free = element.next_free;
+ element.item = std::move(item);
- return id;
+ return { id, ++element.generation };
+ }
+
+ // grow
}
- void remove(uint32_t item_id) {
- free.push_back(item_id);
+ void remove(handle<T> handle) {
+ assert(handle.generation == elements[handle.id].generation);
+ elements[handle.id].next_free = elements[0U].next_free;
+ elements[0U].next_free = handle.id;
}
- T& operator[](uint32_t index) {
- assert(index >= 0);
- return items[index];
+ T& operator[](handle<T> handle) {
+ assert(handle.generation == elements[handle.id].generation);
+ return elements[handle.id].item;
}
- const T& operator[](uint32_t index) const {
- return items[index];
+ const T& operator[](handle<T> handle) const {
+ assert(handle.generation == elements[handle.id].generation);
+ return elements[handle.id].item;
}
- uint32_t find(const T& seeked_item) {
- for (auto index { 0U }; index < items.size(); index++) {
- const auto& item = items[index];
- if (memcmp(&item, &seeked_item, sizeof(T)) == 0) {
- return index;
- }
+ static constexpr uint32_t invalid_id = -1;
+
+private:
+ struct element {
+ union {
+ T item;
+ uint32_t next_free = -1;
+ };
+ uint32_t generation = 0U;
+ };
+
+ std::vector<element> elements;
+};
+
+template<const size_t initial_size = default_element_count>
+class idlist {
+ public:
+
+ idlist() {
+ auto next_free = 1U;
+ elements.reserve(initial_size);
+ for (auto id { 0U }; id < initial_size; id++) {
+ elements.push_back(
+ {
+ .next_free = static_cast<uint32_t>(++next_free % initial_size),
+ }
+ );
}
- return invalid_id;
+ elements.back().next_free = -1U;
}
- auto begin() const {
- return items.begin();
+ handle<void> add() {
+ auto id = elements[0U].next_free;
+
+ if (id != -1U) {
+ auto& element = elements[id];
+ elements[0U].next_free = element.next_free;
+ element.next_free = -1;
+
+ return { id, ++element.generation };
+ }
+
+ // grow
}
- auto end() const {
- return items.end();
+ void remove(handle<void> handle) {
+ assert(handle.generation == elements[handle.id].generation);
+ elements[handle.id].next_free = elements[0U].next_free;
+ elements[0U].next_free = handle.id;
}
static constexpr uint32_t invalid_id = -1;
private:
- std::vector<T> items;
- std::vector<uint32_t> free;
+ struct element {
+ uint32_t next_free = -1;
+ uint32_t generation = 0U;
+ };
+
+ std::vector<element> elements;
};