4template <
typename IdType,
typename ValueType>
10 if (m_IdTable.IsEmpty())
13 while (m_IdTable.m_pEntries[m_CurrentIndex].id.m_InstanceIndex != m_CurrentIndex)
19template <
typename IdType,
typename ValueType>
22 return m_CurrentCount < m_IdTable.m_Count;
25template <
typename IdType,
typename ValueType>
29 return m_IdTable.m_pEntries == it2.m_IdTable.m_pEntries && m_CurrentIndex == it2.m_CurrentIndex;
32template <
typename IdType,
typename ValueType>
36 return !(*
this == it2);
39template <
typename IdType,
typename ValueType>
42 return m_IdTable.m_pEntries[m_CurrentIndex].id;
45template <
typename IdType,
typename ValueType>
48 return m_IdTable.m_pEntries[m_CurrentIndex].value;
51template <
typename IdType,
typename ValueType>
55 if (m_CurrentCount == m_IdTable.m_Count)
61 }
while (m_IdTable.m_pEntries[m_CurrentIndex].id.m_InstanceIndex != m_CurrentIndex);
64template <
typename IdType,
typename ValueType>
73template <
typename IdType,
typename ValueType>
75 : ConstIterator(idTable)
79template <
typename IdType,
typename ValueType>
82 return this->m_IdTable.m_pEntries[this->m_CurrentIndex].value;
88template <
typename IdType,
typename ValueType>
94 m_FreelistEnqueue = -1;
95 m_FreelistDequeue = 0;
96 m_pAllocator = pAllocator;
99template <
typename IdType,
typename ValueType>
102 m_pEntries =
nullptr;
105 m_FreelistEnqueue = -1;
106 m_FreelistDequeue = 0;
107 m_pAllocator = pAllocator;
112template <
typename IdType,
typename ValueType>
115 for (IndexType i = 0; i < m_Capacity; ++i)
117 if (m_pEntries[i].
id.m_InstanceIndex == i)
123 PL_DELETE_RAW_BUFFER(m_pAllocator, m_pEntries);
127template <
typename IdType,
typename ValueType>
133 for (IndexType i = 0; i < rhs.m_Capacity; ++i)
135 Entry& entry = m_pEntries[i];
137 entry.id = rhs.m_pEntries[i].id;
138 if (entry.id.m_InstanceIndex == i)
144 m_Count = rhs.m_Count;
145 m_FreelistDequeue = rhs.m_FreelistDequeue;
148template <
typename IdType,
typename ValueType>
151 if (m_Capacity >= capacity + CAPACITY_ALIGNMENT)
154 const plUInt64 uiCurCap64 =
static_cast<plUInt64
>(this->m_Capacity);
155 plUInt64 uiNewCapacity64 = uiCurCap64 + (uiCurCap64 / 2);
162 uiNewCapacity64 = (uiNewCapacity64 + (CAPACITY_ALIGNMENT - 1)) & ~(CAPACITY_ALIGNMENT - 1);
164 SetCapacity(
static_cast<IndexType
>(uiNewCapacity64 & 0xFFFFFFFF));
167template <
typename IdType,
typename ValueType>
173template <
typename IdType,
typename ValueType>
179template <
typename IdType,
typename ValueType>
182 for (IndexType i = 0; i < m_Capacity; ++i)
184 Entry& entry = m_pEntries[i];
186 if (entry.id.m_InstanceIndex == i)
189 ++entry.id.m_Generation;
192 entry.id.m_InstanceIndex =
static_cast<decltype(entry.
id.m_InstanceIndex)
>(i + 1);
195 m_FreelistDequeue = 0;
196 m_FreelistEnqueue = m_Capacity - 1;
200template <
typename IdType,
typename ValueType>
205 const IndexType uiNewIndex = m_FreelistDequeue;
206 Entry& entry = m_pEntries[uiNewIndex];
208 m_FreelistDequeue = entry.id.m_InstanceIndex;
209 entry.id.m_InstanceIndex =
static_cast<decltype(entry.
id.m_InstanceIndex)
>(uiNewIndex);
218template <
typename IdType,
typename ValueType>
223 const IndexType uiNewIndex = m_FreelistDequeue;
224 Entry& entry = m_pEntries[uiNewIndex];
226 m_FreelistDequeue = entry.id.m_InstanceIndex;
227 entry.id.m_InstanceIndex =
static_cast<decltype(entry.
id.m_InstanceIndex)
>(uiNewIndex);
236template <
typename IdType,
typename ValueType>
239 if (m_Capacity <=
id.m_InstanceIndex)
242 const IndexType uiIndex =
id.m_InstanceIndex;
243 Entry& entry = m_pEntries[uiIndex];
244 if (!entry.id.IsIndexAndGenerationEqual(
id))
247 if (out_pOldValue !=
nullptr)
248 *out_pOldValue = std::move(m_pEntries[uiIndex].value);
252 entry.id.m_InstanceIndex = m_pEntries[m_FreelistEnqueue].id.m_InstanceIndex;
253 ++entry.id.m_Generation;
256 if (entry.id.m_Generation == 0)
257 entry.id.m_Generation = 1;
259 m_pEntries[m_FreelistEnqueue].id.m_InstanceIndex =
static_cast<decltype(entry.
id.m_InstanceIndex)
>(uiIndex);
260 m_FreelistEnqueue = uiIndex;
266template <
typename IdType,
typename ValueType>
269 const IndexType index =
id.m_InstanceIndex;
270 if (index < m_Capacity && m_pEntries[index].
id.IsIndexAndGenerationEqual(
id))
272 out_value = m_pEntries[index].value;
278template <
typename IdType,
typename ValueType>
281 const IndexType index =
id.m_InstanceIndex;
282 if (index < m_Capacity && m_pEntries[index].
id.IsIndexAndGenerationEqual(
id))
284 out_pValue = &m_pEntries[index].value;
290template <
typename IdType,
typename ValueType>
293 PL_ASSERT_DEBUG(
id.m_InstanceIndex < m_Capacity,
"Out of bounds access. Table has {0} elements, trying to access element at index {1}.",
294 m_Capacity,
id.m_InstanceIndex);
295 const Entry& entry = m_pEntries[
id.m_InstanceIndex];
296 PL_ASSERT_DEBUG(entry.id.IsIndexAndGenerationEqual(
id),
"Stale access. Trying to access a value (generation: {0}) that has been removed and replaced by a new value (generation: {1})", entry.id.m_Generation,
id.m_Generation);
301template <
typename IdType,
typename ValueType>
304 PL_ASSERT_DEBUG(
id.m_InstanceIndex < m_Capacity,
"Out of bounds access. Table has {0} elements, trying to access element at index {1}.", m_Capacity,
id.m_InstanceIndex);
306 Entry& entry = m_pEntries[
id.m_InstanceIndex];
308 PL_ASSERT_DEBUG(entry.id.IsIndexAndGenerationEqual(
id),
"Stale access. Trying to access a value (generation: {0}) that has been removed and replaced by a new value (generation: {1})",
static_cast<int>(entry.id.m_Generation),
id.m_Generation);
313template <
typename IdType,
typename ValueType>
316 PL_ASSERT_DEBUG(index < m_Capacity,
"Out of bounds access. Table has {0} elements, trying to access element at index {1}.", m_Capacity, index);
317 return m_pEntries[index].value;
320template <
typename IdType,
typename ValueType>
323 PL_ASSERT_DEBUG(index < m_Capacity,
"Out of bounds access. Table has {0} elements, trying to access element at index {1}.", m_Capacity, index);
324 return m_pEntries[index].value;
327template <
typename IdType,
typename ValueType>
330 const IndexType index =
id.m_InstanceIndex;
331 return index < m_Capacity && m_pEntries[index].id.IsIndexAndGenerationEqual(
id);
334template <
typename IdType,
typename ValueType>
340template <
typename IdType,
typename ValueType>
346template <
typename IdType,
typename ValueType>
352template <
typename IdType,
typename ValueType>
355 if (m_pEntries ==
nullptr)
358 IndexType uiIndex = m_FreelistDequeue;
359 const Entry* pEntry = m_pEntries + uiIndex;
361 while (pEntry->id.m_InstanceIndex < m_Capacity)
363 uiIndex = pEntry->id.m_InstanceIndex;
364 pEntry = m_pEntries + uiIndex;
367 return uiIndex == m_FreelistEnqueue;
372template <
typename IdType,
typename ValueType>
375 Entry* pNewEntries = PL_NEW_RAW_BUFFER(m_pAllocator, Entry, (
size_t)uiCapacity);
377 for (IndexType i = 0; i < m_Capacity; ++i)
379 pNewEntries[i].id = m_pEntries[i].id;
381 if (m_pEntries[i].
id.m_InstanceIndex == i)
387 PL_DELETE_RAW_BUFFER(m_pAllocator, m_pEntries);
388 m_pEntries = pNewEntries;
390 InitializeFreelist(m_Capacity, uiCapacity);
391 m_Capacity = uiCapacity;
394template <
typename IdType,
typename ValueType>
397 for (IndexType i = uiStart; i < uiEnd; ++i)
399 IdType&
id = m_pEntries[i].id;
400 id = IdType(i + 1, 1);
403 m_FreelistEnqueue = uiEnd - 1;
407template <
typename IdType,
typename V,
typename A>
413template <
typename IdType,
typename V,
typename A>
419template <
typename IdType,
typename V,
typename A>
425template <
typename IdType,
typename V,
typename A>
431template <
typename IdType,
typename V,
typename A>
437template <
typename IdType,
typename V,
typename A>
Base class for all memory allocators.
Definition Allocator.h:23
Const iterator.
Definition IdTable.h:25
bool IsValid() const
Checks whether this iterator points to a valid element.
Definition IdTable_inl.h:20
const ValueType & Value() const
Returns the 'value' of the element that this iterator points to.
Definition IdTable_inl.h:46
bool operator==(const typename plIdTableBase< IdType, ValueType >::ConstIterator &it2) const
Checks whether the two iterators point to the same element.
Definition IdTable_inl.h:26
void Next()
Advances the iterator to the next element in the map. The iterator will not be valid anymore,...
Definition IdTable_inl.h:52
void operator++()
Shorthand for 'Next'.
Definition IdTable_inl.h:65
IdType Id() const
Returns the 'id' of the element that this iterator points to.
Definition IdTable_inl.h:40
bool operator!=(const typename plIdTableBase< IdType, ValueType >::ConstIterator &it2) const
Checks whether the two iterators point to the same element.
Definition IdTable_inl.h:33
Implementation of an id mapping table which stores id/value pairs.
Definition IdTable.h:18
~plIdTableBase()
Destructor.
Definition IdTable_inl.h:113
IndexType GetCount() const
Returns the number of active entries in the table.
Definition IdTable_inl.h:168
const ValueType & operator[](const IdType id) const
Returns the value to the given id. Does bounds checks in debug builds.
Definition IdTable_inl.h:291
bool TryGetValue(const IdType id, ValueType &out_value) const
Returns if an entry with the given id was found and if found writes out the corresponding value to ou...
Definition IdTable_inl.h:267
void Clear()
Clears the table.
Definition IdTable_inl.h:180
void Reserve(IndexType capacity)
Expands the table so it can at least store the given capacity.
Definition IdTable_inl.h:149
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition IdTable_inl.h:335
const ValueType & GetValueUnchecked(const IndexType index) const
Returns the value at the given index. Does bounds checks in debug builds but does not check for stale...
Definition IdTable_inl.h:314
bool Contains(const IdType id) const
Returns if the table contains an entry corresponding to the given id.
Definition IdTable_inl.h:328
void operator=(const plIdTableBase< IdType, ValueType > &rhs)
Copies the data from another table into this one.
Definition IdTable_inl.h:128
plIdTableBase(plAllocator *pAllocator)
Creates an empty id-table. Does not allocate any data yet.
Definition IdTable_inl.h:89
bool IsFreelistValid() const
Returns whether the internal free-list is valid. For testing purpose only.
Definition IdTable_inl.h:353
bool Remove(const IdType id, ValueType *out_pOldValue=nullptr)
Removes the entry with the given id. Returns if an entry was removed and optionally writes out the ol...
Definition IdTable_inl.h:237
IdType Insert(const ValueType &value)
Inserts the value into the table and returns the corresponding id.
Definition IdTable_inl.h:201
bool IsEmpty() const
Returns true, if the table does not contain any elements.
Definition IdTable_inl.h:174
plAllocator * GetAllocator() const
Returns the allocator that is used by this instance.
Definition IdTable_inl.h:347
static void CopyConstruct(Destination *pDestination, const Source ©, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination, by creating uiCount copies of c...
static void RelocateConstruct(T *pDestination, T *pSource, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination from an existing array of object...
static void MoveConstruct(T *pDestination, T &&source)
Constructs an object of type T in a raw buffer at pDestination, by using move construction from sourc...
static void Destruct(T *pDestination, size_t uiCount=1)
Destructs uiCount objects of type T at pDestination.
constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition Math_inl.h:27
constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
Returns the greater value, f1 or f2.
Definition Math_inl.h:39
Iterator with write access.
Definition IdTable.h:60
ValueType & Value()
Returns the 'value' of the element that this iterator points to.
Definition IdTable_inl.h:80