4#include "../Foundation/Assert.h"
5#include "../Memory/Globals.h"
6#include "../Memory/Memory.h"
7#include "ArenaMapKey.h"
8#include "ContainersExport.h"
32 using Key = ArenaMapKey<T>;
33 using Gen =
typename Key::Generation;
37 ~ArenaMap() { clear(); }
39 ArenaMap(
const ArenaMap& other) : globalsType(other.globalsType) { *
this = other; }
41 ArenaMap(ArenaMap&& other) : globalsType(other.globalsType) { *
this =
move(other); }
43 ArenaMap& operator=(
const ArenaMap& other)
47 T* newItems =
reinterpret_cast<T*
>(allocator.allocate(
this, other.itemsSize *
sizeof(T),
alignof(T)));
48 Gen* newGens =
reinterpret_cast<Gen*
>(allocator.allocate(
this, other.itemsSize *
sizeof(Gen),
alignof(Gen)));
51 ::memset(newGens, 0, other.itemsSize *
sizeof(Gen));
53 generations = newGens;
54 itemsSize = other.itemsSize;
55 for (
size_t idx = 0; idx < other.itemsSize; ++idx)
57 if (other.generations[idx].used)
59 placementNew(items[idx], other.items[idx]);
61 generations[idx] = other.generations[idx];
63 numUsed = other.numUsed;
67 ArenaMap& operator=(ArenaMap&& other)
71 itemsSize = other.itemsSize;
72 other.items =
nullptr;
74 generations = other.generations;
75 other.generations =
nullptr;
76 numUsed = other.numUsed;
84 template <
typename MapType>
87 MapType* map =
nullptr;
92 const auto numAllocated = map->getNumAllocated();
93 for (++index; index < numAllocated; ++index)
95 if (map->generations[index].used)
105 return it.index == index;
110 return it.index != index;
113 auto& operator*()
const {
return map->items[index]; }
114 auto* operator->()
const {
return &map->items[index]; }
120 ConstIterator cend()
const {
return end(); }
121 ConstIterator begin()
const
125 if (generations[idx].used)
127 return {
this,
static_cast<uint32_t>(idx)};
139 if (generations[idx].used)
141 return {
this,
static_cast<uint32_t>(idx)};
151 for (
size_t idx = 0; idx < itemsSize; ++idx)
153 if (generations[idx].used)
157 generations[idx].used = 0;
163 generations =
nullptr;
168 [[nodiscard]]
size_t size()
const {
return numUsed; }
171 [[nodiscard]]
size_t capacity()
const {
return itemsSize; }
174 [[nodiscard]]
bool isFull()
const {
return itemsSize == numUsed; }
180 [[nodiscard]]
bool resize(
size_t newSize)
184 if (newSize > Key::MaxIndex)
190 generations =
nullptr;
192 T* newItems =
reinterpret_cast<T*
>(allocator.allocate(
this, newSize *
sizeof(T),
alignof(T)));
193 if (newItems ==
nullptr)
196 Gen* newGens =
reinterpret_cast<Gen*
>(allocator.allocate(
this, newSize *
sizeof(Gen),
alignof(Gen)));
197 if (newGens ==
nullptr)
199 ::memset(newGens, 0, newSize *
sizeof(Gen));
200 generations = newGens;
206 template <
typename Value>
207 [[nodiscard]] Key insert(
const Value&
object)
209 Key key = allocateNewKeySlot();
212 placementNew(items[key.index],
object);
217 [[nodiscard]] Key allocate()
219 Key key = allocateNewKeySlot();
222 placementNew(items[key.index]);
227 template <
typename Value>
228 [[nodiscard]] Key insert(Value&&
object)
230 Key key = allocateNewKeySlot();
233 placementNew(items[key.index],
move(
object));
238 [[nodiscard]]
bool containsKey(Key key)
const
240 return key.isValid() and generations[key.index].used != 0 and
241 generations[key.index].generation == key.generation.generation;
244 template <
typename ComparableToValue>
245 [[nodiscard]]
bool containsValue(
const ComparableToValue& value, Key* optionalKey =
nullptr)
const
247 for (
size_t idx = 0; idx < itemsSize; ++idx)
249 if (generations[idx].used and items[idx] == value)
253 optionalKey->index =
static_cast<uint32_t>(idx);
254 optionalKey->generation = generations[idx];
262 [[nodiscard]]
bool remove(Key key)
264 if (generations[key.index] != key.generation)
266 if (generations[key.index].generation + 1 <= Key::MaxGenerations)
268 generations[key.index].generation++;
273 generations[key.index].generation++;
275 generations[key.index].used = 0;
276 items[key.index].~T();
281 [[nodiscard]] T* get(Key key)
283 if (generations[key.index] != key.generation)
285 return &items[key.index];
288 [[nodiscard]]
const T* get(Key key)
const
290 if (generations[key.index] != key.generation)
292 return &items[key.index];
297 size_t itemsSize = 0;
299 Gen* generations =
nullptr;
305 [[nodiscard]] Key allocateNewKeySlot()
307 for (
size_t idx = 0; idx < itemsSize; ++idx)
309 if (generations[idx].used == 0)
311 generations[idx].used = 1;
314 key.generation = generations[idx];
315 key.index =
static_cast<uint32_t>(idx);
#define SC_ASSERT_DEBUG(e)
Assert expression e to be true.
Definition Assert.h:63
#define SC_ASSERT_RELEASE(e)
Assert expression e to be true.
Definition Assert.h:48
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition Compiler.h:273
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
A sparse vector keeping objects at a stable memory location.
Definition ArenaMapKey.h:10
bool resize(size_t newSize)
Changes the size of the arena.
Definition ArenaMap.h:180
size_t size() const
Get the number of used slots in the arena.
Definition ArenaMap.h:168
uint32_t getNumAllocated() const
Get the maximum number of objects that can be stored in this map.
Definition ArenaMap.h:82
size_t capacity() const
Get the total number slots in the arena.
Definition ArenaMap.h:171
bool isFull() const
Returns true if size() == capacity(), that means the arena is full.
Definition ArenaMap.h:174
static Globals & get(Type type)
Obtains current set of Globals.
Type
Definition Globals.h:40
@ Global
Shared globals (NOT thread-safe)
Definition Globals.h:41
void release(void *memory)
Free memory allocated by MemoryAllocator::allocate and / or reallocated by MemoryAllocator::reallocat...
Definition Memory.h:87