128class hive :
private allocator_type
130 typedef std::conditional_t<(
sizeof(element_type) > 10 ||
alignof(element_type) > 10), uint_least16_t, uint_least8_t> skipfield_type;
135 typedef typename std::allocator_traits<allocator_type>::size_type
size_type;
136 typedef typename std::allocator_traits<allocator_type>::difference_type
difference_type;
139 typedef typename std::allocator_traits<allocator_type>::pointer
pointer;
140 typedef typename std::allocator_traits<allocator_type>::const_pointer
const_pointer;
163 struct alignas(alignof(element_type)) aligned_element_struct
167 (
sizeof(element_type) < (
sizeof(skipfield_type) * 2)) ?
168 ((
sizeof(skipfield_type) * 2) <
alignof(element_type) ?
alignof(element_type) : (
sizeof(skipfield_type) * 2)) :
169 ((
sizeof(element_type) <
alignof(element_type)) ?
alignof(element_type) :
sizeof(element_type))
175 struct alignas(alignof(element_type)) aligned_allocation_struct
177 char data[
alignof(element_type)];
182 static size_type get_aligned_block_capacity(
const skipfield_type elements_per_group)
noexcept
184 return ((elements_per_group * (
sizeof(aligned_element_struct) +
sizeof(skipfield_type))) +
sizeof(skipfield_type) +
sizeof(aligned_allocation_struct) - 1) /
sizeof(aligned_allocation_struct);
189 template <
class destination_po
inter_type,
class source_po
inter_type>
190 static constexpr destination_pointer_type pointer_cast(
const source_pointer_type source_pointer)
noexcept
192 if constexpr (std::is_trivial<destination_pointer_type>::value)
194 return reinterpret_cast<destination_pointer_type
>(std::to_address(source_pointer));
198 return destination_pointer_type(std::to_address(source_pointer));
206 struct item_index_tuple;
209 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<aligned_element_struct> aligned_allocator_type;
210 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<group> group_allocator_type;
211 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<skipfield_type> skipfield_allocator_type;
212 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<aligned_allocation_struct> aligned_struct_allocator_type;
213 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<item_index_tuple> tuple_allocator_type;
214 typedef typename std::allocator_traits<allocator_type>::template rebind_alloc<unsigned char> uchar_allocator_type;
216 typedef typename std::allocator_traits<aligned_allocator_type>::pointer aligned_pointer_type;
217 typedef typename std::allocator_traits<group_allocator_type>::pointer group_pointer_type;
218 typedef typename std::allocator_traits<skipfield_allocator_type>::pointer skipfield_pointer_type;
219 typedef typename std::allocator_traits<aligned_struct_allocator_type>::pointer aligned_struct_pointer_type;
220 typedef typename std::allocator_traits<tuple_allocator_type>::pointer tuple_pointer_type;
226 skipfield_pointer_type skipfield;
227 group_pointer_type next_group;
228 aligned_pointer_type
const elements;
229 group_pointer_type previous_group;
230 skipfield_type free_list_head;
231 const skipfield_type capacity;
233 group_pointer_type erasures_list_next_group, erasures_list_previous_group;
238 group(aligned_struct_allocator_type &aligned_struct_allocator,
const skipfield_type elements_per_group, group_pointer_type
const previous):
240 elements(pointer_cast<aligned_pointer_type>(
std::allocator_traits<aligned_struct_allocator_type>::allocate(aligned_struct_allocator, get_aligned_block_capacity(elements_per_group), (previous == nullptr) ? 0 : previous->elements))),
241 previous_group(previous),
242 free_list_head(
std::numeric_limits<skipfield_type>::max()),
243 capacity(elements_per_group),
245 erasures_list_next_group(nullptr),
246 erasures_list_previous_group(nullptr),
247 group_number((previous == nullptr) ? 0 : previous->group_number + 1u)
249 skipfield = pointer_cast<skipfield_pointer_type>(elements + elements_per_group);
250 std::memset(
static_cast<void *
>(std::to_address(skipfield)), 0,
sizeof(skipfield_type) * (
static_cast<size_type>(elements_per_group) + 1u));
255 void reset(
const skipfield_type increment,
const group_pointer_type next,
const group_pointer_type previous,
const size_type group_num)
noexcept
258 free_list_head = std::numeric_limits<skipfield_type>::max();
259 previous_group = previous;
261 erasures_list_next_group =
nullptr;
262 erasures_list_previous_group =
nullptr;
263 group_number = group_num;
265 std::memset(
static_cast<void *
>(std::to_address(skipfield)), 0,
sizeof(skipfield_type) *
static_cast<size_type>(capacity));
273 iterator end_iterator, begin_iterator;
274 group_pointer_type erasure_groups_head,
277 skipfield_type min_block_capacity, max_block_capacity;
279 group_allocator_type group_allocator;
280 aligned_struct_allocator_type aligned_struct_allocator;
281 skipfield_allocator_type skipfield_allocator;
282 tuple_allocator_type tuple_allocator;
287 static constexpr skipfield_type default_min_block_capacity() noexcept
289 constexpr skipfield_type adaptive_size =
static_cast<skipfield_type
>(((
sizeof(
hive) +
sizeof(group)) * 2) /
sizeof(aligned_element_struct));
290 constexpr skipfield_type max_block_capacity = default_max_block_capacity();
291 return (8 > adaptive_size) ? 8 : (adaptive_size > max_block_capacity) ? max_block_capacity : adaptive_size;
297 static constexpr skipfield_type default_max_block_capacity() noexcept
299 return static_cast<skipfield_type
>((std::numeric_limits<skipfield_type>::max() > 8192u) ? 8192u :
std::numeric_limits<skipfield_type>::max());
304 static constexpr hive_limits default_block_capacity_limits() noexcept
306 return hive_limits(
static_cast<size_t>(default_min_block_capacity()),
static_cast<size_t>(default_max_block_capacity()));
311 void check_capacities_conformance(
const hive_limits capacities)
const
315 if (capacities.min < hard_capacities.min || capacities.min > capacities.max || capacities.max > hard_capacities.max)
317 #ifdef PLF_EXCEPTIONS_SUPPORT
318 throw std::length_error(
"Supplied memory block capacity limits are either invalid or outside of block_capacity_hard_limits()");
327 void blank() noexcept
329 if constexpr (std::is_standard_layout<hive>::value && std::allocator_traits<allocator_type>::is_always_equal::value && std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
331 std::memset(
static_cast<void *
>(
this), 0, offsetof(
hive, min_block_capacity));
335 end_iterator.group_pointer =
nullptr;
336 end_iterator.element_pointer =
nullptr;
337 end_iterator.skipfield_pointer =
nullptr;
338 begin_iterator.group_pointer =
nullptr;
339 begin_iterator.element_pointer =
nullptr;
340 begin_iterator.skipfield_pointer =
nullptr;
341 erasure_groups_head =
nullptr;
342 unused_groups_head =
nullptr;
354 explicit hive(
const allocator_type &alloc)
noexcept:
355 allocator_type(alloc),
356 erasure_groups_head(
nullptr),
357 unused_groups_head(
nullptr),
360 min_block_capacity(default_min_block_capacity()),
361 max_block_capacity(default_max_block_capacity()),
362 group_allocator(*
this),
363 aligned_struct_allocator(*
this),
364 skipfield_allocator(*
this),
365 tuple_allocator(*
this)
370 constexpr hive() noexcept(noexcept(allocator_type())) :
371 hive(allocator_type())
377 allocator_type(alloc),
378 erasure_groups_head(nullptr),
379 unused_groups_head(nullptr),
382 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
383 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
384 group_allocator(*this),
385 aligned_struct_allocator(*this),
386 skipfield_allocator(*this),
387 tuple_allocator(*this)
389 check_capacities_conformance(block_limits);
395 hive(block_limits, allocator_type())
402 hive(
const hive &source,
const std::type_identity_t<allocator_type> &alloc):
403 allocator_type(alloc),
404 erasure_groups_head(nullptr),
405 unused_groups_head(nullptr),
408 min_block_capacity(static_cast<skipfield_type>((source.min_block_capacity > source.total_size) ? source.min_block_capacity : ((source.total_size > source.max_block_capacity) ? source.max_block_capacity : source.total_size))),
409 max_block_capacity(source.max_block_capacity),
410 group_allocator(*this),
411 aligned_struct_allocator(*this),
412 skipfield_allocator(*this),
413 tuple_allocator(*this)
415 range_assign(source.begin_iterator, source.total_size);
416 min_block_capacity = source.min_block_capacity;
422 hive(source,
std::allocator_traits<allocator_type>::select_on_container_copy_construction(source))
429 hive(
hive &&source,
const std::type_identity_t<allocator_type> &alloc):
430 allocator_type(alloc),
431 end_iterator(
std::move(source.end_iterator)),
432 begin_iterator(
std::move(source.begin_iterator)),
433 erasure_groups_head(
std::move(source.erasure_groups_head)),
434 unused_groups_head(
std::move(source.unused_groups_head)),
435 total_size(source.total_size),
436 total_capacity(source.total_capacity),
437 min_block_capacity(source.min_block_capacity),
438 max_block_capacity(source.max_block_capacity),
439 group_allocator(*this),
440 aligned_struct_allocator(*this),
441 skipfield_allocator(*this),
442 tuple_allocator(*this)
444 assert(&source !=
this);
451 allocator_type(std::move(
static_cast<allocator_type &
>(source))),
452 end_iterator(std::move(source.end_iterator)),
453 begin_iterator(std::move(source.begin_iterator)),
454 erasure_groups_head(std::move(source.erasure_groups_head)),
455 unused_groups_head(std::move(source.unused_groups_head)),
456 total_size(source.total_size),
457 total_capacity(source.total_capacity),
458 min_block_capacity(source.min_block_capacity),
459 max_block_capacity(source.max_block_capacity),
460 group_allocator(*
this),
461 aligned_struct_allocator(*
this),
462 skipfield_allocator(*
this),
463 tuple_allocator(*
this)
465 assert(&source !=
this);
473 hive(
const size_type fill_number,
const element_type &element,
const hive_limits block_limits,
const allocator_type &alloc = allocator_type()):
474 allocator_type(alloc),
475 erasure_groups_head(nullptr),
476 unused_groups_head(nullptr),
479 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
480 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
481 group_allocator(*this),
482 aligned_struct_allocator(*this),
483 skipfield_allocator(*this),
484 tuple_allocator(*this)
486 check_capacities_conformance(block_limits);
487 assign(fill_number, element);
491 hive(
const size_type fill_number,
const element_type &element,
const allocator_type &alloc = allocator_type()) :
492 hive(fill_number, element, default_block_capacity_limits(), alloc)
500 allocator_type(alloc),
501 erasure_groups_head(nullptr),
502 unused_groups_head(nullptr),
505 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
506 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
507 group_allocator(*this),
508 aligned_struct_allocator(*this),
509 skipfield_allocator(*this),
510 tuple_allocator(*this)
512 check_capacities_conformance(block_limits);
513 assign(fill_number, element_type());
518 hive(
const size_type fill_number,
const allocator_type &alloc = allocator_type()):
519 hive(fill_number, default_block_capacity_limits(), alloc)
526 template<
typename iterator_type>
527 hive(
const typename std::enable_if_t<!std::numeric_limits<iterator_type>::is_integer, iterator_type> &first,
const iterator_type &last,
const hive_limits block_limits,
const allocator_type &alloc = allocator_type()):
528 allocator_type(alloc),
529 erasure_groups_head(nullptr),
530 unused_groups_head(nullptr),
533 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
534 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
535 group_allocator(*this),
536 aligned_struct_allocator(*this),
537 skipfield_allocator(*this),
538 tuple_allocator(*this)
540 check_capacities_conformance(block_limits);
541 assign<iterator_type>(first, last);
546 template<
typename iterator_type>
547 hive(
const typename std::enable_if_t<!std::numeric_limits<iterator_type>::is_integer, iterator_type> &first,
const iterator_type &last,
const allocator_type &alloc = allocator_type()):
548 hive(first, last, default_block_capacity_limits(), alloc)
555 hive(
const std::initializer_list<element_type> &element_list,
const hive_limits block_limits,
const allocator_type &alloc = allocator_type()):
556 allocator_type(alloc),
557 erasure_groups_head(nullptr),
558 unused_groups_head(nullptr),
561 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
562 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
563 group_allocator(*this),
564 aligned_struct_allocator(*this),
565 skipfield_allocator(*this),
566 tuple_allocator(*this)
568 check_capacities_conformance(block_limits);
569 range_assign(element_list.begin(),
static_cast<size_type>(element_list.size()));
574 hive(
const std::initializer_list<element_type> &element_list,
const allocator_type &alloc = allocator_type()):
575 hive(element_list, default_block_capacity_limits(), alloc)
582 template<
class range_type>
583 requires std::ranges::range<range_type>
585 allocator_type(alloc),
586 erasure_groups_head(nullptr),
587 unused_groups_head(nullptr),
590 min_block_capacity(static_cast<skipfield_type>(block_limits.min)),
591 max_block_capacity(static_cast<skipfield_type>(block_limits.max)),
592 group_allocator(*this),
593 aligned_struct_allocator(*this),
594 skipfield_allocator(*this),
595 tuple_allocator(*this)
597 check_capacities_conformance(block_limits);
598 range_assign(std::ranges::begin(rg),
static_cast<size_type>(std::ranges::distance(rg)));
603 template<
class range_type>
604 requires std::ranges::range<range_type>
606 hive(
plf::ranges::from_range,
std::move(rg), default_block_capacity_limits(), alloc)
615 return begin_iterator;
622 return begin_iterator;
643 return begin_iterator;
657 return (end_iterator.group_pointer !=
nullptr) ? ++
reverse_iterator(end_iterator.group_pointer, end_iterator.element_pointer, end_iterator.skipfield_pointer) :
reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
671 return reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
685 return (end_iterator.group_pointer !=
nullptr) ? ++
const_reverse_iterator(end_iterator.group_pointer, end_iterator.element_pointer, end_iterator.skipfield_pointer) :
const_reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
692 return const_reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
707 group_pointer_type allocate_new_group(
const skipfield_type elements_per_group, group_pointer_type
const previous =
nullptr)
709 group_pointer_type
const new_group = std::allocator_traits<group_allocator_type>::allocate(group_allocator, 1, previous);
711 #ifdef PLF_EXCEPTIONS_SUPPORT
714 std::allocator_traits<group_allocator_type>::construct(group_allocator, new_group, aligned_struct_allocator, elements_per_group, previous);
718 std::allocator_traits<group_allocator_type>::deallocate(group_allocator, new_group, 1);
722 std::allocator_traits<group_allocator_type>::construct(group_allocator, new_group, aligned_struct_allocator, elements_per_group, previous);
731 void deallocate_group(group_pointer_type
const the_group)
noexcept
733 std::allocator_traits<aligned_struct_allocator_type>::deallocate(aligned_struct_allocator, pointer_cast<aligned_struct_pointer_type>(the_group->elements), get_aligned_block_capacity(the_group->capacity));
734 std::allocator_traits<group_allocator_type>::deallocate(group_allocator, the_group, 1);
739 constexpr void destroy_element(
const aligned_pointer_type element)
noexcept
741 if constexpr (!std::is_trivially_destructible<element_type>::value)
743 std::allocator_traits<allocator_type>::destroy(*
this, pointer_cast<pointer>(element));
749 void destroy_group(
const aligned_pointer_type end_pointer)
noexcept
751 if constexpr (!std::is_trivially_destructible<element_type>::value)
755 destroy_element(begin_iterator.element_pointer);
756 begin_iterator.element_pointer +=
static_cast<size_type>(*++begin_iterator.skipfield_pointer) + 1u;
757 begin_iterator.skipfield_pointer += *begin_iterator.skipfield_pointer;
758 }
while(begin_iterator.element_pointer != end_pointer);
761 deallocate_group(begin_iterator.group_pointer);
766 void destroy_all_data() noexcept
768 if (begin_iterator.group_pointer !=
nullptr)
770 end_iterator.group_pointer->next_group = unused_groups_head;
772 if constexpr (!std::is_trivially_destructible<element_type>::value)
776 while (begin_iterator.group_pointer != end_iterator.group_pointer)
778 const group_pointer_type next_group = begin_iterator.group_pointer->next_group;
779 destroy_group(pointer_cast<aligned_pointer_type>(begin_iterator.group_pointer->skipfield));
780 begin_iterator.group_pointer = next_group;
781 begin_iterator.element_pointer = next_group->elements + *(next_group->skipfield);
782 begin_iterator.skipfield_pointer = next_group->skipfield + *(next_group->skipfield);
785 destroy_group(end_iterator.element_pointer);
786 begin_iterator.group_pointer = unused_groups_head;
790 while (begin_iterator.group_pointer !=
nullptr)
792 const group_pointer_type next_group = begin_iterator.group_pointer->next_group;
793 deallocate_group(begin_iterator.group_pointer);
794 begin_iterator.group_pointer = next_group;
801 void initialize(
const skipfield_type first_group_size)
803 end_iterator.group_pointer = begin_iterator.group_pointer = allocate_new_group(first_group_size);
804 end_iterator.element_pointer = begin_iterator.element_pointer = begin_iterator.group_pointer->elements;
805 end_iterator.skipfield_pointer = begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield;
806 total_capacity = first_group_size;
811 void edit_free_list(skipfield_pointer_type
const location,
const skipfield_type value)
noexcept
813 std::allocator_traits<skipfield_allocator_type>::destroy(skipfield_allocator, location);
814 std::allocator_traits<skipfield_allocator_type>::construct(skipfield_allocator, location, value);
819 void edit_free_list_prev(aligned_pointer_type
const location,
const skipfield_type value)
noexcept
821 edit_free_list(pointer_cast<skipfield_pointer_type>(location), value);
826 void edit_free_list_next(aligned_pointer_type
const location,
const skipfield_type value)
noexcept
828 edit_free_list(pointer_cast<skipfield_pointer_type>(location) + 1, value);
833 void edit_free_list_head(aligned_pointer_type
const location,
const skipfield_type value)
noexcept
835 skipfield_pointer_type
const converted_location = pointer_cast<skipfield_pointer_type>(location);
836 edit_free_list(converted_location, value);
837 edit_free_list(converted_location + 1, std::numeric_limits<skipfield_type>::max());
842 void update_skipblock(
const iterator &new_location,
const skipfield_type prev_free_list_index)
noexcept
844 const skipfield_type new_value =
static_cast<skipfield_type
>(*(new_location.skipfield_pointer) - 1);
849 *(new_location.skipfield_pointer + new_value) = *(new_location.skipfield_pointer + 1) = new_value;
852 ++(erasure_groups_head->free_list_head);
854 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
856 edit_free_list_next(new_location.group_pointer->elements + prev_free_list_index, erasure_groups_head->free_list_head);
859 edit_free_list_head(new_location.element_pointer + 1, prev_free_list_index);
863 erasure_groups_head->free_list_head = prev_free_list_index;
865 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
867 edit_free_list_next(new_location.group_pointer->elements + prev_free_list_index, std::numeric_limits<skipfield_type>::max());
871 erasure_groups_head = erasure_groups_head->erasures_list_next_group;
875 *(new_location.skipfield_pointer) = 0;
876 ++(new_location.group_pointer->size);
878 if (new_location.group_pointer == begin_iterator.group_pointer && new_location.element_pointer < begin_iterator.element_pointer)
880 begin_iterator = new_location;
888 void reset() noexcept
896 void update_subsequent_group_numbers(
size_type current_group_number, group_pointer_type update_group)
noexcept
900 update_group->group_number = current_group_number++;
901 update_group = update_group->next_group;
902 }
while (update_group !=
nullptr);
907 void reset_group_numbers() noexcept
909 update_subsequent_group_numbers(0, begin_iterator.group_pointer);
914 void reset_group_numbers_if_necessary() noexcept
916 if (end_iterator.group_pointer->group_number == std::numeric_limits<size_type>::max())
918 reset_group_numbers();
924 group_pointer_type reuse_unused_group() noexcept
926 group_pointer_type
const next_group = unused_groups_head;
927 unused_groups_head = next_group->next_group;
928 reset_group_numbers_if_necessary();
929 next_group->reset(1,
nullptr, end_iterator.group_pointer, end_iterator.group_pointer->group_number + 1u);
940 if (end_iterator.element_pointer !=
nullptr)
942 if (erasure_groups_head ==
nullptr)
944 if (end_iterator.element_pointer != pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield))
946 const iterator return_iterator = end_iterator;
948 #ifdef PLF_EXCEPTIONS_SUPPORT
949 if constexpr (!std::is_nothrow_copy_constructible<element_type>::value)
951 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), element);
952 ++end_iterator.element_pointer;
957 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), element);
960 ++(end_iterator.group_pointer->size);
961 ++end_iterator.skipfield_pointer;
964 return return_iterator;
967 group_pointer_type next_group;
969 if (unused_groups_head ==
nullptr)
971 const skipfield_type new_group_size = (total_size < static_cast<size_type>(max_block_capacity)) ?
static_cast<skipfield_type
>(total_size) : max_block_capacity;
972 reset_group_numbers_if_necessary();
973 next_group = allocate_new_group(new_group_size, end_iterator.group_pointer);
975 #ifdef PLF_EXCEPTIONS_SUPPORT
976 if constexpr (!std::is_nothrow_copy_constructible<element_type>::value)
980 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), element);
984 deallocate_group(next_group);
991 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), element);
994 total_capacity += new_group_size;
998 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(unused_groups_head->elements), element);
999 next_group = reuse_unused_group();
1002 end_iterator.group_pointer->next_group = next_group;
1003 end_iterator.group_pointer = next_group;
1004 end_iterator.element_pointer = next_group->elements + 1;
1005 end_iterator.skipfield_pointer = next_group->skipfield + 1;
1008 return iterator(next_group, next_group->elements, next_group->skipfield);
1012 iterator new_location(erasure_groups_head, erasure_groups_head->elements + erasure_groups_head->free_list_head, erasure_groups_head->skipfield + erasure_groups_head->free_list_head);
1015 const skipfield_type prev_free_list_index = *pointer_cast<skipfield_pointer_type>(new_location.element_pointer);
1016 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(new_location.element_pointer), element);
1017 update_skipblock(new_location, prev_free_list_index);
1019 return new_location;
1024 initialize(min_block_capacity);
1026 #ifdef PLF_EXCEPTIONS_SUPPORT
1027 if constexpr (!std::is_nothrow_copy_constructible<element_type>::value)
1031 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), element);
1042 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), element);
1045 ++end_iterator.skipfield_pointer;
1047 return begin_iterator;
1055 if (end_iterator.element_pointer !=
nullptr)
1057 if (erasure_groups_head ==
nullptr)
1059 if (end_iterator.element_pointer != pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield))
1061 const iterator return_iterator = end_iterator;
1063 #ifdef PLF_EXCEPTIONS_SUPPORT
1064 if constexpr (!std::is_nothrow_move_constructible<element_type>::value)
1066 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), std::move(element));
1067 ++end_iterator.element_pointer;
1072 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::move(element));
1075 ++(end_iterator.group_pointer->size);
1076 ++end_iterator.skipfield_pointer;
1079 return return_iterator;
1082 group_pointer_type next_group;
1084 if (unused_groups_head ==
nullptr)
1086 const skipfield_type new_group_size = (total_size < static_cast<size_type>(max_block_capacity)) ?
static_cast<skipfield_type
>(total_size) : max_block_capacity;
1087 reset_group_numbers_if_necessary();
1088 next_group = allocate_new_group(new_group_size, end_iterator.group_pointer);
1090 #ifdef PLF_EXCEPTIONS_SUPPORT
1091 if constexpr (!std::is_nothrow_move_constructible<element_type>::value)
1095 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), std::move(element));
1099 deallocate_group(next_group);
1106 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), std::move(element));
1109 total_capacity += new_group_size;
1113 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(unused_groups_head->elements), std::move(element));
1114 next_group = reuse_unused_group();
1117 end_iterator.group_pointer->next_group = next_group;
1118 end_iterator.group_pointer = next_group;
1119 end_iterator.element_pointer = next_group->elements + 1;
1120 end_iterator.skipfield_pointer = next_group->skipfield + 1;
1123 return iterator(next_group, next_group->elements, next_group->skipfield);
1127 iterator new_location(erasure_groups_head, erasure_groups_head->elements + erasure_groups_head->free_list_head, erasure_groups_head->skipfield + erasure_groups_head->free_list_head);
1129 const skipfield_type prev_free_list_index = *pointer_cast<skipfield_pointer_type>(new_location.element_pointer);
1130 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(new_location.element_pointer), std::move(element));
1131 update_skipblock(new_location, prev_free_list_index);
1133 return new_location;
1138 initialize(min_block_capacity);
1140 #ifdef PLF_EXCEPTIONS_SUPPORT
1141 if constexpr (!std::is_nothrow_move_constructible<element_type>::value)
1145 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::move(element));
1156 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::move(element));
1159 ++end_iterator.skipfield_pointer;
1161 return begin_iterator;
1167 template<
typename... arguments>
1170 if (end_iterator.element_pointer !=
nullptr)
1172 if (erasure_groups_head ==
nullptr)
1174 if (end_iterator.element_pointer != pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield))
1176 const iterator return_iterator = end_iterator;
1178 #ifdef PLF_EXCEPTIONS_SUPPORT
1179 if constexpr (!std::is_nothrow_constructible<element_type>::value)
1181 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), std::forward<arguments>(parameters) ...);
1182 ++end_iterator.element_pointer;
1187 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::forward<arguments>(parameters) ...);
1190 ++(end_iterator.group_pointer->size);
1191 ++end_iterator.skipfield_pointer;
1194 return return_iterator;
1197 group_pointer_type next_group;
1199 if (unused_groups_head ==
nullptr)
1201 const skipfield_type new_group_size = (total_size < static_cast<size_type>(max_block_capacity)) ?
static_cast<skipfield_type
>(total_size) : max_block_capacity;
1202 reset_group_numbers_if_necessary();
1203 next_group = allocate_new_group(new_group_size, end_iterator.group_pointer);
1205 #ifdef PLF_EXCEPTIONS_SUPPORT
1206 if constexpr (!std::is_nothrow_constructible<element_type>::value)
1210 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), std::forward<arguments>(parameters) ...);
1214 deallocate_group(next_group);
1221 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(next_group->elements), std::forward<arguments>(parameters) ...);
1224 total_capacity += new_group_size;
1228 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(unused_groups_head->elements), std::forward<arguments>(parameters) ...);
1229 next_group = reuse_unused_group();
1232 end_iterator.group_pointer->next_group = next_group;
1233 end_iterator.group_pointer = next_group;
1234 end_iterator.element_pointer = next_group->elements + 1;
1235 end_iterator.skipfield_pointer = next_group->skipfield + 1;
1238 return iterator(next_group, next_group->elements, next_group->skipfield);
1242 iterator new_location(erasure_groups_head, erasure_groups_head->elements + erasure_groups_head->free_list_head, erasure_groups_head->skipfield + erasure_groups_head->free_list_head);
1244 const skipfield_type prev_free_list_index = *pointer_cast<skipfield_pointer_type>(new_location.element_pointer);
1245 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(new_location.element_pointer), std::forward<arguments>(parameters) ...);
1246 update_skipblock(new_location, prev_free_list_index);
1248 return new_location;
1253 initialize(min_block_capacity);
1255 #ifdef PLF_EXCEPTIONS_SUPPORT
1256 if constexpr (!std::is_nothrow_constructible<element_type>::value)
1260 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::forward<arguments>(parameters) ...);
1271 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer++), std::forward<arguments>(parameters) ...);
1274 ++end_iterator.skipfield_pointer;
1276 return begin_iterator;
1285 void recover_from_partial_fill()
1287 #ifdef PLF_EXCEPTIONS_SUPPORT
1288 if constexpr ((!std::is_copy_constructible<element_type>::value && !std::is_nothrow_move_constructible<element_type>::value) || !std::is_nothrow_copy_constructible<element_type>::value)
1290 const skipfield_type elements_constructed_before_exception =
static_cast<skipfield_type
>(end_iterator.element_pointer - end_iterator.group_pointer->elements);
1291 end_iterator.group_pointer->size = elements_constructed_before_exception;
1292 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + elements_constructed_before_exception;
1293 total_size += elements_constructed_before_exception;
1294 unused_groups_head = end_iterator.group_pointer->next_group;
1295 end_iterator.group_pointer->next_group =
nullptr;
1302 void fill(
const element_type &element,
const skipfield_type
size)
1304 #ifdef PLF_EXCEPTIONS_SUPPORT
1305 if constexpr (!std::is_nothrow_copy_constructible<element_type>::value)
1307 const aligned_pointer_type fill_end = end_iterator.element_pointer +
size;
1313 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), element);
1317 recover_from_partial_fill();
1320 }
while (++end_iterator.element_pointer != fill_end);
1324 if constexpr (std::is_trivially_copyable<element_type>::value && std::is_trivially_copy_constructible<element_type>::value)
1326 if constexpr (
sizeof(aligned_element_struct) !=
sizeof(element_type))
1328 alignas (
alignof(aligned_element_struct)) element_type aligned_copy = element;
1329 std::fill_n(end_iterator.element_pointer,
size, *pointer_cast<aligned_pointer_type>(&aligned_copy));
1333 std::fill_n(pointer_cast<pointer>(end_iterator.element_pointer),
size, element);
1336 end_iterator.element_pointer +=
size;
1340 const aligned_pointer_type fill_end = end_iterator.element_pointer +
size;
1344 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), element);
1345 }
while (++end_iterator.element_pointer != fill_end);
1354 void recover_from_partial_skipblock_fill(aligned_pointer_type
const location,
const aligned_pointer_type current_location, skipfield_pointer_type
const skipfield_pointer,
const skipfield_type prev_free_list_node)
1356 #ifdef PLF_EXCEPTIONS_SUPPORT
1357 if constexpr ((!std::is_copy_constructible<element_type>::value && !std::is_nothrow_move_constructible<element_type>::value) || !std::is_nothrow_copy_constructible<element_type>::value)
1360 const skipfield_type elements_constructed_before_exception =
static_cast<skipfield_type
>(current_location - location);
1361 erasure_groups_head->size =
static_cast<skipfield_type
>(erasure_groups_head->size + elements_constructed_before_exception);
1362 total_size += elements_constructed_before_exception;
1364 std::memset(skipfield_pointer, 0, elements_constructed_before_exception *
sizeof(skipfield_type));
1366 edit_free_list_head(location + elements_constructed_before_exception, prev_free_list_node);
1368 const skipfield_type new_skipblock_head_index =
static_cast<skipfield_type
>((location - erasure_groups_head->elements) + elements_constructed_before_exception);
1369 erasure_groups_head->free_list_head = new_skipblock_head_index;
1371 if (prev_free_list_node != std::numeric_limits<skipfield_type>::max())
1373 edit_free_list_next(erasure_groups_head->elements + prev_free_list_node, new_skipblock_head_index);
1381 void fill_skipblock(
const element_type &element, aligned_pointer_type
const location, skipfield_pointer_type
const skipfield_pointer,
const skipfield_type
size)
1383 #ifdef PLF_EXCEPTIONS_SUPPORT
1384 if constexpr (!std::is_nothrow_copy_constructible<element_type>::value)
1386 const aligned_pointer_type fill_end = location +
size;
1387 const skipfield_type prev_free_list_node = *pointer_cast<skipfield_pointer_type>(location);
1389 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1393 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), element);
1397 recover_from_partial_skipblock_fill(location, current_location, skipfield_pointer, prev_free_list_node);
1404 if constexpr (std::is_trivially_copyable<element_type>::value && std::is_trivially_copy_constructible<element_type>::value)
1406 if constexpr (
sizeof(aligned_element_struct) !=
sizeof(element_type))
1408 alignas (
alignof(aligned_element_struct)) element_type aligned_copy = element;
1409 std::fill_n(location,
size, *pointer_cast<aligned_pointer_type>(&aligned_copy));
1413 std::fill_n(pointer_cast<pointer>(location),
size, element);
1418 const aligned_pointer_type fill_end = location +
size;
1420 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1422 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), element);
1426 std::memset(skipfield_pointer, 0,
size *
sizeof(skipfield_type));
1427 erasure_groups_head->size =
static_cast<skipfield_type
>(erasure_groups_head->size +
size);
1433 void fill_unused_groups(
size_type size,
const element_type &element,
size_type group_number, group_pointer_type previous_group,
const group_pointer_type current_group)
1435 for (end_iterator.group_pointer = current_group; end_iterator.group_pointer->capacity <
size; end_iterator.group_pointer = end_iterator.group_pointer->next_group)
1437 const skipfield_type
capacity = end_iterator.group_pointer->capacity;
1438 end_iterator.group_pointer->reset(
capacity, end_iterator.group_pointer->next_group, previous_group, group_number++);
1439 previous_group = end_iterator.group_pointer;
1441 end_iterator.element_pointer = end_iterator.group_pointer->elements;
1446 unused_groups_head = end_iterator.group_pointer->next_group;
1447 end_iterator.group_pointer->reset(
static_cast<skipfield_type
>(
size),
nullptr, previous_group, group_number);
1448 end_iterator.element_pointer = end_iterator.group_pointer->elements;
1449 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield +
size;
1450 fill(element,
static_cast<skipfield_type
>(
size));
1471 if (total_size == 0)
1480 while(erasure_groups_head !=
nullptr)
1482 aligned_pointer_type
const element_pointer = erasure_groups_head->elements + erasure_groups_head->free_list_head;
1483 skipfield_pointer_type
const skipfield_pointer = erasure_groups_head->skipfield + erasure_groups_head->free_list_head;
1484 const skipfield_type skipblock_size = *skipfield_pointer;
1486 if (erasure_groups_head == begin_iterator.group_pointer && element_pointer < begin_iterator.element_pointer)
1488 begin_iterator.element_pointer = element_pointer;
1489 begin_iterator.skipfield_pointer = skipfield_pointer;
1492 if (skipblock_size <=
size)
1494 erasure_groups_head->free_list_head = *pointer_cast<skipfield_pointer_type>(element_pointer);
1495 fill_skipblock(element, element_pointer, skipfield_pointer, skipblock_size);
1496 size -= skipblock_size;
1498 if (erasure_groups_head->free_list_head != std::numeric_limits<skipfield_type>::max())
1500 edit_free_list_next(erasure_groups_head->elements + erasure_groups_head->free_list_head, std::numeric_limits<skipfield_type>::max());
1504 erasure_groups_head = erasure_groups_head->erasures_list_next_group;
1514 const skipfield_type prev_index = *pointer_cast<skipfield_pointer_type>(element_pointer);
1515 fill_skipblock(element, element_pointer, skipfield_pointer,
static_cast<skipfield_type
>(
size));
1516 const skipfield_type new_skipblock_size =
static_cast<skipfield_type
>(skipblock_size -
size);
1519 *(skipfield_pointer +
size) = new_skipblock_size;
1520 *(skipfield_pointer + skipblock_size - 1) = new_skipblock_size;
1521 erasure_groups_head->free_list_head =
static_cast<skipfield_type
>(erasure_groups_head->free_list_head +
size);
1524 edit_free_list_head(element_pointer +
size, prev_index);
1526 if (prev_index != std::numeric_limits<skipfield_type>::max())
1528 edit_free_list_next(erasure_groups_head->elements + prev_index, erasure_groups_head->free_list_head);
1538 const skipfield_type group_remainder =
static_cast<skipfield_type
>(
1539 (
static_cast<size_type>(pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer) >=
size) ?
1540 size : pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer);
1542 if (group_remainder != 0)
1544 fill(element, group_remainder);
1545 end_iterator.group_pointer->size =
static_cast<skipfield_type
>(end_iterator.group_pointer->size + group_remainder);
1547 if (
size == group_remainder)
1549 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->size;
1553 size -= group_remainder;
1558 end_iterator.group_pointer->next_group = unused_groups_head;
1560 if ((std::numeric_limits<size_type>::max() - end_iterator.group_pointer->group_number) <
size)
1562 reset_group_numbers();
1565 fill_unused_groups(
size, element, end_iterator.group_pointer->group_number + 1u, end_iterator.group_pointer, unused_groups_head);
1572 template <
class iterator_type>
1573 iterator_type range_fill(iterator_type it,
const skipfield_type
size)
1575 const aligned_pointer_type fill_end = end_iterator.element_pointer +
size;
1577 #ifdef PLF_EXCEPTIONS_SUPPORT
1578 if constexpr ((!std::is_copy_constructible<element_type>::value && !std::is_nothrow_move_constructible<element_type>::value) || !std::is_nothrow_copy_constructible<element_type>::value)
1584 if constexpr (std::is_copy_constructible<element_type>::value)
1586 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), std::move(*it++));
1590 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), *it++);
1595 recover_from_partial_fill();
1598 }
while (++end_iterator.element_pointer != fill_end);
1602 if constexpr (std::is_copy_constructible<element_type>::value)
1606 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), *it++);
1607 }
while (++end_iterator.element_pointer != fill_end);
1613 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(end_iterator.element_pointer), std::move(*it++));
1614 }
while (++end_iterator.element_pointer != fill_end);
1623 template <
class iterator_type>
1624 iterator_type range_fill_skipblock(iterator_type it, aligned_pointer_type
const location, skipfield_pointer_type
const skipfield_pointer,
const skipfield_type
size)
1626 const aligned_pointer_type fill_end = location +
size;
1628 #ifdef PLF_EXCEPTIONS_SUPPORT
1629 if constexpr ((!std::is_copy_constructible<element_type>::value && !std::is_nothrow_move_constructible<element_type>::value) || !std::is_nothrow_copy_constructible<element_type>::value)
1631 const skipfield_type prev_free_list_node = *pointer_cast<skipfield_pointer_type>(location);
1633 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1637 if constexpr (std::is_copy_constructible<element_type>::value)
1639 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), std::move(*it++));
1643 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), *it++);
1648 recover_from_partial_skipblock_fill(location, current_location, skipfield_pointer, prev_free_list_node);
1655 if constexpr (std::is_copy_constructible<element_type>::value)
1657 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1659 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), *it++);
1664 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1666 std::allocator_traits<allocator_type>::construct(*
this, pointer_cast<pointer>(current_location), std::move(*it++));
1670 std::memset(skipfield_pointer, 0,
size *
sizeof(skipfield_type));
1671 erasure_groups_head->size =
static_cast<skipfield_type
>(erasure_groups_head->size +
size);
1679 template <
class iterator_type>
1680 void range_fill_unused_groups(
size_type size, iterator_type it,
size_type group_number, group_pointer_type previous_group,
const group_pointer_type current_group)
1682 for (end_iterator.group_pointer = current_group; end_iterator.group_pointer->capacity <
size; end_iterator.group_pointer = end_iterator.group_pointer->next_group)
1684 const skipfield_type
capacity = end_iterator.group_pointer->capacity;
1685 end_iterator.group_pointer->reset(
capacity, end_iterator.group_pointer->next_group, previous_group, group_number++);
1686 previous_group = end_iterator.group_pointer;
1688 end_iterator.element_pointer = end_iterator.group_pointer->elements;
1693 unused_groups_head = end_iterator.group_pointer->next_group;
1694 end_iterator.group_pointer->reset(
static_cast<skipfield_type
>(
size),
nullptr, previous_group, group_number);
1695 end_iterator.element_pointer = end_iterator.group_pointer->elements;
1696 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield +
size;
1697 range_fill(it,
static_cast<skipfield_type
>(
size));
1702 template <
class iterator_type>
1715 if (total_size == 0)
1717 range_assign(it,
size);
1723 while(erasure_groups_head !=
nullptr)
1725 aligned_pointer_type
const element_pointer = erasure_groups_head->elements + erasure_groups_head->free_list_head;
1726 skipfield_pointer_type
const skipfield_pointer = erasure_groups_head->skipfield + erasure_groups_head->free_list_head;
1727 const skipfield_type skipblock_size = *skipfield_pointer;
1729 if (erasure_groups_head == begin_iterator.group_pointer && element_pointer < begin_iterator.element_pointer)
1731 begin_iterator.element_pointer = element_pointer;
1732 begin_iterator.skipfield_pointer = skipfield_pointer;
1735 if (skipblock_size <=
size)
1737 erasure_groups_head->free_list_head = *pointer_cast<skipfield_pointer_type>(element_pointer);
1738 it = range_fill_skipblock(it, element_pointer, skipfield_pointer, skipblock_size);
1739 size -= skipblock_size;
1741 if (erasure_groups_head->free_list_head != std::numeric_limits<skipfield_type>::max())
1743 edit_free_list_next(erasure_groups_head->elements + erasure_groups_head->free_list_head, std::numeric_limits<skipfield_type>::max());
1747 erasure_groups_head = erasure_groups_head->erasures_list_next_group;
1757 const skipfield_type prev_index = *pointer_cast<skipfield_pointer_type>(element_pointer);
1758 it = range_fill_skipblock(it, element_pointer, skipfield_pointer,
static_cast<skipfield_type
>(
size));
1759 const skipfield_type new_skipblock_size =
static_cast<skipfield_type
>(skipblock_size -
size);
1761 *(skipfield_pointer +
size) = new_skipblock_size;
1762 *(skipfield_pointer + skipblock_size - 1) = new_skipblock_size;
1763 erasure_groups_head->free_list_head =
static_cast<skipfield_type
>(erasure_groups_head->free_list_head +
size);
1764 edit_free_list_head(element_pointer +
size, prev_index);
1766 if (prev_index != std::numeric_limits<skipfield_type>::max())
1768 edit_free_list_next(erasure_groups_head->elements + prev_index, erasure_groups_head->free_list_head);
1775 const skipfield_type group_remainder =
static_cast<skipfield_type
>(
1776 (
static_cast<size_type>(pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer) >=
size) ?
1777 size : pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer);
1779 if (group_remainder != 0)
1781 it = range_fill(it, group_remainder);
1782 end_iterator.group_pointer->size =
static_cast<skipfield_type
>(end_iterator.group_pointer->size + group_remainder);
1784 if (
size == group_remainder)
1786 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->size;
1790 size -= group_remainder;
1794 end_iterator.group_pointer->next_group = unused_groups_head;
1796 if ((std::numeric_limits<size_type>::max() - end_iterator.group_pointer->group_number) <
size)
1798 reset_group_numbers();
1801 range_fill_unused_groups(
size, it, end_iterator.group_pointer->group_number + 1u, end_iterator.group_pointer, unused_groups_head);
1810 template <
class iterator_type>
1811 void insert (
const typename std::enable_if_t<!std::numeric_limits<iterator_type>::is_integer, iterator_type> first,
const iterator_type last)
1820 template <
class iterator_type>
1821 void insert (
const std::move_iterator<iterator_type> first,
const std::move_iterator<iterator_type> last)
1830 void insert (
const std::initializer_list<element_type> &element_list)
1832 range_insert(element_list.begin(),
static_cast<size_type>(element_list.size()));
1837 template<
class range_type>
1838 requires std::ranges::range<range_type>
1841 range_insert(std::ranges::begin(the_range),
static_cast<size_type>(std::ranges::distance(the_range)));
1848 void remove_from_groups_with_erasures_list(
const group_pointer_type group_to_remove)
noexcept
1850 if (group_to_remove != erasure_groups_head)
1852 group_to_remove->erasures_list_previous_group->erasures_list_next_group = group_to_remove->erasures_list_next_group;
1854 if (group_to_remove->erasures_list_next_group !=
nullptr)
1856 group_to_remove->erasures_list_next_group->erasures_list_previous_group = group_to_remove->erasures_list_previous_group;
1861 erasure_groups_head = erasure_groups_head->erasures_list_next_group;
1867 void reset_only_group_left(group_pointer_type
const group_pointer)
noexcept
1869 erasure_groups_head =
nullptr;
1870 group_pointer->reset(0,
nullptr,
nullptr, 0);
1873 end_iterator.element_pointer = begin_iterator.element_pointer = group_pointer->elements;
1874 end_iterator.skipfield_pointer = begin_iterator.skipfield_pointer = group_pointer->skipfield;
1879 void add_group_to_unused_groups_list(group *
const group_pointer)
noexcept
1881 group_pointer->next_group = unused_groups_head;
1882 unused_groups_head = group_pointer;
1892 assert(total_size != 0);
1893 assert(it.group_pointer !=
nullptr);
1894 assert(it.element_pointer != pointer_cast<aligned_pointer_type>(it.group_pointer->skipfield));
1895 assert(*(it.skipfield_pointer) == 0);
1897 if constexpr (!std::is_trivially_destructible<element_type>::value)
1899 destroy_element(it.element_pointer);
1904 if (it.group_pointer->size-- != 1)
1916 const char prev_skipfield = *(it.skipfield_pointer - (it.skipfield_pointer != it.group_pointer->skipfield)) != 0;
1917 const char after_skipfield = *(it.skipfield_pointer + 1) != 0;
1918 skipfield_type update_value = 1;
1920 if (!(prev_skipfield | after_skipfield))
1922 *it.skipfield_pointer = 1;
1923 const skipfield_type index =
static_cast<skipfield_type
>(it.element_pointer - it.group_pointer->elements);
1925 if (it.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
1927 edit_free_list_next(it.group_pointer->elements + it.group_pointer->free_list_head, index);
1931 it.group_pointer->erasures_list_next_group = erasure_groups_head;
1933 if (erasure_groups_head !=
nullptr)
1935 erasure_groups_head->erasures_list_previous_group = it.group_pointer;
1938 erasure_groups_head = it.group_pointer;
1941 edit_free_list_head(it.element_pointer, it.group_pointer->free_list_head);
1942 it.group_pointer->free_list_head = index;
1944 else if (prev_skipfield & (!after_skipfield))
1946 *(it.skipfield_pointer - *(it.skipfield_pointer - 1)) = *it.skipfield_pointer =
static_cast<skipfield_type
>(*(it.skipfield_pointer - 1) + 1);
1948 else if ((!prev_skipfield) & after_skipfield)
1950 const skipfield_type following_value =
static_cast<skipfield_type
>(*(it.skipfield_pointer + 1) + 1);
1951 *(it.skipfield_pointer + following_value - 1) = *(it.skipfield_pointer) = following_value;
1953 const skipfield_type following_previous = *(pointer_cast<skipfield_pointer_type>(it.element_pointer + 1));
1954 const skipfield_type following_next = *(pointer_cast<skipfield_pointer_type>(it.element_pointer + 1) + 1);
1955 edit_free_list_prev(it.element_pointer, following_previous);
1956 edit_free_list_next(it.element_pointer, following_next);
1958 const skipfield_type index =
static_cast<skipfield_type
>(it.element_pointer - it.group_pointer->elements);
1960 if (following_previous != std::numeric_limits<skipfield_type>::max())
1962 edit_free_list_next(it.group_pointer->elements + following_previous, index);
1965 if (following_next != std::numeric_limits<skipfield_type>::max())
1967 edit_free_list_prev(it.group_pointer->elements + following_next, index);
1971 it.group_pointer->free_list_head = index;
1974 update_value = following_value;
1978 *(it.skipfield_pointer) = 1;
1979 const skipfield_type preceding_value = *(it.skipfield_pointer - 1);
1980 const skipfield_type following_value =
static_cast<skipfield_type
>(*(it.skipfield_pointer + 1) + 1);
1983 *(it.skipfield_pointer - preceding_value) = *(it.skipfield_pointer + following_value - 1) =
static_cast<skipfield_type
>(preceding_value + following_value);
1986 const skipfield_type following_previous = *(pointer_cast<skipfield_pointer_type>(it.element_pointer + 1));
1987 const skipfield_type following_next = *(pointer_cast<skipfield_pointer_type>(it.element_pointer + 1) + 1);
1989 if (following_previous != std::numeric_limits<skipfield_type>::max())
1991 edit_free_list_next(it.group_pointer->elements + following_previous, following_next);
1994 if (following_next != std::numeric_limits<skipfield_type>::max())
1996 edit_free_list_prev(it.group_pointer->elements + following_next, following_previous);
2000 it.group_pointer->free_list_head = following_previous;
2003 update_value = following_value;
2006 iterator return_iterator(it.group_pointer, it.element_pointer + update_value, it.skipfield_pointer + update_value);
2008 if (return_iterator.element_pointer == pointer_cast<aligned_pointer_type>(it.group_pointer->skipfield) && it.group_pointer != end_iterator.group_pointer)
2010 return_iterator.group_pointer = it.group_pointer->next_group;
2011 const aligned_pointer_type elements = return_iterator.group_pointer->elements;
2012 const skipfield_pointer_type skipfield = return_iterator.group_pointer->skipfield;
2013 return_iterator.element_pointer = elements + *skipfield;
2014 return_iterator.skipfield_pointer = skipfield + *skipfield;
2017 if (it.element_pointer == begin_iterator.element_pointer)
2019 begin_iterator = return_iterator;
2022 return return_iterator;
2026 const bool in_back_block = (it.group_pointer->next_group ==
nullptr), in_front_block = (it.group_pointer == begin_iterator.group_pointer);
2028 if (in_back_block & in_front_block)
2031 reset_only_group_left(it.group_pointer);
2032 return end_iterator;
2034 else if ((!in_back_block) & in_front_block)
2036 it.group_pointer->next_group->previous_group =
nullptr;
2037 begin_iterator.group_pointer = it.group_pointer->next_group;
2039 if (it.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2041 remove_from_groups_with_erasures_list(it.group_pointer);
2044 total_capacity -= it.group_pointer->capacity;
2045 deallocate_group(it.group_pointer);
2048 begin_iterator.element_pointer = begin_iterator.group_pointer->elements + *(begin_iterator.group_pointer->skipfield);
2049 begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield + *(begin_iterator.group_pointer->skipfield);
2051 return begin_iterator;
2053 else if (!(in_back_block | in_front_block))
2055 it.group_pointer->next_group->previous_group = it.group_pointer->previous_group;
2056 group_pointer_type
const return_group = it.group_pointer->previous_group->next_group = it.group_pointer->next_group;
2058 if (it.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2060 remove_from_groups_with_erasures_list(it.group_pointer);
2063 if (it.group_pointer->next_group != end_iterator.group_pointer)
2065 total_capacity -= it.group_pointer->capacity;
2066 deallocate_group(it.group_pointer);
2070 add_group_to_unused_groups_list(it.group_pointer);
2074 return iterator(return_group, return_group->elements + *(return_group->skipfield), return_group->skipfield + *(return_group->skipfield));
2078 if (it.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2080 remove_from_groups_with_erasures_list(it.group_pointer);
2083 it.group_pointer->previous_group->next_group =
nullptr;
2084 end_iterator.group_pointer = it.group_pointer->previous_group;
2085 end_iterator.element_pointer = pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield);
2086 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->capacity;
2088 add_group_to_unused_groups_list(it.group_pointer);
2090 return end_iterator;
2100 assert(iterator1 <= iterator2);
2104 if (current.group_pointer != iterator2.group_pointer)
2106 if (current.element_pointer != current.group_pointer->elements + *(current.group_pointer->skipfield))
2111 const aligned_pointer_type
end = pointer_cast<aligned_pointer_type>(iterator1.group_pointer->skipfield);
2115 if (std::is_trivially_destructible<element_type>::value && current.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
2117 number_of_group_erasures +=
static_cast<size_type>(
end - current.element_pointer);
2121 while (current.element_pointer !=
end)
2123 if (*current.skipfield_pointer == 0)
2125 if constexpr (!std::is_trivially_destructible<element_type>::value)
2127 destroy_element(current.element_pointer);
2130 ++number_of_group_erasures;
2131 ++current.element_pointer;
2132 ++current.skipfield_pointer;
2136 const skipfield_type prev_free_list_index = *(pointer_cast<skipfield_pointer_type>(current.element_pointer));
2137 const skipfield_type next_free_list_index = *(pointer_cast<skipfield_pointer_type>(current.element_pointer) + 1);
2139 current.element_pointer += *(current.skipfield_pointer);
2140 current.skipfield_pointer += *(current.skipfield_pointer);
2142 if (next_free_list_index == std::numeric_limits<skipfield_type>::max() && prev_free_list_index == std::numeric_limits<skipfield_type>::max())
2144 remove_from_groups_with_erasures_list(iterator1.group_pointer);
2145 iterator1.group_pointer->free_list_head = std::numeric_limits<skipfield_type>::max();
2146 number_of_group_erasures +=
static_cast<size_type>(
end - current.element_pointer);
2148 if constexpr (!std::is_trivially_destructible<element_type>::value)
2150 while (current.element_pointer !=
end)
2152 destroy_element(current.element_pointer++);
2158 else if (next_free_list_index == std::numeric_limits<skipfield_type>::max())
2160 current.group_pointer->free_list_head = prev_free_list_index;
2161 edit_free_list_next(current.group_pointer->elements + prev_free_list_index, std::numeric_limits<skipfield_type>::max());
2165 edit_free_list_prev(current.group_pointer->elements + next_free_list_index, prev_free_list_index);
2167 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
2169 edit_free_list_next(current.group_pointer->elements + prev_free_list_index, next_free_list_index);
2177 const skipfield_type previous_node_value = *(iterator1.skipfield_pointer - 1);
2178 const skipfield_type distance_to_end =
static_cast<skipfield_type
>(
end - iterator1.element_pointer);
2180 if (previous_node_value == 0)
2182 *iterator1.skipfield_pointer = distance_to_end;
2183 *(iterator1.skipfield_pointer + distance_to_end - 1) = distance_to_end;
2185 const skipfield_type index =
static_cast<skipfield_type
>(iterator1.element_pointer - iterator1.group_pointer->elements);
2187 if (iterator1.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2189 edit_free_list_next(iterator1.group_pointer->elements + iterator1.group_pointer->free_list_head, index);
2193 iterator1.group_pointer->erasures_list_next_group = erasure_groups_head;
2195 if (erasure_groups_head !=
nullptr)
2197 erasure_groups_head->erasures_list_previous_group = iterator1.group_pointer;
2200 erasure_groups_head = iterator1.group_pointer;
2203 edit_free_list_head(iterator1.element_pointer, iterator1.group_pointer->free_list_head);
2204 iterator1.group_pointer->free_list_head = index;
2208 *(iterator1.skipfield_pointer - previous_node_value) = *(iterator1.skipfield_pointer + distance_to_end - 1) =
static_cast<skipfield_type
>(previous_node_value + distance_to_end);
2211 if (distance_to_end > 2)
2213 std::memset(
static_cast<void *
>(std::to_address(iterator1.skipfield_pointer) + 1), 1,
sizeof(skipfield_type) * (distance_to_end - 2));
2216 iterator1.group_pointer->size =
static_cast<skipfield_type
>(iterator1.group_pointer->size - number_of_group_erasures);
2217 total_size -= number_of_group_erasures;
2219 current.group_pointer = current.group_pointer->next_group;
2224 const group_pointer_type previous_group = current.group_pointer->previous_group;
2226 while (current.group_pointer != iterator2.group_pointer)
2228 if constexpr (!std::is_trivially_destructible<element_type>::value)
2230 current.element_pointer = current.group_pointer->elements + *(current.group_pointer->skipfield);
2231 current.skipfield_pointer = current.group_pointer->skipfield + *(current.group_pointer->skipfield);
2232 const aligned_pointer_type
end = pointer_cast<aligned_pointer_type>(current.group_pointer->skipfield);
2236 destroy_element(current.element_pointer);
2237 current.element_pointer +=
static_cast<size_type>(*(++current.skipfield_pointer)) + 1u;
2238 current.skipfield_pointer += *(current.skipfield_pointer);
2239 }
while (current.element_pointer !=
end);
2242 if (current.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2244 remove_from_groups_with_erasures_list(current.group_pointer);
2247 total_size -= current.group_pointer->size;
2248 const group_pointer_type current_group = current.group_pointer;
2249 current.group_pointer = current.group_pointer->next_group;
2251 if (current_group != end_iterator.group_pointer && current_group->next_group != end_iterator.group_pointer)
2253 total_capacity -= current_group->capacity;
2254 deallocate_group(current_group);
2258 add_group_to_unused_groups_list(current_group);
2262 current.element_pointer = current.group_pointer->elements + *(current.group_pointer->skipfield);
2263 current.skipfield_pointer = current.group_pointer->skipfield + *(current.group_pointer->skipfield);
2264 current.group_pointer->previous_group = previous_group;
2266 if (previous_group !=
nullptr)
2268 previous_group->next_group = current.group_pointer;
2272 begin_iterator =
iterator(iterator2.group_pointer, iterator2.element_pointer, iterator2.skipfield_pointer);;
2282 if (current.element_pointer != iterator2.element_pointer)
2284 if (iterator2.element_pointer != end_iterator.element_pointer || current.element_pointer != current.group_pointer->elements + *(current.group_pointer->skipfield))
2291 if (std::is_trivially_destructible<element_type>::value && current.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
2293 number_of_group_erasures +=
static_cast<size_type>(iterator2.element_pointer - current.element_pointer);
2297 while (current.element_pointer != iterator2.element_pointer)
2299 if (*current.skipfield_pointer == 0)
2301 if constexpr (!std::is_trivially_destructible<element_type>::value)
2303 destroy_element(current.element_pointer);
2306 ++number_of_group_erasures;
2307 ++current.element_pointer;
2308 ++current.skipfield_pointer;
2312 const skipfield_type prev_free_list_index = *(pointer_cast<skipfield_pointer_type>(current.element_pointer));
2313 const skipfield_type next_free_list_index = *(pointer_cast<skipfield_pointer_type>(current.element_pointer) + 1);
2315 current.element_pointer += *(current.skipfield_pointer);
2316 current.skipfield_pointer += *(current.skipfield_pointer);
2318 if (next_free_list_index == std::numeric_limits<skipfield_type>::max() && prev_free_list_index == std::numeric_limits<skipfield_type>::max())
2320 remove_from_groups_with_erasures_list(iterator2.group_pointer);
2321 iterator2.group_pointer->free_list_head = std::numeric_limits<skipfield_type>::max();
2322 number_of_group_erasures +=
static_cast<size_type>(iterator2.element_pointer - current.element_pointer);
2324 if constexpr (!std::is_trivially_destructible<element_type>::value)
2326 while (current.element_pointer != iterator2.element_pointer)
2328 destroy_element(current.element_pointer++);
2334 else if (next_free_list_index == std::numeric_limits<skipfield_type>::max())
2336 current.group_pointer->free_list_head = prev_free_list_index;
2337 edit_free_list_next(current.group_pointer->elements + prev_free_list_index, std::numeric_limits<skipfield_type>::max());
2341 edit_free_list_prev(current.group_pointer->elements + next_free_list_index, prev_free_list_index);
2343 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
2345 edit_free_list_next(current.group_pointer->elements + prev_free_list_index, next_free_list_index);
2353 const skipfield_type distance_to_iterator2 =
static_cast<skipfield_type
>(iterator2.element_pointer - current_saved.element_pointer);
2354 const skipfield_type index =
static_cast<skipfield_type
>(current_saved.element_pointer - iterator2.group_pointer->elements);
2356 if (index == 0 || *(current_saved.skipfield_pointer - 1) == 0)
2358 *(current_saved.skipfield_pointer) = distance_to_iterator2;
2359 *(iterator2.skipfield_pointer - 1) = distance_to_iterator2;
2361 if (iterator2.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2363 edit_free_list_next(iterator2.group_pointer->elements + iterator2.group_pointer->free_list_head, index);
2367 iterator2.group_pointer->erasures_list_next_group = erasure_groups_head;
2369 if (erasure_groups_head !=
nullptr)
2371 erasure_groups_head->erasures_list_previous_group = iterator2.group_pointer;
2374 erasure_groups_head = iterator2.group_pointer;
2377 edit_free_list_head(current_saved.element_pointer, iterator2.group_pointer->free_list_head);
2378 iterator2.group_pointer->free_list_head = index;
2383 const skipfield_type prev_node_value = *(current_saved.skipfield_pointer - 1);
2384 *(current_saved.skipfield_pointer - prev_node_value) =
static_cast<skipfield_type
>(prev_node_value + distance_to_iterator2);
2385 *(iterator2.skipfield_pointer - 1) =
static_cast<skipfield_type
>(prev_node_value + distance_to_iterator2);
2389 if (distance_to_iterator2 > 2)
2391 std::memset(
static_cast<void *
>(std::to_address(current_saved.skipfield_pointer) + 1), 1,
sizeof(skipfield_type) * (distance_to_iterator2 - 2));
2394 if (iterator1.element_pointer == begin_iterator.element_pointer)
2396 begin_iterator =
iterator(iterator2.group_pointer, iterator2.element_pointer, iterator2.skipfield_pointer);
2399 iterator2.group_pointer->size =
static_cast<skipfield_type
>(iterator2.group_pointer->size - number_of_group_erasures);
2400 total_size -= number_of_group_erasures;
2404 if constexpr (!std::is_trivially_destructible<element_type>::value)
2406 while(current.element_pointer != iterator2.element_pointer)
2408 destroy_element(current.element_pointer);
2409 current.element_pointer +=
static_cast<size_type>(*(++current.skipfield_pointer)) + 1u;
2410 current.skipfield_pointer += *(current.skipfield_pointer);
2414 if ((total_size -= current.group_pointer->size) != 0)
2416 if (current.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2418 remove_from_groups_with_erasures_list(current.group_pointer);
2421 current.group_pointer->previous_group->next_group = current.group_pointer->next_group;
2423 end_iterator.group_pointer = current.group_pointer->previous_group;
2424 end_iterator.element_pointer = pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield);
2425 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->capacity;
2426 add_group_to_unused_groups_list(current.group_pointer);
2431 reset_only_group_left(current.group_pointer);
2434 return end_iterator;
2438 return iterator(iterator2.group_pointer, iterator2.element_pointer, iterator2.skipfield_pointer);
2448 if constexpr (!std::is_trivially_destructible<element_type>::value)
2450 for (
iterator current = begin_iterator; current != end_iterator; ++current)
2452 destroy_element(current.element_pointer);
2456 if (
size < total_capacity && (total_capacity -
size) >= min_block_capacity)
2459 end_iterator.group_pointer->next_group = unused_groups_head;
2462 group_pointer_type current_group = begin_iterator.group_pointer, previous_group =
nullptr;
2466 const group_pointer_type next_group = current_group->next_group;
2468 if (current_group->capacity <= difference)
2470 difference -= current_group->capacity;
2471 total_capacity -= current_group->capacity;
2472 deallocate_group(current_group);
2474 if (current_group == begin_iterator.group_pointer)
2476 begin_iterator.group_pointer = next_group;
2481 if (previous_group !=
nullptr)
2483 previous_group->next_group = current_group;
2486 previous_group = current_group;
2489 current_group = next_group;
2490 }
while (current_group !=
nullptr);
2492 previous_group->next_group =
nullptr;
2496 if (
size > total_capacity)
2502 end_iterator.group_pointer->next_group = unused_groups_head;
2505 begin_iterator.element_pointer = begin_iterator.group_pointer->elements;
2506 begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield;
2507 erasure_groups_head =
nullptr;
2525 prepare_groups_for_assign(
size);
2526 fill_unused_groups(
size, element, 0,
nullptr, begin_iterator.group_pointer);
2535 template <
class iterator_type>
2536 void range_assign(
const iterator_type it,
const size_type size)
2544 prepare_groups_for_assign(
size);
2545 range_fill_unused_groups(
size, it, 0,
nullptr, begin_iterator.group_pointer);
2555 template <
class iterator_type>
2556 void assign(
const typename std::enable_if_t<!std::numeric_limits<iterator_type>::is_integer, iterator_type> first,
const iterator_type last)
2565 template <
class iterator_type>
2566 void assign (
const std::move_iterator<iterator_type> first,
const std::move_iterator<iterator_type> last)
2575 void assign(
const std::initializer_list<element_type> &element_list)
2577 range_assign(element_list.begin(),
static_cast<size_type>(element_list.size()));
2582 template<
class range_type>
2583 requires std::ranges::range<range_type>
2586 range_assign(std::ranges::begin(the_range),
static_cast<size_type>(std::ranges::distance(the_range)));
2591 [[nodiscard]]
bool empty() const noexcept
2593 return total_size == 0;
2607 return std::allocator_traits<allocator_type>::max_size(*
this);
2614 return total_capacity;
2624 #ifdef PLF_EXCEPTIONS_SUPPORT
2625 if constexpr (!(std::is_nothrow_move_constructible<element_type>::value && std::is_nothrow_move_assignable<element_type>::value))
2633 hive temp(hive_limits(min_block_capacity, max_block_capacity));
2634 temp.range_assign(std::make_move_iterator(begin_iterator), total_size);
2635 *
this = std::move(temp);
2646 check_capacities_conformance(block_limits);
2647 #ifdef PLF_EXCEPTIONS_SUPPORT
2648 const skipfield_type original_min = min_block_capacity, original_max = max_block_capacity;
2650 min_block_capacity =
static_cast<skipfield_type
>(block_limits.
min);
2651 max_block_capacity =
static_cast<skipfield_type
>(block_limits.
max);
2654 for (group_pointer_type current_group = begin_iterator.group_pointer; current_group !=
nullptr; current_group = current_group->next_group)
2656 if (current_group->capacity < min_block_capacity || current_group->capacity > max_block_capacity)
2658 if constexpr (!(std::is_copy_constructible<element_type>::value || std::is_move_constructible<element_type>::value))
2660 throw std::length_error(
"Current hive's block capacities do not fit within the supplied block limits, therefore reallocation of elements must occur, however user is using a non-copy-constructible/non-move-constructible type.");
2664 #ifdef PLF_EXCEPTIONS_SUPPORT
2671 min_block_capacity = original_min;
2672 max_block_capacity = original_max;
2685 for (group_pointer_type current_group = unused_groups_head, previous_group =
nullptr; current_group !=
nullptr;)
2687 const group_pointer_type next_group = current_group->next_group;
2689 if (current_group->capacity < min_block_capacity || current_group->capacity > max_block_capacity)
2691 total_capacity -= current_group->capacity;
2692 deallocate_group(current_group);
2694 if (previous_group ==
nullptr)
2696 unused_groups_head = next_group;
2700 previous_group->next_group = next_group;
2705 previous_group = current_group;
2708 current_group = next_group;
2716 return hive_limits(
static_cast<size_t>(min_block_capacity),
static_cast<size_t>(max_block_capacity));
2723 return hive_limits(3, std::numeric_limits<skipfield_type>::max());
2731 size_type num_units = allocation_amount / (
sizeof(aligned_element_struct) +
sizeof(skipfield_type));
2734 if (num_units > std::numeric_limits<skipfield_type>::max())
2736 num_units = std::numeric_limits<skipfield_type>::max();
2746 ((((num_units + 1) *
sizeof(aligned_allocation_struct)) - 1 +
sizeof(skipfield_type)) /
sizeof(aligned_allocation_struct))
2748 + (num_units *
sizeof(aligned_element_struct)))
2750 > allocation_amount)
2762 if (total_size == 0)
2768 if constexpr (!std::is_trivially_destructible<element_type>::value)
2770 for (
iterator current = begin_iterator; current != end_iterator; ++current)
2772 destroy_element(current.element_pointer);
2776 if (begin_iterator.group_pointer != end_iterator.group_pointer)
2778 end_iterator.group_pointer->next_group = unused_groups_head;
2779 unused_groups_head = begin_iterator.group_pointer->next_group;
2780 end_iterator.group_pointer = begin_iterator.group_pointer;
2783 reset_only_group_left(begin_iterator.group_pointer);
2784 erasure_groups_head =
nullptr;
2792 assert(&source !=
this);
2794 if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value)
2796 allocator_type source_allocator(source);
2798 if(!std::allocator_traits<allocator_type>::is_always_equal::value &&
static_cast<allocator_type &
>(*
this) != source_allocator)
2803 static_cast<allocator_type &
>(*this) = std::move(source_allocator);
2805 group_allocator = group_allocator_type(*
this);
2806 aligned_struct_allocator = aligned_struct_allocator_type(*
this);
2807 skipfield_allocator = skipfield_allocator_type(*
this);
2808 tuple_allocator = tuple_allocator_type(*
this);
2811 range_assign(source.begin_iterator, source.total_size);
2818 hive &
operator = (
hive &&source)
noexcept(std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value || std::allocator_traits<allocator_type>::is_always_equal::value)
2820 assert(&source !=
this);
2823 if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value || std::allocator_traits<allocator_type>::is_always_equal::value ||
static_cast<allocator_type &
>(*
this) ==
static_cast<allocator_type &
>(source))
2825 if constexpr ((std::is_trivially_copyable<allocator_type>::value || std::allocator_traits<allocator_type>::is_always_equal::value) &&
2826 std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
2828 std::memcpy(
static_cast<void *
>(
this), &source,
sizeof(
hive));
2832 end_iterator = std::move(source.end_iterator);
2833 begin_iterator = std::move(source.begin_iterator);
2834 erasure_groups_head = std::move(source.erasure_groups_head);
2835 unused_groups_head = std::move(source.unused_groups_head);
2836 total_size = source.total_size;
2837 total_capacity = source.total_capacity;
2838 min_block_capacity = source.min_block_capacity;
2839 max_block_capacity = source.max_block_capacity;
2841 if constexpr(std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
2843 static_cast<allocator_type &
>(*this) = std::move(
static_cast<allocator_type &
>(source));
2845 group_allocator = group_allocator_type(*
this);
2846 aligned_struct_allocator = aligned_struct_allocator_type(*
this);
2847 skipfield_allocator = skipfield_allocator_type(*
this);
2848 tuple_allocator = tuple_allocator_type(*
this);
2854 range_assign(std::make_move_iterator(source.begin_iterator), source.total_size);
2855 source.destroy_all_data();
2866 range_assign(element_list.begin(),
static_cast<size_type>(element_list.size()));
2874 if (total_size == total_capacity)
2878 else if (total_size == 0)
2891 if (end_iterator.element_pointer ==
nullptr)
2896 while(unused_groups_head !=
nullptr)
2898 total_capacity -= unused_groups_head->capacity;
2899 const group_pointer_type next_group = unused_groups_head->next_group;
2900 deallocate_group(unused_groups_head);
2901 unused_groups_head = next_group;
2904 if (begin_iterator.element_pointer == end_iterator.element_pointer)
2906 deallocate_group(begin_iterator.group_pointer);
2915 const size_type capacity_difference = total_capacity - capacity_retain;
2917 if (end_iterator.element_pointer ==
nullptr || total_capacity <= capacity_retain || total_size >= capacity_retain || capacity_difference < min_block_capacity)
2922 size_type number_of_elements_to_remove = capacity_difference;
2924 for (group_pointer_type current_group = unused_groups_head, previous_group =
nullptr; current_group !=
nullptr;)
2926 const group_pointer_type next_group = current_group->next_group;
2928 if (number_of_elements_to_remove >= current_group->capacity)
2930 number_of_elements_to_remove -= current_group->capacity;
2931 deallocate_group(current_group);
2933 if (previous_group ==
nullptr)
2935 unused_groups_head = next_group;
2939 previous_group->next_group = next_group;
2942 if (number_of_elements_to_remove < min_block_capacity)
2949 previous_group = current_group;
2952 current_group = next_group;
2956 if (begin_iterator.element_pointer == end_iterator.element_pointer)
2958 if (number_of_elements_to_remove >= begin_iterator.group_pointer->capacity)
2960 number_of_elements_to_remove -= begin_iterator.group_pointer->capacity;
2961 deallocate_group(begin_iterator.group_pointer);
2963 if (unused_groups_head !=
nullptr)
2965 begin_iterator.group_pointer = unused_groups_head;
2966 begin_iterator.element_pointer = unused_groups_head->elements;
2967 begin_iterator.skipfield_pointer = unused_groups_head->skipfield;
2968 end_iterator = begin_iterator;
2970 unused_groups_head = unused_groups_head->next_group;
2971 begin_iterator.group_pointer->next_group =
nullptr;
2981 total_capacity -= capacity_difference - number_of_elements_to_remove;
2988 if (new_capacity == 0 || new_capacity <= total_capacity)
2995 #ifdef PLF_EXCEPTIONS_SUPPORT
2996 throw std::length_error(
"Capacity requested via reserve() greater than max_size()");
3002 new_capacity -= total_capacity;
3004 size_type number_of_max_groups = new_capacity / max_block_capacity;
3005 skipfield_type remainder =
static_cast<skipfield_type
>(new_capacity - (number_of_max_groups * max_block_capacity));
3010 remainder = max_block_capacity;
3011 --number_of_max_groups;
3013 else if (remainder < min_block_capacity)
3015 remainder = min_block_capacity;
3019 group_pointer_type current_group, first_unused_group;
3021 if (begin_iterator.group_pointer ==
nullptr)
3023 initialize(remainder);
3024 begin_iterator.group_pointer->size = 0;
3026 if (number_of_max_groups == 0)
3032 first_unused_group = current_group = allocate_new_group(max_block_capacity, begin_iterator.group_pointer);
3033 total_capacity += max_block_capacity;
3034 --number_of_max_groups;
3039 if ((std::numeric_limits<size_type>::max() - end_iterator.group_pointer->group_number) < (number_of_max_groups + 1))
3041 reset_group_numbers();
3044 first_unused_group = current_group = allocate_new_group(remainder, end_iterator.group_pointer);
3045 total_capacity += remainder;
3049 while (number_of_max_groups != 0)
3051 #ifdef PLF_EXCEPTIONS_SUPPORT
3054 current_group->next_group = allocate_new_group(max_block_capacity, current_group);
3058 deallocate_group(current_group->next_group);
3059 current_group->next_group = unused_groups_head;
3060 unused_groups_head = first_unused_group;
3064 current_group->next_group = allocate_new_group(max_block_capacity, current_group);
3067 current_group = current_group->next_group;
3068 total_capacity += max_block_capacity;
3069 --number_of_max_groups;
3072 current_group->next_group = unused_groups_head;
3073 unused_groups_head = first_unused_group;
3080 template <
bool is_const>
3081 hive_iterator<is_const> get_it(
const pointer element_pointer)
const noexcept
3083 const aligned_pointer_type aligned_element_pointer = pointer_cast<aligned_pointer_type>(element_pointer);
3086 aligned_pointer_type
end = end_iterator.element_pointer;
3087 for (group_pointer_type current_group = end_iterator.group_pointer; current_group !=
nullptr; current_group = current_group->previous_group,
end = pointer_cast<aligned_pointer_type>(current_group->skipfield))
3089 if (std::greater_equal()(aligned_element_pointer, current_group->elements) && std::less()(aligned_element_pointer,
end))
3091 const skipfield_pointer_type skipfield_pointer = current_group->skipfield + (aligned_element_pointer - current_group->elements);
3092 return (*skipfield_pointer == 0) ? hive_iterator<is_const>(current_group, aligned_element_pointer, skipfield_pointer) : hive_iterator<is_const>(end_iterator);
3096 return end_iterator;
3105 return get_it<false>(element_pointer);
3112 return get_it<true>(
const_cast<pointer>(element_pointer));
3120 aligned_pointer_type
end = end_iterator.element_pointer;
3122 for (group_pointer_type current_group = end_iterator.group_pointer; current_group !=
nullptr; current_group = current_group->previous_group,
end = pointer_cast<aligned_pointer_type>(current_group->skipfield))
3124 if (it.group_pointer == current_group && std::greater_equal()(it.element_pointer, current_group->elements) && std::less()(it.element_pointer,
end))
3126 return (*it.skipfield_pointer == 0);
3149 assert(&source !=
this);
3151 if (source.total_size == 0)
3157 if (source.min_block_capacity < min_block_capacity || source.max_block_capacity > max_block_capacity)
3159 for (group_pointer_type current_group = source.begin_iterator.group_pointer; current_group !=
nullptr; current_group = current_group->next_group)
3161 if (current_group->capacity < min_block_capacity || current_group->capacity > max_block_capacity)
3163 #ifdef PLF_EXCEPTIONS_SUPPORT
3164 throw std::length_error(
"A source memory block capacity is outside of the destination's minimum or maximum memory block capacity limits - please change either the source or the destination's min/max block capacity limits using reshape() before calling splice() in this case");
3173 group_pointer_type
const source_unused_groups = source.unused_groups_head, unused_groups_head_original = unused_groups_head;
3174 source.unused_groups_head =
nullptr;
3175 unused_groups_head =
nullptr;
3177 if (total_size != 0)
3180 if ((pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer) > (pointer_cast<aligned_pointer_type>(source.end_iterator.group_pointer->skipfield) - source.end_iterator.element_pointer))
3185 const skipfield_type source_hive_limits[2] = {source.min_block_capacity, source.max_block_capacity};
3186 source.min_block_capacity = min_block_capacity;
3187 source.max_block_capacity = max_block_capacity;
3188 min_block_capacity = source_hive_limits[0];
3189 max_block_capacity = source_hive_limits[1];
3194 if (source.erasure_groups_head !=
nullptr)
3196 if (erasure_groups_head !=
nullptr)
3198 group_pointer_type tail_group = erasure_groups_head;
3200 while (tail_group->erasures_list_next_group !=
nullptr)
3202 tail_group = tail_group->erasures_list_next_group;
3205 tail_group->erasures_list_next_group = source.erasure_groups_head;
3206 source.erasure_groups_head->erasures_list_previous_group = tail_group;
3210 erasure_groups_head = source.erasure_groups_head;
3215 const skipfield_type distance_to_end =
static_cast<skipfield_type
>(pointer_cast<aligned_pointer_type>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer);
3217 if (distance_to_end != 0)
3220 const skipfield_type previous_node_value = *(end_iterator.skipfield_pointer - 1);
3222 if (previous_node_value == 0)
3224 *end_iterator.skipfield_pointer = distance_to_end;
3225 *(end_iterator.skipfield_pointer + distance_to_end - 1) = distance_to_end;
3227 if (distance_to_end > 2)
3229 std::memset(
static_cast<void *
>(end_iterator.skipfield_pointer + 1), 1,
sizeof(skipfield_type) * (distance_to_end - 2));
3232 const skipfield_type index =
static_cast<skipfield_type
>(end_iterator.element_pointer - end_iterator.group_pointer->elements);
3234 if (end_iterator.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
3236 edit_free_list_next(end_iterator.group_pointer->elements + end_iterator.group_pointer->free_list_head, index);
3240 end_iterator.group_pointer->erasures_list_next_group = erasure_groups_head;
3242 if (erasure_groups_head !=
nullptr)
3244 erasure_groups_head->erasures_list_previous_group = end_iterator.group_pointer;
3247 erasure_groups_head = end_iterator.group_pointer;
3250 edit_free_list_head(end_iterator.element_pointer, end_iterator.group_pointer->free_list_head);
3251 end_iterator.group_pointer->free_list_head = index;
3255 *(end_iterator.skipfield_pointer - previous_node_value) = *(end_iterator.skipfield_pointer + distance_to_end - 1) =
static_cast<skipfield_type
>(previous_node_value + distance_to_end);
3257 if (distance_to_end > 1)
3259 std::memset(
static_cast<void *
>(end_iterator.skipfield_pointer), 1,
sizeof(skipfield_type) * (distance_to_end - 1));
3266 end_iterator.group_pointer->next_group = source.begin_iterator.group_pointer;
3267 source.begin_iterator.group_pointer->previous_group = end_iterator.group_pointer;
3270 if (source.begin_iterator.group_pointer->group_number <= end_iterator.group_pointer->group_number)
3274 for (group_pointer_type current_group = source.begin_iterator.group_pointer; current_group !=
nullptr; current_group = current_group->next_group, ++source_group_count) {}
3276 if ((std::numeric_limits<size_type>::max() - end_iterator.group_pointer->group_number) >= source_group_count)
3278 update_subsequent_group_numbers(end_iterator.group_pointer->group_number + 1u, source.begin_iterator.group_pointer);
3282 reset_group_numbers();
3286 end_iterator = source.end_iterator;
3287 total_size += source.total_size;
3288 total_capacity += source.total_capacity;
3292 *
this = std::move(source);
3295 for (group_pointer_type current = unused_groups_head_original; current !=
nullptr; current = current->next_group)
3297 total_capacity += current->capacity;
3303 unused_groups_head = unused_groups_head_original;
3308 if (source_unused_groups !=
nullptr)
3310 size_type source_unused_groups_capacity = 0;
3313 for (group_pointer_type current = source_unused_groups; current !=
nullptr; current = current->next_group)
3315 source_unused_groups_capacity += current->capacity;
3318 total_capacity -= source_unused_groups_capacity;
3319 source.total_capacity = source_unused_groups_capacity;
3322 source.unused_groups_head = source_unused_groups->next_group;
3323 source.begin_iterator.group_pointer = source_unused_groups;
3324 source.begin_iterator.element_pointer = source_unused_groups->elements;
3325 source.begin_iterator.skipfield_pointer = source_unused_groups->skipfield;
3326 source.end_iterator = source.begin_iterator;
3327 source_unused_groups->reset(0,
nullptr,
nullptr, 0);
3335 splice(std::move(source));
3342 struct item_index_tuple
3348 original_location(_item),
3349 original_index(_index)
3355 template <
class comparison_function>
3356 struct sort_dereferencer
3358 comparison_function stored_instance;
3360 explicit sort_dereferencer(
const comparison_function &function_instance):
3361 stored_instance(function_instance)
3364 bool operator() (
const item_index_tuple first,
const item_index_tuple second)
3366 return stored_instance(*(first.original_location), *(second.original_location));
3374 template <
class comparison_function>
3375 void sort(comparison_function compare)
3382 if constexpr ((std::is_trivially_copyable<element_type>::value || std::is_move_assignable<element_type>::value) &&
sizeof(element_type) <=
sizeof(element_type *) * 2)
3384 element_type *
const sort_array = std::allocator_traits<allocator_type>::allocate(*
this, total_size,
nullptr), *
const end = sort_array + total_size;
3386 if constexpr (!std::is_trivially_copyable<element_type>::value && std::is_move_assignable<element_type>::value)
3388 std::uninitialized_copy(std::make_move_iterator(begin_iterator), std::make_move_iterator(end_iterator), sort_array);
3392 std::uninitialized_copy(begin_iterator, end_iterator, sort_array);
3395 std::sort(sort_array,
end, compare);
3397 if constexpr (!std::is_trivially_copyable<element_type>::value && std::is_move_assignable<element_type>::value)
3399 std::copy(std::make_move_iterator(sort_array), std::make_move_iterator(
end), begin_iterator);
3403 std::copy(sort_array,
end, begin_iterator);
3405 if (!std::is_trivially_destructible<element_type>::value)
3407 for (element_type *current = sort_array; current !=
end; ++current)
3409 std::allocator_traits<allocator_type>::destroy(*
this, current);
3414 std::allocator_traits<allocator_type>::deallocate(*
this, sort_array, total_size);
3418 tuple_pointer_type
const sort_array = std::allocator_traits<tuple_allocator_type>::allocate(tuple_allocator, total_size,
nullptr);
3419 tuple_pointer_type tuple_pointer = sort_array;
3424 for (
iterator current_element = begin_iterator; current_element != end_iterator; ++current_element, ++tuple_pointer, ++index)
3426 std::allocator_traits<tuple_allocator_type>::construct(tuple_allocator, tuple_pointer, &*current_element, index);
3430 std::sort(sort_array, tuple_pointer, sort_dereferencer<comparison_function>(compare));
3435 for (tuple_pointer_type current_tuple = sort_array; current_tuple != tuple_pointer; ++current_tuple, ++index)
3437 if (current_tuple->original_index != index)
3439 element_type end_value = std::move(*(current_tuple->original_location));
3441 size_type source_index = current_tuple->original_index;
3445 *(sort_array[destination_index].original_location) = std::move(*(sort_array[source_index].original_location));
3446 destination_index = source_index;
3447 source_index = sort_array[destination_index].original_index;
3448 sort_array[destination_index].original_index = destination_index;
3449 }
while (source_index != index);
3451 *(sort_array[destination_index].original_location) = std::move(end_value);
3455 std::allocator_traits<tuple_allocator_type>::deallocate(tuple_allocator, sort_array, total_size);
3463 sort(std::less<element_type>());
3468 template <
class comparison_function>
3480 if (compare(*current, *previous))
3482 const size_type original_count = ++count;
3485 while(last != end_iterator && compare(*last, *previous))
3493 if (count != original_count)
3495 current =
erase(current, last);
3499 current =
erase(current);
3504 previous = current++;
3515 return unique(std::equal_to<element_type>());
3520 void swap(
hive &source)
noexcept(std::allocator_traits<allocator_type>::propagate_on_container_swap::value || std::allocator_traits<allocator_type>::is_always_equal::value)
3522 assert(&source !=
this);
3524 if constexpr (std::allocator_traits<allocator_type>::is_always_equal::value && std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
3526 char temp[
sizeof(
hive)];
3527 std::memcpy(&temp,
static_cast<void *
>(
this),
sizeof(
hive));
3528 std::memcpy(
static_cast<void *
>(
this),
static_cast<void *
>(&source),
sizeof(
hive));
3529 std::memcpy(
static_cast<void *
>(&source), &temp,
sizeof(
hive));
3531 else if constexpr (std::is_move_assignable<group_pointer_type>::value && std::is_move_assignable<aligned_pointer_type>::value && std::is_move_assignable<skipfield_pointer_type>::value && std::is_move_constructible<group_pointer_type>::value && std::is_move_constructible<aligned_pointer_type>::value && std::is_move_constructible<skipfield_pointer_type>::value)
3533 hive temp(std::move(source));
3534 source = std::move(*
this);
3535 *
this = std::move(temp);
3539 const iterator swap_end_iterator = end_iterator, swap_begin_iterator = begin_iterator;
3540 const group_pointer_type swap_erasure_groups_head = erasure_groups_head, swap_unused_groups_head = unused_groups_head;
3541 const size_type swap_total_size = total_size, swap_total_capacity = total_capacity;
3542 const skipfield_type swap_min_block_capacity = min_block_capacity, swap_max_block_capacity = max_block_capacity;
3544 end_iterator = source.end_iterator;
3545 begin_iterator = source.begin_iterator;
3546 erasure_groups_head = source.erasure_groups_head;
3547 unused_groups_head = source.unused_groups_head;
3548 total_size = source.total_size;
3549 total_capacity = source.total_capacity;
3550 min_block_capacity = source.min_block_capacity;
3551 max_block_capacity = source.max_block_capacity;
3553 source.end_iterator = swap_end_iterator;
3554 source.begin_iterator = swap_begin_iterator;
3555 source.erasure_groups_head = swap_erasure_groups_head;
3556 source.unused_groups_head = swap_unused_groups_head;
3557 source.total_size = swap_total_size;
3558 source.total_capacity = swap_total_capacity;
3559 source.min_block_capacity = swap_min_block_capacity;
3560 source.max_block_capacity = swap_max_block_capacity;
3562 if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_swap::value && !std::allocator_traits<allocator_type>::is_always_equal::value)
3564 allocator_type swap_allocator = std::move(
static_cast<allocator_type &
>(source));
3565 static_cast<allocator_type &
>(source) = std::move(
static_cast<allocator_type &
>(*
this));
3566 static_cast<allocator_type &
>(*this) = std::move(swap_allocator);
3569 group_allocator = group_allocator_type(*
this);
3570 aligned_struct_allocator = aligned_struct_allocator_type(*
this);
3571 skipfield_allocator = skipfield_allocator_type(*
this);
3572 tuple_allocator = tuple_allocator_type(*
this);
3573 source.group_allocator = group_allocator_type(source);
3574 source.aligned_struct_allocator = aligned_struct_allocator_type(source);
3575 source.skipfield_allocator = skipfield_allocator_type(source);
3576 source.tuple_allocator = tuple_allocator_type(source);
3587 end_iterator.group_pointer->next_group = unused_groups_head;
3589 for(group_pointer_type current = begin_iterator.group_pointer; current !=
nullptr; current = current->next_group)
3591 memory_use +=
sizeof(group) + (get_aligned_block_capacity(current->capacity) *
sizeof(aligned_allocation_struct));
3594 end_iterator.group_pointer->next_group =
nullptr;
3603 template <
bool is_const>
3607 typedef typename hive::group_pointer_type group_pointer_type;
3608 typedef typename hive::aligned_pointer_type aligned_pointer_type;
3609 typedef typename hive::skipfield_pointer_type skipfield_pointer_type;
3611 group_pointer_type group_pointer;
3612 aligned_pointer_type element_pointer;
3613 skipfield_pointer_type skipfield_pointer;
3622 typedef typename std::conditional_t<is_const, typename hive::const_pointer, typename hive::pointer>
pointer;
3623 typedef typename std::conditional_t<is_const, typename hive::const_reference, typename hive::reference>
reference;
3629 template <hive_iterator_concept it_type,
typename distance_type>
3632 template <hive_iterator_concept it_type>
3633 friend it_type
std::next(it_type it,
const typename std::iterator_traits<it_type>::difference_type
distance);
3635 template <hive_iterator_concept it_type>
3636 friend it_type
std::prev(it_type it,
const typename std::iterator_traits<it_type>::difference_type
distance);
3638 template <hive_iterator_concept it_type>
3639 friend typename std::iterator_traits<it_type>::difference_type
std::distance(
const it_type first,
const it_type last);
3644 group_pointer(
nullptr),
3645 element_pointer(
nullptr),
3646 skipfield_pointer(
nullptr)
3652 group_pointer(source.group_pointer),
3653 element_pointer(source.element_pointer),
3654 skipfield_pointer(source.skipfield_pointer)
3659 template <
bool is_const_it = is_const,
class = std::enable_if_t<is_const_it> >
3661 group_pointer(source.group_pointer),
3662 element_pointer(source.element_pointer),
3663 skipfield_pointer(source.skipfield_pointer)
3669 group_pointer(std::move(source.group_pointer)),
3670 element_pointer(std::move(source.element_pointer)),
3671 skipfield_pointer(std::move(source.skipfield_pointer))
3676 template <
bool is_const_it = is_const,
class = std::enable_if_t<is_const_it> >
3678 group_pointer(std::move(source.group_pointer)),
3679 element_pointer(std::move(source.element_pointer)),
3680 skipfield_pointer(std::move(source.skipfield_pointer))
3687 group_pointer = source.group_pointer;
3688 element_pointer = source.element_pointer;
3689 skipfield_pointer = source.skipfield_pointer;
3695 template <
bool is_const_it = is_const,
class = std::enable_if_t<is_const_it> >
3698 group_pointer = source.group_pointer;
3699 element_pointer = source.element_pointer;
3700 skipfield_pointer = source.skipfield_pointer;
3708 assert(&source !=
this);
3709 group_pointer = std::move(source.group_pointer);
3710 element_pointer = std::move(source.element_pointer);
3711 skipfield_pointer = std::move(source.skipfield_pointer);
3717 template <
bool is_const_it = is_const,
class = std::enable_if_t<is_const_it> >
3720 group_pointer = std::move(source.group_pointer);
3721 element_pointer = std::move(source.element_pointer);
3722 skipfield_pointer = std::move(source.skipfield_pointer);
3730 return (element_pointer == rh.element_pointer);
3737 return (element_pointer == rh.element_pointer);
3744 return (element_pointer != rh.element_pointer);
3751 return (element_pointer != rh.element_pointer);
3758 return *pointer_cast<pointer>(element_pointer);
3765 return pointer_cast<pointer>(element_pointer);
3772 assert(group_pointer !=
nullptr);
3773 skipfield_type skip = *(++skipfield_pointer);
3775 if ((element_pointer +=
static_cast<size_type>(skip) + 1u) == pointer_cast<aligned_pointer_type>(group_pointer->skipfield) && group_pointer->next_group !=
nullptr)
3777 group_pointer = group_pointer->next_group;
3778 const aligned_pointer_type elements = group_pointer->elements;
3779 const skipfield_pointer_type skipfield = group_pointer->skipfield;
3781 element_pointer = elements + skip;
3782 skipfield_pointer = skipfield;
3785 skipfield_pointer += skip;
3802 assert(group_pointer !=
nullptr);
3804 if (element_pointer != group_pointer->elements)
3806 const skipfield_type skip = *(--skipfield_pointer);
3807 skipfield_pointer -= skip;
3809 if ((element_pointer -=
static_cast<size_type>(skip) + 1u) != group_pointer->elements - 1)
3815 group_pointer = group_pointer->previous_group;
3816 const skipfield_pointer_type skipfield = group_pointer->skipfield + group_pointer->capacity - 1;
3817 const skipfield_type skip = *skipfield;
3818 element_pointer = (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - 1) - skip;
3819 skipfield_pointer = skipfield - skip;
3835 template <
bool is_const_it>
3838 return ((group_pointer == rh.group_pointer) & std::greater()(element_pointer, rh.element_pointer)) ||
3839 (group_pointer != rh.group_pointer && group_pointer->group_number > rh.group_pointer->group_number);
3844 template <
bool is_const_it>
3852 template <
bool is_const_it>
3855 return !(rh > *
this);
3860 template <
bool is_const_it>
3863 return !(*
this > rh);
3868 template <
bool is_const_it>
3871 return (element_pointer == rh.element_pointer) ? std::strong_ordering::equal : ((*
this > rh) ? std::strong_ordering::greater : std::strong_ordering::less);
3878 hive_iterator(
const group_pointer_type group_p,
const aligned_pointer_type element_p,
const skipfield_pointer_type skipfield_p)
noexcept:
3879 group_pointer(group_p),
3880 element_pointer(element_p),
3881 skipfield_pointer(skipfield_p)
3890 assert(group_pointer !=
nullptr);
3909 if (group_pointer->next_group ==
nullptr && element_pointer == pointer_cast<aligned_pointer_type>(group_pointer->skipfield))
3916 if (element_pointer != group_pointer->elements + *(group_pointer->skipfield))
3918 const difference_type distance_from_end = pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - element_pointer;
3920 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3928 else if (group_pointer->next_group ==
nullptr)
3930 element_pointer += distance_from_end;
3931 skipfield_pointer += distance_from_end;
3941 const skipfield_pointer_type endpoint = skipfield_pointer + distance_from_end;
3945 skipfield_pointer += *++skipfield_pointer;
3948 if (skipfield_pointer == endpoint)
3954 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3959 if (group_pointer->next_group ==
nullptr)
3961 element_pointer = pointer_cast<aligned_pointer_type>(group_pointer->skipfield);
3966 group_pointer = group_pointer->next_group;
3970 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3971 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3980 if (group_pointer->next_group ==
nullptr)
3982 element_pointer = pointer_cast<aligned_pointer_type>(group_pointer->skipfield);
3983 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity;
3986 else if ((
distance -= group_pointer->size) == 0)
3988 group_pointer = group_pointer->next_group;
3989 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3990 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3995 group_pointer = group_pointer->next_group;
4001 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4003 element_pointer = group_pointer->elements +
distance;
4004 skipfield_pointer = group_pointer->skipfield +
distance;
4009 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4013 skipfield_pointer += *++skipfield_pointer;
4016 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4025 if(group_pointer->previous_group ==
nullptr && element_pointer == group_pointer->elements + *(group_pointer->skipfield))
4033 if (element_pointer != pointer_cast<aligned_pointer_type>(group_pointer->skipfield))
4035 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4039 if (
distance <= distance_from_beginning)
4045 else if (group_pointer->previous_group ==
nullptr)
4047 element_pointer = group_pointer->elements;
4048 skipfield_pointer = group_pointer->skipfield;
4053 distance -= distance_from_beginning;
4058 const skipfield_pointer_type beginning_point = group_pointer->skipfield + *(group_pointer->skipfield);
4060 while(skipfield_pointer != beginning_point)
4062 skipfield_pointer -= *--skipfield_pointer;
4066 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4071 if (group_pointer->previous_group ==
nullptr)
4073 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4074 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4079 group_pointer = group_pointer->previous_group;
4086 if (group_pointer->previous_group ==
nullptr)
4088 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4089 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4094 group_pointer = group_pointer->previous_group;
4101 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4102 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4105 else if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4107 element_pointer = pointer_cast<aligned_pointer_type>(group_pointer->skipfield) -
distance;
4108 skipfield_pointer = (group_pointer->skipfield + group_pointer->size) -
distance;
4113 skipfield_pointer = group_pointer->skipfield + (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - group_pointer->elements);
4117 skipfield_pointer -= *--skipfield_pointer;
4120 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4142 assert(!(group_pointer ==
nullptr) && !(last.group_pointer ==
nullptr));
4144 if (last.element_pointer == element_pointer)
4151 const bool swap = iterator1 > iterator2;
4159 if (iterator1.group_pointer != iterator2.group_pointer)
4162 if (iterator1.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4164 distance +=
static_cast<difference_type>(pointer_cast<aligned_pointer_type>(iterator1.group_pointer->skipfield) - iterator1.element_pointer);
4166 else if (iterator1.element_pointer == iterator1.group_pointer->elements + *(iterator1.group_pointer->skipfield))
4172 const skipfield_pointer_type endpoint = iterator1.skipfield_pointer + (pointer_cast<aligned_pointer_type>(iterator1.group_pointer->skipfield) - iterator1.element_pointer);
4174 while (iterator1.skipfield_pointer != endpoint)
4176 iterator1.skipfield_pointer += *++iterator1.skipfield_pointer;
4182 iterator1.group_pointer = iterator1.group_pointer->next_group;
4184 while (iterator1.group_pointer != iterator2.group_pointer)
4187 iterator1.group_pointer = iterator1.group_pointer->next_group;
4190 iterator1.skipfield_pointer = iterator1.group_pointer->skipfield + *(iterator1.group_pointer->skipfield);
4194 if (iterator2.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4196 distance += iterator2.skipfield_pointer - iterator1.skipfield_pointer;
4198 else if (iterator1.element_pointer == iterator2.group_pointer->elements + *(iterator2.group_pointer->skipfield) && iterator2.element_pointer + 1 + *(iterator2.skipfield_pointer + 1) == pointer_cast<aligned_pointer_type>(iterator2.group_pointer->skipfield))
4204 while (iterator1.skipfield_pointer != iterator2.skipfield_pointer)
4206 iterator1.skipfield_pointer += *++iterator1.skipfield_pointer;
4227 template <
bool is_const_r>
4231 typedef typename hive::group_pointer_type group_pointer_type;
4232 typedef typename hive::aligned_pointer_type aligned_pointer_type;
4233 typedef typename hive::skipfield_pointer_type skipfield_pointer_type;
4245 typedef typename std::conditional_t<is_const_r, typename hive::const_pointer, typename hive::pointer>
pointer;
4246 typedef typename std::conditional_t<is_const_r, typename hive::const_reference, typename hive::reference>
reference;
4250 template <hive_iterator_concept it_type,
typename distance_type>
4253 template <hive_iterator_concept it_type>
4254 friend it_type
std::next(it_type it,
const typename std::iterator_traits<it_type>::difference_type
distance);
4256 template <hive_iterator_concept it_type>
4257 friend it_type
std::prev(it_type it,
const typename std::iterator_traits<it_type>::difference_type
distance);
4259 template <hive_iterator_concept it_type>
4260 friend typename std::iterator_traits<it_type>::difference_type
std::distance(
const it_type first,
const it_type last);
4273 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4286 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4295 current(std::move(source.current))
4299 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4301 current(std::move(source.current))
4313 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4329 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4339 assert(&source !=
this);
4340 current = std::move(source.current);
4345 template <
bool is_const_rit = is_const_r,
class = std::enable_if_t<is_const_rit> >
4348 assert(&source !=
this);
4349 current = std::move(source.current);
4357 return (
current == rh.current);
4364 return (
current == rh.current);
4371 return (
current != rh.current);
4378 return (
current != rh.current);
4385 return *pointer_cast<pointer>(
current.element_pointer);
4392 return pointer_cast<pointer>(
current.element_pointer);
4400 group_pointer_type &group_pointer =
current.group_pointer;
4401 aligned_pointer_type &element_pointer =
current.element_pointer;
4402 skipfield_pointer_type &skipfield_pointer =
current.skipfield_pointer;
4404 assert(group_pointer !=
nullptr);
4406 if (element_pointer != group_pointer->elements)
4408 element_pointer -=
static_cast<size_type>(*(--skipfield_pointer)) + 1u;
4409 skipfield_pointer -= *skipfield_pointer;
4411 if (!(element_pointer == group_pointer->elements - 1 && group_pointer->previous_group ==
nullptr))
4417 if (group_pointer->previous_group !=
nullptr)
4419 group_pointer = group_pointer->previous_group;
4420 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity - 1;
4421 element_pointer = (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - 1) - *skipfield_pointer;
4422 skipfield_pointer -= *skipfield_pointer;
4427 --skipfield_pointer;
4468 template <
bool is_const_it>
4471 return (rh.current >
current);
4476 template <
bool is_const_it>
4479 return (
current > rh.current);
4484 template <
bool is_const_it>
4487 return !(
current > rh.current);
4492 template <
bool is_const_it>
4495 return !(rh.current >
current);
4500 template <
bool is_const_it>
4503 return (rh.current <=>
current);
4510 hive_reverse_iterator(
const group_pointer_type group_p,
const aligned_pointer_type element_p,
const skipfield_pointer_type skipfield_p)
noexcept:
current(group_p, element_p, skipfield_p) {}
4518 return last.current.distance(
current);
4526 group_pointer_type &group_pointer =
current.group_pointer;
4527 aligned_pointer_type &element_pointer =
current.element_pointer;
4528 skipfield_pointer_type &skipfield_pointer =
current.skipfield_pointer;
4530 assert(element_pointer !=
nullptr);
4534 if (group_pointer->previous_group ==
nullptr && element_pointer == group_pointer->elements - 1)
4539 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4541 const difference_type distance_from_beginning = element_pointer - group_pointer->elements;
4543 if (
distance <= distance_from_beginning)
4549 else if (group_pointer->previous_group ==
nullptr)
4551 element_pointer = group_pointer->elements - 1;
4552 skipfield_pointer = group_pointer->skipfield - 1;
4557 distance -= distance_from_beginning;
4562 const skipfield_pointer_type beginning_point = group_pointer->skipfield + *(group_pointer->skipfield);
4564 while(skipfield_pointer != beginning_point)
4566 skipfield_pointer -= *--skipfield_pointer;
4570 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4575 if (group_pointer->previous_group ==
nullptr)
4577 element_pointer = group_pointer->elements - 1;
4578 skipfield_pointer = group_pointer->skipfield - 1;
4583 group_pointer = group_pointer->previous_group;
4589 if (group_pointer->previous_group ==
nullptr)
4591 element_pointer = group_pointer->elements - 1;
4592 skipfield_pointer = group_pointer->skipfield - 1;
4597 group_pointer = group_pointer->previous_group;
4604 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4605 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4608 else if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4610 element_pointer = (group_pointer->elements + group_pointer->size) -
distance;
4611 skipfield_pointer = (group_pointer->skipfield + group_pointer->size) -
distance;
4616 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity;
4620 skipfield_pointer -= *--skipfield_pointer;
4623 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4629 if (group_pointer->next_group ==
nullptr && (element_pointer == (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - 1) - *(group_pointer->skipfield + (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - group_pointer->elements) - 1)))
4634 if (element_pointer != group_pointer->elements + *(group_pointer->skipfield))
4636 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4638 const difference_type distance_from_end = pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - element_pointer;
4646 else if (group_pointer->next_group ==
nullptr)
4648 element_pointer += distance_from_end - 1;
4649 skipfield_pointer += distance_from_end - 1;
4659 const skipfield_pointer_type endpoint = skipfield_pointer + (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - element_pointer);
4663 skipfield_pointer += *++skipfield_pointer;
4666 if (skipfield_pointer == endpoint)
4672 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
4677 if (group_pointer->next_group ==
nullptr)
4683 group_pointer = group_pointer->next_group;
4687 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4688 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4697 if (group_pointer->next_group ==
nullptr)
4699 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity - 1;
4700 element_pointer = (pointer_cast<aligned_pointer_type>(group_pointer->skipfield) - 1) - *skipfield_pointer;
4701 skipfield_pointer -= *skipfield_pointer;
4704 else if ((
distance -= group_pointer->size) == 0)
4706 group_pointer = group_pointer->next_group;
4707 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
4708 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4713 group_pointer = group_pointer->next_group;
4719 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
4721 element_pointer = group_pointer->elements +
distance;
4722 skipfield_pointer = group_pointer->skipfield +
distance;
4727 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
4731 skipfield_pointer += *++skipfield_pointer;
4734 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);