Skip to content

Commit

Permalink
PagedEntityContainer: add ReuseSlots boolean template parameter
Browse files Browse the repository at this point in the history
This allows to disable slot reuse in `PagedEntityContainer`.

The feature is temporary and will be used only until
we are confident that we don't have any issues in the
WZ code base regarding object pointers not updated
properly, e.g. when transitioning between the base
and offworld missions.

So, it's to prevent cases where one object would be
overwritten by another and the game code haven't noticed
that. It's better to crash/assert rather than silently
use one object instead of another, which could lead to
unobvious and weird bugs.

Signed-off-by: Pavel Solodovnikov <[email protected]>
  • Loading branch information
ManManson committed Mar 16, 2024
1 parent b77b5cb commit 4f3de9d
Showing 1 changed file with 34 additions and 10 deletions.
44 changes: 34 additions & 10 deletions lib/framework/paged_entity_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
/// </summary>
/// <typeparam name="T">Entity type. Should be a complete type.</typeparam>
/// <typeparam name="MaxElementsPerPage">The fixed number of elements each page may hold.</typeparam>
template <typename T, size_t MaxElementsPerPage = 1024>
/// <typeparam name="ReuseSlots">If `false`, slots are one-shot and set to expire after single use.</typeparam>
template <typename T, size_t MaxElementsPerPage = 1024, bool ReuseSlots = true>
class PagedEntityContainer
{
using SlotIndexType = size_t;
Expand Down Expand Up @@ -150,6 +151,11 @@ class PagedEntityContainer
return _isAlive;
}

void invalidate()
{
_generation = INVALID_GENERATION;
}

void set_dead()
{
_isAlive = false;
Expand Down Expand Up @@ -399,8 +405,11 @@ class PagedEntityContainer
{
return;
}
// Advance slot generation number.
slotMetadata.advance_generation();

// Either advance slot generation number or invalidate the slot right away,
// the behavior depends on whether we reuse the slots or not.
advance_slot_generation<ReuseSlots>(slotMetadata);

// Ensure that the element pointed-to by this slot is dead.
slotMetadata.set_dead();

Expand Down Expand Up @@ -580,7 +589,7 @@ class PagedEntityContainer

const_iterator begin() const
{
return const_iterator(const_cast<PagedEntityContainer<T>*>(this)->begin());
return const_iterator(const_cast<PagedEntityContainer*>(this)->begin());
}

iterator begin()
Expand Down Expand Up @@ -657,7 +666,7 @@ class PagedEntityContainer

const_iterator find(const T& x) const
{
return const_iterator(const_cast<PagedEntityContainer<T>*>(this)->find(const_cast<T&>(x)));
return const_iterator(const_cast<PagedEntityContainer*>(this)->find(const_cast<T&>(x)));
}

void erase(const_iterator it)
Expand Down Expand Up @@ -787,17 +796,32 @@ class PagedEntityContainer
return (reinterpret_cast<uintptr_t>(addr) % alignof(T)) == 0;
}

template <bool ReuseSlotsAux>
void advance_slot_generation(SlotMetadata& meta)
{
// Advance slot generation number, when `ReuseSlots=true`.
meta.advance_generation();
}

// Specialization for the case when `ReuseSlots=false`.
template <>
void advance_slot_generation<false>(SlotMetadata& meta)
{
// Invalidate slot right away so that it cannot be reused anymore.
meta.invalidate();
}

std::vector<Page> _pages;
SlotIndexType _maxIndex = INVALID_SLOT_IDX;
size_t _size = 0;
size_t _capacity = 0;
size_t _expiredSlotsCount = 0;
};

template <typename T, size_t MaxElementsPerPage>
constexpr typename PagedEntityContainer<T, MaxElementsPerPage>::SlotIndexType
PagedEntityContainer<T, MaxElementsPerPage>::INVALID_SLOT_IDX;
template <typename T, size_t MaxElementsPerPage, bool ReuseSlots>
constexpr typename PagedEntityContainer<T, MaxElementsPerPage, ReuseSlots>::SlotIndexType
PagedEntityContainer<T, MaxElementsPerPage, ReuseSlots>::INVALID_SLOT_IDX;

template <typename T, size_t MaxElementsPerPage>
constexpr size_t PagedEntityContainer<T, MaxElementsPerPage>::INVALID_PAGE_IDX;
template <typename T, size_t MaxElementsPerPage, bool ReuseSlots>
constexpr size_t PagedEntityContainer<T, MaxElementsPerPage, ReuseSlots>::INVALID_PAGE_IDX;

0 comments on commit 4f3de9d

Please sign in to comment.