2#include "gaia/config/config.h"
8#include "gaia/cnt/bitset.h"
9#include "gaia/cnt/darray.h"
10#include "gaia/core/utility.h"
11#include "gaia/mem/mem_alloc.h"
12#include "gaia/mem/raw_data_holder.h"
18 template <
typename TListItem>
19 struct ilist_item_traits;
23 template <
typename T,
typename =
void>
24 struct ilist_has_idx_member: std::false_type {};
26 struct ilist_has_idx_member<T, std::void_t<decltype(std::declval<T&>().idx)>>: std::true_type {};
28 template <
typename T,
typename =
void>
29 struct ilist_has_gen_member: std::false_type {};
31 struct ilist_has_gen_member<T, std::void_t<decltype(std::declval<T&>().gen)>>: std::true_type {};
33 template <
typename T,
typename =
void>
34 struct ilist_has_data_gen_member: std::false_type {};
36 struct ilist_has_data_gen_member<T, std::void_t<decltype(std::declval<T&>().data.gen)>>: std::true_type {};
38 template <
typename T,
typename =
void>
39 struct ilist_has_id_mask: std::false_type {};
41 struct ilist_has_id_mask<T, std::void_t<decltype(T::IdMask)>>: std::true_type {};
43 template <
typename T,
typename =
void>
44 struct ilist_has_handle_id: std::false_type {};
46 struct ilist_has_handle_id<T, std::void_t<decltype(std::declval<const T&>().id())>>: std::true_type {};
48 template <
typename T,
typename =
void>
49 struct ilist_has_handle_gen: std::false_type {};
51 struct ilist_has_handle_gen<T, std::void_t<decltype(std::declval<const T&>().gen())>>: std::true_type {};
53 template <
typename T,
typename =
void>
54 struct ilist_has_create: std::false_type {};
56 struct ilist_has_create<
57 T, std::void_t<decltype(T::create(std::declval<uint32_t>(), std::declval<uint32_t>(), (void*)nullptr))>>:
60 template <
typename T,
typename THandle,
typename =
void>
61 struct ilist_has_handle: std::false_type {};
62 template <
typename T,
typename THandle>
63 struct ilist_has_handle<T, THandle, std::void_t<decltype(T::handle(std::declval<const T&>()))>>:
64 std::bool_constant<std::is_convertible_v<decltype(T::handle(std::declval<const T&>())), THandle>> {};
66 template <
typename T,
typename =
void>
67 struct ilist_traits_has_idx: std::false_type {};
69 struct ilist_traits_has_idx<T, std::void_t<decltype(ilist_item_traits<T>::idx(std::declval<const T&>()))>>:
72 template <
typename T,
typename =
void>
73 struct ilist_traits_has_set_idx: std::false_type {};
75 struct ilist_traits_has_set_idx<
76 T, std::void_t<decltype(ilist_item_traits<T>::set_idx(std::declval<T&>(), std::declval<uint32_t>()))>>:
79 template <
typename T,
typename =
void>
80 struct ilist_traits_has_gen: std::false_type {};
82 struct ilist_traits_has_gen<T, std::void_t<decltype(ilist_item_traits<T>::gen(std::declval<const T&>()))>>:
85 template <
typename T,
typename =
void>
86 struct ilist_traits_has_set_gen: std::false_type {};
88 struct ilist_traits_has_set_gen<
89 T, std::void_t<decltype(ilist_item_traits<T>::set_gen(std::declval<T&>(), std::declval<uint32_t>()))>>:
96 template <
typename TListItem>
99 detail::ilist_has_idx_member<TListItem>::value,
100 "ilist item type must expose idx or specialize ilist_item_traits");
102 detail::ilist_has_gen_member<TListItem>::value || detail::ilist_has_data_gen_member<TListItem>::value,
103 "ilist item type must expose gen/data.gen or specialize ilist_item_traits");
123 if constexpr (detail::ilist_has_gen_member<TListItem>::value)
133 if constexpr (detail::ilist_has_gen_member<TListItem>::value)
136 item.data.gen = value;
172 GAIA_ASSERT(core::addressof(other) !=
this);
191 GAIA_ASSERT(core::addressof(other) !=
this);
203 template <
typename TListItem>
222 template <
typename TListItem,
typename TItemHandle,
typename TInternalStorage = darray_ilist_storage<TListItem>>
250 static_assert(detail::ilist_traits_has_idx<TListItem>::value,
"ilist_item_traits<T> must expose idx(const T&)");
252 detail::ilist_traits_has_set_idx<TListItem>::value,
"ilist_item_traits<T> must expose set_idx(T&, uint32_t)");
253 static_assert(detail::ilist_traits_has_gen<TListItem>::value,
"ilist_item_traits<T> must expose gen(const T&)");
255 detail::ilist_traits_has_set_gen<TListItem>::value,
"ilist_item_traits<T> must expose set_gen(T&, uint32_t)");
257 detail::ilist_has_create<TListItem>::value,
258 "ilist item type must expose static create(index, generation, ctx)");
260 detail::ilist_has_handle<TListItem, TItemHandle>::value,
261 "ilist item type must expose static handle(const item) returning the handle type");
262 static_assert(detail::ilist_has_id_mask<TItemHandle>::value,
"ilist handle type must expose IdMask");
263 static_assert(detail::ilist_has_handle_id<TItemHandle>::value,
"ilist handle type must expose id()");
264 static_assert(detail::ilist_has_handle_gen<TItemHandle>::value,
"ilist handle type must expose gen()");
389 GAIA_ASSERT(
itemCnt < TItemHandle::IdMask &&
"Trying to allocate too many items!");
391 GAIA_GCC_WARNING_PUSH()
392 GAIA_CLANG_WARNING_PUSH()
393 GAIA_GCC_WARNING_DISABLE(
"-Wstringop-overflow");
394 GAIA_GCC_WARNING_DISABLE(
"-Wmissing-field-initializers");
395 GAIA_CLANG_WARNING_DISABLE(
"-Wmissing-field-initializers");
398 GAIA_GCC_WARNING_POP()
399 GAIA_CLANG_WARNING_POP()
410 return TListItem::handle(
j);
419 GAIA_ASSERT(
itemCnt < TItemHandle::IdMask &&
"Trying to allocate too many items!");
421 GAIA_GCC_WARNING_PUSH()
422 GAIA_CLANG_WARNING_PUSH()
423 GAIA_GCC_WARNING_DISABLE(
"-Wstringop-overflow");
424 GAIA_GCC_WARNING_DISABLE(
"-Wmissing-field-initializers");
425 GAIA_CLANG_WARNING_DISABLE(
"-Wmissing-field-initializers");
428 GAIA_GCC_WARNING_POP()
429 GAIA_CLANG_WARNING_POP()
447 auto& item =
m_items[handle.id()];
490 template <
typename TItemHandle,
typename =
void>
505 template <
typename TItemHandle>
523 template <
typename TListItem,
typename TItemHandle, u
int32_t MaxPages = 0>
530 template <
typename TPagedIList,
bool IsConst>
532 using owner_type = std::conditional_t<IsConst, const TPagedIList, TPagedIList>;
533 using owner_pointer = owner_type*;
535 owner_pointer m_pOwner =
nullptr;
536 typename TPagedIList::size_type m_index = 0;
548 std::conditional_t<IsConst, typename TPagedIList::const_reference, typename TPagedIList::reference>;
550 using pointer = std::conditional_t<IsConst, typename TPagedIList::const_pointer, typename TPagedIList::pointer>;
561 m_pOwner(
pOwner), m_index(index) {
568 return (*m_pOwner)[m_index];
574 return &(*m_pOwner)[m_index];
597 return m_pOwner == other.m_pOwner && m_index == other.m_index;
604 return !(*
this == other);
617 template <
typename TListItem,
typename TItemHandle, u
int32_t MaxPages>
636 static_assert(detail::ilist_traits_has_idx<TListItem>::value,
"ilist_item_traits<T> must expose idx(const T&)");
638 detail::ilist_traits_has_set_idx<TListItem>::value,
"ilist_item_traits<T> must expose set_idx(T&, uint32_t)");
639 static_assert(detail::ilist_traits_has_gen<TListItem>::value,
"ilist_item_traits<T> must expose gen(const T&)");
641 detail::ilist_traits_has_set_gen<TListItem>::value,
"ilist_item_traits<T> must expose set_gen(T&, uint32_t)");
643 detail::ilist_has_create<TListItem>::value,
644 "paged_ilist item type must expose static create(index, generation, ctx)");
646 detail::ilist_has_handle<TListItem, TItemHandle>::value,
647 "paged_ilist item type must expose static handle(const item) returning the handle type");
648 static_assert(detail::ilist_has_id_mask<TItemHandle>::value,
"paged_ilist handle type must expose IdMask");
649 static_assert(detail::ilist_has_handle_id<TItemHandle>::value,
"paged_ilist handle type must expose id()");
650 static_assert(detail::ilist_has_handle_gen<TItemHandle>::value,
"paged_ilist handle type must expose gen()");
661 static constexpr size_type max_page_capacity() noexcept {
665 static constexpr size_type calc_page_capacity() noexcept {
666 const size_type payloadItemBytes =
sizeof(TListItem) == 0 ? 1U : (
size_type)sizeof(TListItem);
667 const size_type desired = target_payload_bytes() / payloadItemBytes;
668 if (desired < min_page_capacity())
669 return min_page_capacity();
670 if (desired > max_page_capacity())
671 return max_page_capacity();
675 static constexpr size_type PageCapacity = calc_page_capacity();
676 static constexpr bool FixedPageTable = MaxPages != 0;
677 static constexpr size_type StaticPageCount = MaxPages == 0 ? 1U : MaxPages;
680 using alive_mask_type = cnt::bitset<PageCapacity>;
681 using storage_type = mem::raw_data_holder<TListItem,
sizeof(TListItem) * PageCapacity>;
683 alive_mask_type aliveMask;
684 TItemHandle handles[PageCapacity]{};
685 uint32_t nextFree[PageCapacity];
686 uint32_t liveCount = 0;
687 storage_type* pStorage =
nullptr;
690 GAIA_FOR(PageCapacity)
691 nextFree[i] = TItemHandle::IdMask;
698 page_type(
const page_type&) =
delete;
699 page_type& operator=(
const page_type&) =
delete;
701 page_type(page_type&& other)
noexcept:
702 aliveMask(other.aliveMask), liveCount(other.liveCount), pStorage(other.pStorage) {
703 GAIA_FOR(PageCapacity) {
704 handles[i] = other.handles[i];
705 nextFree[i] = other.nextFree[i];
708 other.aliveMask.reset();
710 other.pStorage =
nullptr;
713 page_type& operator=(page_type&& other)
noexcept {
714 GAIA_ASSERT(core::addressof(other) !=
this);
717 aliveMask = other.aliveMask;
718 liveCount = other.liveCount;
719 pStorage = other.pStorage;
720 GAIA_FOR(PageCapacity) {
721 handles[i] = other.handles[i];
722 nextFree[i] = other.nextFree[i];
725 other.aliveMask.reset();
727 other.pStorage =
nullptr;
731 GAIA_NODISCARD
pointer data() noexcept {
732 return pStorage ==
nullptr ? nullptr :
reinterpret_cast<pointer>((uint8_t*)*pStorage);
736 return pStorage ==
nullptr ? nullptr :
reinterpret_cast<const_pointer>((
const uint8_t*)*pStorage);
740 GAIA_ASSERT(slot < PageCapacity);
741 GAIA_ASSERT(pStorage !=
nullptr);
742 return data() + slot;
746 GAIA_ASSERT(slot < PageCapacity);
747 GAIA_ASSERT(pStorage !=
nullptr);
748 return data() + slot;
751 void ensure_storage() {
752 if GAIA_LIKELY (pStorage !=
nullptr)
755 constexpr auto StorageAlignment =
756 alignof(storage_type) < sizeof(
void*) ? sizeof(
void*) : alignof(storage_type);
757 pStorage = mem::AllocHelper::alloc_alig<storage_type>("PagedIListPage", StorageAlignment);
760 void maybe_release_storage() {
761 if (liveCount != 0 || pStorage ==
nullptr)
769 if (pStorage !=
nullptr) {
770 for (
auto slot: aliveMask)
771 core::call_dtor(ptr(slot));
778 GAIA_FOR(PageCapacity)
779 nextFree[i] = TItemHandle::IdMask;
782 template <
typename... Args>
783 void construct(
size_type slot, Args&&... args) {
784 GAIA_ASSERT(slot < PageCapacity);
786 core::call_ctor(ptr(slot), GAIA_FWD(args)...);
792 GAIA_ASSERT(slot < PageCapacity);
793 GAIA_ASSERT(aliveMask.test(slot));
794 core::call_dtor(ptr(slot));
795 aliveMask.reset(slot);
796 GAIA_ASSERT(liveCount > 0);
798 maybe_release_storage();
803 cnt::darray<page_type*> m_pages;
806 page_type* m_staticPages[StaticPageCount]{};
817 return index / PageCapacity;
821 return index % PageCapacity;
824 GAIA_NODISCARD
static constexpr size_type page_count_for_slots(
size_type slotCnt)
noexcept {
825 return slotCnt == 0 ? 0U : (slotCnt + PageCapacity - 1) / PageCapacity;
839 return page_count_for_slots(
slotCnt);
844 if constexpr (FixedPageTable)
850 GAIA_NODISCARD page_type*& page_slot(
size_type pageIdx)
noexcept {
851 if constexpr (FixedPageTable) {
852 GAIA_ASSERT(pageIdx < MaxPages);
853 return m_staticPages[pageIdx];
855 GAIA_ASSERT(pageIdx < (
size_type)m_pages.size());
856 return m_pages[pageIdx];
860 GAIA_NODISCARD
const page_type* page_slot(
size_type pageIdx)
const noexcept {
861 if constexpr (FixedPageTable) {
862 GAIA_ASSERT(pageIdx < MaxPages);
863 return m_staticPages[pageIdx];
865 GAIA_ASSERT(pageIdx < (
size_type)m_pages.size());
866 return m_pages[pageIdx];
871 const auto pageCnt = page_table_size();
873 auto*& pPage = page_slot(i);
874 if (pPage ==
nullptr)
880 if constexpr (!FixedPageTable)
884 void ensure_page_count(
size_type slotCnt) {
885 const auto pageCnt = page_count_for_slots(slotCnt);
886 if constexpr (FixedPageTable) {
887 GAIA_ASSERT(pageCnt <= MaxPages &&
"Trying to allocate too many paged_ilist pages!");
890 m_pages.resize(pageCnt,
nullptr);
894 GAIA_NODISCARD page_type& ensure_page(
size_type index) {
895 ensure_page_count(index + 1);
896 auto*& pPage = page_slot(page_index(index));
897 if (pPage ==
nullptr)
898 pPage =
new page_type();
902 GAIA_NODISCARD page_type* try_page(
size_type index)
noexcept {
903 const auto pageIdx = page_index(index);
904 if (pageIdx >= page_table_size())
906 return page_slot(pageIdx);
909 GAIA_NODISCARD
const page_type* try_page(
size_type index)
const noexcept {
910 const auto pageIdx = page_index(index);
911 if (pageIdx >= page_table_size())
913 return page_slot(pageIdx);
917 auto* pPage = try_page(index);
918 GAIA_ASSERT(pPage !=
nullptr);
919 return *pPage->ptr(slot_index(index));
923 auto* pPage = try_page(index);
924 GAIA_ASSERT(pPage !=
nullptr);
925 return *pPage->ptr(slot_index(index));
945 if constexpr (FixedPageTable) {
947 m_staticPages[
i] = other.m_staticPages[
i];
948 other.m_staticPages[
i] =
nullptr;
951 m_pages = GAIA_MOV(other.m_pages);
956 other.m_freeItems = 0;
962 GAIA_ASSERT(core::addressof(other) !=
this);
965 if constexpr (FixedPageTable) {
967 m_staticPages[
i] = other.m_staticPages[
i];
968 other.m_staticPages[
i] =
nullptr;
971 m_pages = GAIA_MOV(other.m_pages);
974 m_size = other.m_size;
980 other.m_freeItems = 0;
1000 if (index >= m_size)
1003 const auto*
pPage = try_page(index);
1004 return pPage !=
nullptr &&
pPage->aliveMask.test(slot_index(index));
1018 GAIA_ASSERT(index < m_size);
1019 const auto*
pPage = try_page(index);
1020 GAIA_ASSERT(
pPage !=
nullptr);
1021 return pPage->handles[slot_index(index)];
1028 return handle(index).gen();
1035 GAIA_ASSERT(index < m_size);
1036 const auto*
pPage = try_page(index);
1037 GAIA_ASSERT(
pPage !=
nullptr);
1038 return pPage->nextFree[slot_index(index)];
1045 GAIA_ASSERT(
has(index));
1046 return slot_ref(index);
1053 GAIA_ASSERT(
has(index));
1054 return slot_ref(index);
1098 if constexpr (FixedPageTable)
1145 const auto pageCnt = page_count_for_slots(
cap);
1146 if constexpr (FixedPageTable) {
1159 const auto pageCnt = page_count_for_slots(
cap);
1160 if constexpr (FixedPageTable) {
1163 ensure_page_count(
cap);
1173 auto*
pPage = try_page(index);
1174 GAIA_ASSERT(
pPage !=
nullptr);
1175 const auto slot = slot_index(index);
1176 GAIA_ASSERT(
pPage->aliveMask.test(
slot));
1186 const auto*
pPage = try_page(index);
1187 GAIA_ASSERT(
pPage !=
nullptr);
1188 const auto slot = slot_index(index);
1189 GAIA_ASSERT(
pPage->aliveMask.test(
slot));
1198 auto*
pPage = try_page(index);
1199 GAIA_ASSERT(
pPage !=
nullptr);
1200 return *
pPage->ptr(slot_index(index));
1208 const auto*
pPage = try_page(index);
1209 GAIA_ASSERT(
pPage !=
nullptr);
1210 return *
pPage->ptr(slot_index(index));
1219 return &slot_ref(index);
1228 return &slot_ref(index);
1237 auto&
page = ensure_page(index);
1238 const auto slot = slot_index(index);
1239 const bool existed = index < m_size;
1243 if (index >= m_size)
1250 page.construct(
slot, GAIA_MOV(item));
1252 page.nextFree[
slot] = TItemHandle::IdMask;
1260 auto&
page = ensure_page(index);
1261 const auto slot = slot_index(index);
1262 const bool existed = index < m_size;
1266 if (index >= m_size)
1297 GAIA_ASSERT(index < TItemHandle::IdMask &&
"Trying to allocate too many items!");
1300 GAIA_ASSERT(
m_nextFreeIdx < m_size &&
"Item recycle list broken!");
1302 auto&
page = ensure_page(index);
1303 const auto slot = slot_index(index);
1305 page.nextFree[
slot] = TItemHandle::IdMask;
1312 auto&
page = ensure_page(index);
1313 const auto slot = slot_index(index);
1316 page.nextFree[
slot] = TItemHandle::IdMask;
1329 GAIA_ASSERT(index < TItemHandle::IdMask &&
"Trying to allocate too many items!");
1332 GAIA_ASSERT(
m_nextFreeIdx < m_size &&
"Item recycle list broken!");
1334 auto&
page = ensure_page(index);
1335 const auto slot = slot_index(index);
1337 page.nextFree[
slot] = TItemHandle::IdMask;
1344 auto&
page = ensure_page(index);
1345 const auto slot = slot_index(index);
1348 page.nextFree[
slot] = TItemHandle::IdMask;
1394 GAIA_ASSERT(
nextFreeItem < m_size &&
"Item recycle list broken!");
Array with variable size of elements of type.
Definition darray_impl.h:27
const_pointer const_iterator
Read-only random-access iterator type.
Definition darray_impl.h:49
darr_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_impl.h:44
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_impl.h:516
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_impl.h:223
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_impl.h:504
core::random_access_iterator_tag iterator_category
Iterator category exposed by the container.
Definition darray_impl.h:51
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_impl.h:542
void clear() noexcept
Removes all elements.
Definition darray_impl.h:449
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
pointer iterator
Mutable random-access iterator type.
Definition darray_impl.h:47
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_impl.h:510
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_impl.h:193
void push_back(const T &arg)
Appends an element.
Definition darray_impl.h:309
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_impl.h:592
Forward iterator used by paged_ilist. Kept outside the container template so the container body stays...
Definition ilist.h:531
GAIA_NODISCARD bool operator!=(const paged_ilist_iterator &other) const
Compares iterator positions and owners.
Definition ilist.h:603
GAIA_NODISCARD bool operator==(const paged_ilist_iterator &other) const
Compares iterator positions and owners.
Definition ilist.h:596
paged_ilist_iterator(owner_pointer pOwner, typename TPagedIList::size_type index)
Definition ilist.h:560
std::conditional_t< IsConst, typename TPagedIList::const_reference, typename TPagedIList::reference > reference
Reference type selected from iterator constness.
Definition ilist.h:548
GAIA_NODISCARD pointer operator->() const
Accesses the current live payload.
Definition ilist.h:573
std::conditional_t< IsConst, typename TPagedIList::const_pointer, typename TPagedIList::pointer > pointer
Pointer type selected from iterator constness.
Definition ilist.h:550
paged_ilist_iterator & operator++()
Advances to the next live payload.
Definition ilist.h:579
typename TPagedIList::value_type value_type
Stored payload type.
Definition ilist.h:545
typename TPagedIList::difference_type difference_type
Type used for iterator distances.
Definition ilist.h:552
GAIA_NODISCARD reference operator*() const
Dereferences the current live payload.
Definition ilist.h:567
paged_ilist_iterator operator++(int)
Advances to the next live payload.
Definition ilist.h:587
Contiguous storage adapter used by ilist by default.
Definition ilist.h:204
void del_item(TListItem &container)
Notifies the storage adapter that an item is being recycled.
Definition ilist.h:213
void add_item(TListItem &&container)
Appends a live item.
Definition ilist.h:207
static TItemHandle make(uint32_t id, uint32_t gen, const TItemHandle &prev)
Rebuilds a handle after its generation changes while preserving packed priority bits.
Definition ilist.h:512
Rebuild policy for implicit-list handles after generation changes.
Definition ilist.h:491
static TItemHandle make(uint32_t id, uint32_t gen, const TItemHandle &prev)
Rebuilds a handle after its generation changes.
Definition ilist.h:497
Generation metadata associated with an item slot.
Definition ilist.h:143
uint32_t gen
Generation ID.
Definition ilist.h:145
Access policy for implicit-list slot index and generation metadata.
Definition ilist.h:97
static void set_idx(TListItem &item, uint32_t value) noexcept
Sets an item's slot index or free-list link.
Definition ilist.h:115
static GAIA_NODISCARD uint32_t gen(const TListItem &item) noexcept
Returns an item's generation.
Definition ilist.h:122
static GAIA_NODISCARD uint32_t idx(const TListItem &item) noexcept
Returns an item's slot index or free-list link.
Definition ilist.h:108
static void set_gen(TListItem &item, uint32_t value) noexcept
Sets an item's generation.
Definition ilist.h:132
Basic item metadata supported by ilist.
Definition ilist.h:141
ilist_item(const ilist_item &other)
Copy-constructs item metadata.
Definition ilist.h:164
uint32_t idx
Allocated items: Index in the list. Deleted items: Index of the next deleted item in the list.
Definition ilist.h:150
ilist_item & operator=(const ilist_item &other)
Copy-assigns item metadata.
Definition ilist.h:171
ItemData data
Item data.
Definition ilist.h:152
ilist_item(ilist_item &&other)
Move-constructs item metadata and invalidates the source metadata.
Definition ilist.h:180
ilist_item & operator=(ilist_item &&other)
Move-assigns item metadata and invalidates the source metadata.
Definition ilist.h:190
ilist_item(uint32_t index, uint32_t generation)
Constructs item metadata for a slot.
Definition ilist.h:158
Implicit list. Rather than with pointers, items.
Definition ilist.h:223
GAIA_NODISCARD const_iterator end() const noexcept
Returns the immutable storage end sentinel.
Definition ilist.h:366
GAIA_NODISCARD size_type size() const noexcept
Returns the total number of allocated slots.
Definition ilist.h:324
GAIA_NODISCARD size_type get_next_free_item() const noexcept
Returns the free-list head.
Definition ilist.h:306
GAIA_NODISCARD const_reference operator[](size_type index) const
Returns an item slot by index.
Definition ilist.h:293
TListItem & free(TItemHandle handle)
Invalidates handle. Every time an item is deallocated its generation is increased by one.
Definition ilist.h:446
size_type m_nextFreeIdx
Index of the next item to recycle.
Definition ilist.h:268
void clear()
Removes all slots and resets the free list.
Definition ilist.h:298
typename internal_storage::difference_type difference_type
Underlying iterator distance type.
Definition ilist.h:238
GAIA_NODISCARD reference operator[](size_type index)
Returns an item slot by index.
Definition ilist.h:287
GAIA_NODISCARD iterator end() noexcept
Returns the mutable storage end sentinel.
Definition ilist.h:360
GAIA_NODISCARD iterator begin() noexcept
Returns a mutable iterator to the first storage slot.
Definition ilist.h:342
GAIA_NODISCARD pointer data() noexcept
Returns contiguous item storage.
Definition ilist.h:274
GAIA_NODISCARD const_pointer data() const noexcept
Returns contiguous item storage.
Definition ilist.h:280
void reserve(size_type cap)
Reserves storage for slots.
Definition ilist.h:378
typename internal_storage::iterator iterator
Mutable storage iterator.
Definition ilist.h:244
typename internal_storage::size_type size_type
Underlying size and index type.
Definition ilist.h:240
size_type m_freeItems
Number of items to recycle.
Definition ilist.h:270
void validate() const
Verifies that the implicit linked list is valid.
Definition ilist.h:464
GAIA_NODISCARD size_type get_free_items() const noexcept
Returns the number of recyclable slots.
Definition ilist.h:312
GAIA_NODISCARD size_type capacity() const noexcept
Returns slot capacity.
Definition ilist.h:336
GAIA_NODISCARD TItemHandle alloc()
Allocates a new item in the list.
Definition ilist.h:415
typename internal_storage::iterator_category iterator_category
Underlying iterator category tag.
Definition ilist.h:248
typename internal_storage::const_iterator const_iterator
Immutable storage iterator.
Definition ilist.h:246
GAIA_NODISCARD size_type item_count() const noexcept
Returns the number of live items.
Definition ilist.h:318
GAIA_NODISCARD bool empty() const noexcept
Checks whether no slots have been allocated.
Definition ilist.h:330
internal_storage m_items
Implicit list items.
Definition ilist.h:266
GAIA_NODISCARD const_iterator cend() const noexcept
Returns the immutable storage end sentinel.
Definition ilist.h:372
GAIA_NODISCARD const_iterator begin() const noexcept
Returns an immutable iterator to the first storage slot.
Definition ilist.h:348
GAIA_NODISCARD const_iterator cbegin() const noexcept
Returns an immutable iterator to the first storage slot.
Definition ilist.h:354
GAIA_NODISCARD TItemHandle alloc(void *ctx)
Allocates a new item in the list.
Definition ilist.h:385
Paged implicit list declaration.
Definition ilist.h:618
static GAIA_NODISCARD constexpr size_type page_capacity() noexcept
Returns the compile-time number of payload slots stored in one page.
Definition ilist.h:831
GAIA_NODISCARD size_type size() const noexcept
Returns the total number of addressable slots in use.
Definition ilist.h:1085
GAIA_NODISCARD reference live_unsafe(size_type index)
Returns a live payload slot without consulting list-wide size metadata.
Definition ilist.h:1172
GAIA_NODISCARD size_type get_free_items() const noexcept
Returns the number of recyclable slots.
Definition ilist.h:1073
GAIA_NODISCARD size_type capacity() const noexcept
Returns the slot capacity represented by the page table.
Definition ilist.h:1097
GAIA_NODISCARD pointer data() noexcept
Reports that paged storage is not globally contiguous.
Definition ilist.h:986
GAIA_NODISCARD pointer try_get(size_type index) noexcept
Attempts to access a live payload.
Definition ilist.h:1216
GAIA_NODISCARD const_pointer data() const noexcept
Reports that paged storage is not globally contiguous.
Definition ilist.h:992
uint32_t size_type
Type used for slot indices and sizes.
Definition ilist.h:632
GAIA_NODISCARD size_type item_count() const noexcept
Returns the number of live payloads.
Definition ilist.h:1079
static GAIA_NODISCARD constexpr size_type page_count_for_capacity(size_type slotCnt) noexcept
Calculates how many pages are needed to address slotCnt slots.
Definition ilist.h:838
void add_free(TItemHandle handle, uint32_t nextFreeIdx)
Restores a free slot with a preassigned id/generation and free-list link.
Definition ilist.h:1258
paged_ilist & operator=(paged_ilist &&other) noexcept
Move-assigns a paged list and leaves the source empty.
Definition ilist.h:961
size_type m_freeItems
Number of slots currently linked through the implicit free-list.
Definition ilist.h:813
GAIA_NODISCARD const_reference operator[](size_type index) const
Returns a live payload by slot index.
Definition ilist.h:1052
GAIA_NODISCARD TItemHandle alloc()
Allocates a new item in the list.
Definition ilist.h:1323
void validate() const
Verifies that the implicit free-list links are well formed.
Definition ilist.h:1387
GAIA_NODISCARD const_iterator cend() const noexcept
Returns the immutable end sentinel.
Definition ilist.h:1136
void clear()
Destroys all live payloads, releases all pages, and resets slot metadata.
Definition ilist.h:1058
GAIA_NODISCARD bool empty() const noexcept
Checks whether no slots are in use.
Definition ilist.h:1091
GAIA_NODISCARD const_iterator begin() const noexcept
Returns an iterator over live payload objects only.
Definition ilist.h:1112
const TListItem * const_pointer
Immutable payload pointer.
Definition ilist.h:628
GAIA_NODISCARD iterator end() noexcept
Returns the mutable end sentinel.
Definition ilist.h:1124
TListItem & reference
Mutable payload reference.
Definition ilist.h:622
GAIA_NODISCARD reference operator[](size_type index)
Returns a live payload by slot index.
Definition ilist.h:1044
GAIA_NODISCARD const_reference payload_unsafe(size_type index) const
Returns a constructed payload slot without consulting shared liveness metadata.
Definition ilist.h:1207
size_type m_nextFreeIdx
Head of the implicit free-list, or TItemHandle::IdMask when no slots are free.
Definition ilist.h:811
TListItem * pointer
Mutable payload pointer.
Definition ilist.h:626
GAIA_NODISCARD TItemHandle alloc(void *ctx)
Allocates a new item in the list.
Definition ilist.h:1291
GAIA_NODISCARD uint32_t generation(size_type index) const noexcept
Returns a slot's generation.
Definition ilist.h:1027
GAIA_NODISCARD const_iterator cbegin() const noexcept
Returns an iterator over live payload objects only.
Definition ilist.h:1118
GAIA_NODISCARD bool has(size_type index) const noexcept
Checks whether a slot contains a live payload.
Definition ilist.h:999
GAIA_NODISCARD const_iterator end() const noexcept
Returns the immutable end sentinel.
Definition ilist.h:1130
GAIA_NODISCARD reference payload_unsafe(size_type index)
Returns a constructed payload slot without consulting shared liveness metadata.
Definition ilist.h:1197
GAIA_NODISCARD TItemHandle handle(size_type index) const noexcept
Returns the handle metadata stored for a slot.
Definition ilist.h:1017
GAIA_NODISCARD const_reference live_unsafe(size_type index) const
Returns a live payload slot without consulting list-wide size metadata.
Definition ilist.h:1185
GAIA_NODISCARD iterator begin() noexcept
Returns an iterator over live payload objects only.
Definition ilist.h:1106
void add_free(size_type index, uint32_t generation, uint32_t nextFreeIdx)
Restores a free slot with a preassigned id/generation and free-list link.
Definition ilist.h:1283
std::ptrdiff_t difference_type
Type used for iterator distances.
Definition ilist.h:630
GAIA_NODISCARD bool has(TItemHandle handle) const noexcept
Checks whether a handle identifies its current live payload.
Definition ilist.h:1010
void reserve(size_type cap)
Reserves page-table capacity for at least cap slots.
Definition ilist.h:1144
paged_ilist_iterator< paged_ilist, false > iterator
Mutable forward iterator over live payloads.
Definition ilist.h:930
void add_live(TListItem &&item)
Restores a live slot with a preassigned id/generation.
Definition ilist.h:1235
paged_ilist_iterator< paged_ilist, true > const_iterator
Immutable forward iterator over live payloads.
Definition ilist.h:932
GAIA_NODISCARD size_type get_next_free_item() const noexcept
Returns the free-list head.
Definition ilist.h:1067
const TListItem & const_reference
Immutable payload reference.
Definition ilist.h:624
GAIA_NODISCARD uint32_t next_free(size_type index) const noexcept
Returns the free-list link stored for a slot.
Definition ilist.h:1034
GAIA_NODISCARD const_pointer try_get(size_type index) const noexcept
Attempts to access a live payload.
Definition ilist.h:1225
void free(TItemHandle handle)
Frees a live item and destroys its payload immediately.
Definition ilist.h:1355
void free_keep_live(TItemHandle handle)
Frees a handle while keeping the payload alive until slot reuse or clear().
Definition ilist.h:1375
void reserve_slot_table(size_type cap)
Ensures the page pointer table can address cap slots without resizing later.
Definition ilist.h:1158
paged_ilist(paged_ilist &&other) noexcept
Move-constructs a paged list and leaves the source empty.
Definition ilist.h:943
static void free_alig(void *ptr)
Releases aligned storage allocated through an adaptor.
Definition mem_alloc.h:291