53 using difference_type = detail::difference_type;
54 using size_type = detail::size_type;
61 using bit_set_iter_type = std::conditional_t<
62 IsFwd,
typename page_data_type::bit_set::iter,
typename page_data_type::bit_set::iter_rev>;
65 bit_set_iter_type m_it;
72 reference operator*()
const {
73 return m_pPage->set_data(*m_it);
75 pointer operator->()
const {
76 return &m_pPage->set_data(*m_it);
89 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
90 return m_pPage == other.m_pPage && m_it == other.m_it;
92 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
93 return m_pPage != other.m_pPage && m_it != other.m_it;
102 using difference_type = detail::difference_type;
103 using size_type = detail::size_type;
110 using bit_set_iter_type = std::conditional_t<
111 IsFwd,
typename page_data_type::bit_set::iter,
typename page_data_type::bit_set::iter_rev>;
114 bit_set_iter_type m_it;
119 value_type operator*()
const {
120 return m_pPage->set_data(*m_it);
122 value_type operator->()
const {
123 return &m_pPage->set_data(*m_it);
145 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
146 return m_pPage == other.m_pPage && m_it == other.m_it;
148 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
149 return m_pPage != other.m_pPage && m_it != other.m_it;
176 static_assert(!std::is_empty_v<T>,
"It only makes sense to use page storage for data types with non-zero size");
179 using value_type = T;
180 using reference = T&;
181 using const_reference =
const T&;
183 using const_pointer =
const T*;
185 using difference_type = detail::difference_type;
186 using size_type = detail::size_type;
188 template <
bool IsFwd>
193 template <
bool IsFwd>
199 static constexpr uint32_t PageCapacity = PageData::PageCapacity;
206 if GAIA_LIKELY (m_pData !=
nullptr)
210 m_pData = mem::AllocHelper::alloc<PageData, Allocator>(1);
213 core::call_ctor_raw_n(data(), PageCapacity);
216 void dtr_data_inter(uint32_t idx)
noexcept {
217 GAIA_ASSERT(!empty());
219 if constexpr (!mem::is_soa_layout_v<T>) {
220 auto* ptr = &data()[idx];
221 core::call_dtor(ptr);
228 void dtr_active_data()
noexcept {
229 if constexpr (!mem::is_soa_layout_v<T>) {
231 auto* ptr = &data()[i];
232 core::call_dtor(ptr);
238 if (m_pData ==
nullptr)
245 m_pData->~PageData();
246 mem::AllocHelper::free<Allocator>(m_pData);
255 if (other.m_pData ==
nullptr) {
265 add_data(i, other.get_data(i));
270 GAIA_ASSERT(core::addressof(other) !=
this);
273 if (other.m_pData ==
nullptr) {
279 if (m_pData !=
nullptr)
287 add_data(i, other.get_data(i));
294 m_pData = other.m_pData;
295 other.m_pData =
nullptr;
299 GAIA_ASSERT(core::addressof(other) !=
this);
303 m_pData = other.m_pData;
304 other.m_pData =
nullptr;
313 GAIA_CLANG_WARNING_PUSH()
315 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
317 GAIA_NODISCARD pointer data()
noexcept {
318 return GAIA_ACC((pointer)&m_pData->
data[0]);
321 GAIA_NODISCARD const_pointer data()
const noexcept {
322 return GAIA_ACC((const_pointer)&m_pData->
data[0]);
325 GAIA_NODISCARD
decltype(
auto) set_data(size_type pos)
noexcept {
327 return view_policy::set(
328 {GAIA_ACC((
typename view_policy::TargetCastType) & m_pData->
data[0]), PageCapacity}, pos);
331 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
333 return view_policy::set(
334 {GAIA_ACC((
typename view_policy::TargetCastType) & m_pData->
data[0]), PageCapacity}, pos);
337 GAIA_NODISCARD
decltype(
auto) get_data(size_type pos)
const noexcept {
339 return view_policy::get(
340 {GAIA_ACC((
typename view_policy::TargetCastType) & m_pData->
data[0]), PageCapacity}, pos);
343 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
345 return view_policy::get(
346 {GAIA_ACC((
typename view_policy::TargetCastType) & m_pData->
data[0]), PageCapacity}, pos);
349 GAIA_CLANG_WARNING_POP()
356 decltype(
auto) add_data(uint32_t idx,
const T& arg) {
359 if constexpr (mem::is_soa_layout_v<T>) {
362 auto* ptr = &set_data(idx);
363 core::call_ctor(ptr, arg);
364 return (reference)(*ptr);
368 decltype(
auto) add_data(uint32_t idx, T&& arg) {
371 if constexpr (mem::is_soa_layout_v<T>) {
372 set_data(idx) = GAIA_MOV(arg);
374 auto* ptr = &set_data(idx);
375 core::call_ctor(ptr, GAIA_MOV(arg));
376 return (reference)(*ptr);
380 template <
typename... Args>
381 decltype(
auto) emplace_data(uint32_t idx, Args&&... args) {
382 m_pData->
header.used.set(idx);
384 if constexpr (mem::is_soa_layout_v<T>) {
385 set_data(idx) = T(GAIA_FWD(args)...);
387 auto* ptr = &set_data(idx);
388 core::call_ctor(ptr, GAIA_FWD(args)...);
389 return (reference)(*ptr);
393 void del_data(uint32_t idx)
noexcept {
401 GAIA_NODISCARD
bool has_data(uint32_t idx)
const noexcept {
405 GAIA_NODISCARD size_type size()
const noexcept {
406 return m_pData ? m_pData->
header.
cnt : 0;
409 GAIA_NODISCARD
bool empty()
const noexcept {
413 GAIA_NODISCARD
decltype(
auto) front()
noexcept {
414 GAIA_ASSERT(!empty());
415 if constexpr (mem::is_soa_layout_v<T>)
418 return (reference)*begin();
421 GAIA_NODISCARD
decltype(
auto) front()
const noexcept {
422 GAIA_ASSERT(!empty());
423 if constexpr (mem::is_soa_layout_v<T>)
426 return (const_reference)*begin();
429 GAIA_NODISCARD
decltype(
auto) back()
noexcept {
430 GAIA_ASSERT(!empty());
431 const auto idx = *m_pData->
header.
mask.rbegin();
432 if constexpr (mem::is_soa_layout_v<T>)
433 return set_data(idx);
435 return (reference)(set_data(idx));
438 GAIA_NODISCARD
decltype(
auto) back()
const noexcept {
439 GAIA_ASSERT(!empty());
440 const auto idx = *m_pData->
header.
mask.rbegin();
441 if constexpr (mem::is_soa_layout_v<T>)
442 return set_data(idx);
444 return (const_reference)set_data(idx);
449 GAIA_NODISCARD
auto begin()
const noexcept {
450 if constexpr (mem::is_soa_layout_v<T>)
456 GAIA_NODISCARD
auto end()
const noexcept {
457 if constexpr (mem::is_soa_layout_v<T>)
463 GAIA_NODISCARD
auto rbegin()
const noexcept {
464 if constexpr (mem::is_soa_layout_v<T>)
471 GAIA_NODISCARD
auto rend()
const noexcept {
472 if constexpr (mem::is_soa_layout_v<T>)
478 GAIA_NODISCARD
bool operator==(
const mem_page& other)
const noexcept {
480 GAIA_ASSERT(m_pData !=
nullptr);
481 GAIA_ASSERT(other.m_pData !=
nullptr);
488 if (!(get_data(i) == other[i]))
493 GAIA_NODISCARD
bool operator!=(
const mem_page& other)
const noexcept {
494 return !operator==(other);
501 using value_type = T;
503 using reference = T&;
504 using difference_type = detail::difference_type;
505 using size_type = detail::size_type;
514 typename page_type::template iterator_base<IsFwd> m_it;
521 if constexpr (!IsFwd) {
522 m_it = m_pPage->rbegin();
523 while (m_it == m_pPage->rend()) {
525 if (m_pPage == m_pPageLast) {
529 m_it = m_pPage->rbegin();
532 m_it = m_pPage->begin();
533 while (m_it == m_pPage->end()) {
535 if (m_pPage == m_pPageLast) {
539 m_it = m_pPage->begin();
544 reference operator*()
const {
545 return m_it.operator*();
547 pointer operator->()
const {
548 return m_it.operator->();
552 if constexpr (!IsFwd) {
554 if (m_it == m_pPage->rend()) {
556 if (m_pPage == m_pPageLast) {
560 m_it = m_pPage->rbegin();
564 if (m_it == m_pPage->end()) {
566 if (m_pPage == m_pPageLast) {
570 m_it = m_pPage->begin();
581 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
582 return m_pPage == other.m_pPage && m_it == other.m_it;
584 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
585 return m_pPage != other.m_pPage || m_it != other.m_it;
591 using value_type = T;
592 using pointer =
const T*;
593 using reference =
const T&;
594 using difference_type = detail::difference_type;
595 using size_type = detail::size_type;
604 typename page_type::template iterator_base<IsFwd> m_it;
611 if constexpr (!IsFwd) {
612 m_it = m_pPage->rbegin();
613 while (m_it == m_pPage->rend()) {
615 if (m_pPage == m_pPageLast) {
619 m_it = m_pPage->rbegin();
622 m_it = m_pPage->begin();
623 while (m_it == m_pPage->end()) {
625 if (m_pPage == m_pPageLast) {
629 m_it = m_pPage->begin();
634 reference operator*()
const {
635 return m_it.operator*();
637 pointer operator->()
const {
638 return m_it.operator->();
642 if constexpr (!IsFwd) {
644 if (m_it == m_pPage->rend()) {
646 if (m_pPage == m_pPageLast) {
650 m_it = m_pPage->rbegin();
654 if (m_it == m_pPage->end()) {
656 if (m_pPage == m_pPageLast) {
660 m_it = m_pPage->begin();
671 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
672 return m_pPage == other.m_pPage && m_it == other.m_it;
674 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
675 return m_pPage != other.m_pPage || m_it != other.m_it;
681 using value_type = T;
684 using difference_type = detail::difference_type;
685 using size_type = detail::size_type;
694 typename page_type::template iterator_soa_base<IsFwd> m_it;
701 if constexpr (!IsFwd) {
702 m_it = m_pPage->rbegin();
703 while (m_it == m_pPage->rend()) {
704 if (m_pPage == m_pPageLast)
707 m_it = m_pPage->rbegin();
710 m_it = m_pPage->begin();
711 while (m_it == m_pPage->end()) {
712 if (m_pPage == m_pPageLast)
715 m_it = m_pPage->begin();
720 value_type operator*()
const {
721 return m_it.operator*();
723 value_type operator->()
const {
724 return m_it.operator->();
728 if constexpr (!IsFwd) {
730 while (m_it == m_pPage->rend()) {
732 m_it = m_pPage->rbegin();
736 while (m_it == m_pPage->end()) {
738 m_it = m_pPage->begin();
749 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
750 return m_pPage == other.m_pPage && m_it == other.m_it;
752 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
753 return m_pPage != other.m_pPage || m_it != other.m_it;
759 using value_type = T;
762 using difference_type = detail::difference_type;
763 using size_type = detail::size_type;
772 typename page_type::template iterator_soa_base<IsFwd> m_it;
778 m_pPage(pPage), m_pPageLast(pPageLast) {
780 if constexpr (!IsFwd) {
781 m_it = m_pPage->rbegin();
782 while (m_it == m_pPage->rend()) {
783 if (m_pPage == m_pPageLast)
786 m_it = m_pPage->rbegin();
789 m_it = m_pPage->begin();
790 while (m_it == m_pPage->end()) {
791 if (m_pPage == m_pPageLast)
794 m_it = m_pPage->begin();
799 value_type operator*()
const {
800 return m_it.operator*();
802 value_type operator->()
const {
803 return m_it.operator->();
807 if constexpr (!IsFwd) {
809 while (m_it == m_pPage->rend()) {
811 m_it = m_pPage->rbegin();
815 while (m_it == m_pPage->end()) {
817 m_it = m_pPage->begin();
828 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
829 return m_pPage == other.m_pPage && m_it == other.m_it;
831 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
832 return m_pPage != other.m_pPage || m_it != other.m_it;
842 using value_type = T;
843 using reference = T&;
844 using const_reference =
const T&;
846 using const_pointer =
const T*;
848 using difference_type = detail::difference_type;
849 using size_type = detail::size_type;
856 static constexpr uint32_t PageCapacity = page_type::PageCapacity;
869 constexpr static uint32_t PageMask = PageCapacity - 1;
870 constexpr static uint32_t ToPageIndex = core::count_bits(PageMask);
875 uint32_t m_itemCnt = 0;
877 void try_grow(uint32_t pid) {
879 if (pid >= m_pages.size())
880 m_pages.resize(pid + 1);
890 m_pages = other.m_pages;
891 m_itemCnt = other.m_itemCnt;
895 GAIA_ASSERT(core::addressof(other) !=
this);
897 m_pages = other.m_pages;
898 m_itemCnt = other.m_itemCnt;
903 m_pages = GAIA_MOV(other.m_pages);
904 m_itemCnt = other.m_itemCnt;
910 GAIA_ASSERT(core::addressof(other) !=
this);
912 m_pages = GAIA_MOV(other.m_pages);
913 m_itemCnt = other.m_itemCnt;
922 GAIA_CLANG_WARNING_PUSH()
924 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
926 GAIA_NODISCARD
decltype(
auto)
operator[](page_storage_id
id)
noexcept {
927 GAIA_ASSERT(
has(
id));
928 const auto pid = size_type(
id >> ToPageIndex);
929 const auto did = size_type(
id & PageMask);
930 auto& page = m_pages[pid];
931 return view_policy::set({(
typename view_policy::TargetCastType)page.data(), PageCapacity}, did);
934 GAIA_NODISCARD
decltype(
auto)
operator[](page_storage_id
id)
const noexcept {
935 GAIA_ASSERT(
has(
id));
936 const auto pid = size_type(
id >> ToPageIndex);
937 const auto did = size_type(
id & PageMask);
938 auto& page = m_pages[pid];
939 return view_policy::get({(
typename view_policy::TargetCastType)page.data(), PageCapacity}, did);
942 GAIA_CLANG_WARNING_POP()
946 GAIA_NODISCARD
bool has(page_storage_id
id) const noexcept {
947 const auto pid = size_type(
id >> ToPageIndex);
948 if (pid >= m_pages.size())
951 const auto did = size_type(
id & PageMask);
952 const auto val = page_data_type::bit_set::BitCount;
953 return did < val && m_pages[pid].has_data(did);
958 GAIA_NODISCARD
bool has(
const T& arg)
const noexcept {
960 GAIA_ASSERT(
id != detail::InvalidPageStorageId);
967 template <
typename TType>
968 decltype(
auto)
add(TType&& arg) {
971 if constexpr (mem::is_soa_layout_v<TType>)
974 const auto pid = size_type(
id >> ToPageIndex);
975 const auto did = size_type(
id & PageMask);
976 auto& page = m_pages[pid];
977 return page.set_data(did);
981 const auto pid = size_type(
id >> ToPageIndex);
982 const auto did = size_type(
id & PageMask);
986 auto& page = m_pages[pid];
987 if constexpr (mem::is_soa_layout_v<TType>)
988 page.add_data(did, GAIA_FWD(arg));
990 return page.add_data(did, GAIA_FWD(arg));
996 decltype(
auto)
set(page_storage_id
id) {
997 GAIA_ASSERT(
has(
id));
999 const auto pid = uint32_t(
id >> ToPageIndex);
1000 const auto did = uint32_t(
id & PageMask);
1002 auto& page = m_pages[pid];
1003 return page.set_data(did);
1008 void del(page_storage_id
id)
noexcept {
1009 GAIA_ASSERT(!
empty());
1010 GAIA_ASSERT(
id != detail::InvalidPageStorageId);
1015 const auto pid = uint32_t(
id >> ToPageIndex);
1016 const auto did = uint32_t(
id & PageMask);
1018 auto& page = m_pages[pid];
1025 void del(
const T& arg)
noexcept {
1037 GAIA_NODISCARD size_type
size() const noexcept {
1042 GAIA_NODISCARD
bool empty() const noexcept {
1043 return m_itemCnt == 0;
1046 GAIA_NODISCARD
decltype(
auto) front() noexcept {
1047 GAIA_ASSERT(!
empty());
1048 return (reference)*begin();
1051 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
1052 GAIA_ASSERT(!
empty());
1053 return (const_reference)*begin();
1056 GAIA_NODISCARD
decltype(
auto) back() noexcept {
1057 GAIA_ASSERT(!
empty());
1058 return (reference)*rbegin();
1061 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
1062 GAIA_ASSERT(!
empty());
1063 return (const_reference)*rbegin();
1066 GAIA_NODISCARD
auto begin() noexcept {
1067 GAIA_ASSERT(!
empty());
1068 return iterator(m_pages.data(), m_pages.data() + m_pages.size());
1071 GAIA_NODISCARD
auto begin() const noexcept {
1072 GAIA_ASSERT(!
empty());
1073 return const_iterator(m_pages.data(), m_pages.data() + m_pages.size());
1076 GAIA_NODISCARD
auto cbegin() const noexcept {
1077 GAIA_ASSERT(!
empty());
1078 return const_iterator(m_pages.data(), m_pages.data() + m_pages.size());
1081 GAIA_NODISCARD
auto end() noexcept {
1082 GAIA_ASSERT(!
empty());
1083 return iterator(m_pages.data() + m_pages.size());
1086 GAIA_NODISCARD
auto end() const noexcept {
1087 GAIA_ASSERT(!
empty());
1088 return const_iterator(m_pages.data() + m_pages.size());
1091 GAIA_NODISCARD
auto cend() const noexcept {
1092 GAIA_ASSERT(!
empty());
1093 return const_iterator(m_pages.data() + m_pages.size());
1096 GAIA_NODISCARD
auto rbegin() noexcept {
1097 GAIA_ASSERT(!
empty());
1098 return iterator_reverse(m_pages.data() + m_pages.size() - 1, m_pages.data() - 1);
1101 GAIA_NODISCARD
auto rbegin() const noexcept {
1102 GAIA_ASSERT(!
empty());
1103 return const_iterator_reverse(m_pages.data() + m_pages.size() - 1, m_pages.data() - 1);
1106 GAIA_NODISCARD
auto crbegin() const noexcept {
1107 GAIA_ASSERT(!
empty());
1108 return const_iterator_reverse(m_pages.data() + m_pages.size() - 1, m_pages.data() - 1);
1111 GAIA_NODISCARD
auto rend() noexcept {
1112 GAIA_ASSERT(!
empty());
1113 return iterator_reverse(m_pages.data() - 1);
1116 GAIA_NODISCARD
auto rend() const noexcept {
1117 GAIA_ASSERT(!
empty());
1118 return const_iterator_reverse(m_pages.data() - 1);
1121 GAIA_NODISCARD
auto crend() const noexcept {
1122 GAIA_ASSERT(!
empty());
1123 return const_iterator_reverse(m_pages.data() - 1);
1126 GAIA_NODISCARD
bool operator==(
const page_storage& other)
const noexcept {
1127 return m_pages == other.m_pages;
1130 GAIA_NODISCARD
bool operator!=(
const page_storage& other)
const noexcept {
1131 return !operator==(other);
Definition paged_storage.h:175
Array with variable size of elements of type.
Definition paged_storage.h:840
decltype(auto) add(TType &&arg)
Inserts the item arg into the storage.
Definition paged_storage.h:968
void clear()
Clears the storage.
Definition paged_storage.h:1031
void del(const T &arg) noexcept
Removes the item arg from the storage.
Definition paged_storage.h:1025
decltype(auto) set(page_storage_id id)
Update the record at the index id.
Definition paged_storage.h:996
GAIA_NODISCARD size_type size() const noexcept
Returns the number of items inserted into the storage.
Definition paged_storage.h:1037
GAIA_NODISCARD bool empty() const noexcept
Checks if the storage is empty (no items inserted)
Definition paged_storage.h:1042
GAIA_NODISCARD bool has(const T &arg) const noexcept
Checks if an item arg exists within the storage.
Definition paged_storage.h:958
void del(page_storage_id id) noexcept
Removes the item at the index id from the storage.
Definition paged_storage.h:1008
GAIA_NODISCARD bool has(page_storage_id id) const noexcept
Checks if an item with a given page id exists.
Definition paged_storage.h:946
Definition paged_storage.h:758
Definition paged_storage.h:590
Definition paged_storage.h:154
PageHeader header
Page header.
Definition paged_storage.h:169
mem::raw_data_holder< T, AllocatedBytes > data
Page data.
Definition paged_storage.h:171
Definition paged_storage.h:680
Definition paged_storage.h:500
Definition paged_storage.h:37