219template <
class element_type,
class element_allocator_type = std::allocator<element_type>,
typename element_skipfield_type =
unsigned short >
class colony :
private element_allocator_type
224 typedef element_type value_type;
225 typedef element_allocator_type allocator_type;
226 typedef element_skipfield_type skipfield_type;
228 #ifdef PLF_COLONY_ALIGNMENT_SUPPORT
229 typedef typename std::aligned_storage<sizeof(element_type), (sizeof(element_type) > (
sizeof(element_skipfield_type) * 2)) ?
alignof(element_type) : (
sizeof(element_skipfield_type) * 2)>::type aligned_element_type;
231 typedef element_type aligned_element_type;
234 #ifdef PLF_COLONY_ALLOCATOR_TRAITS_SUPPORT
235 typedef typename std::allocator_traits<element_allocator_type>::size_type size_type;
236 typedef typename std::allocator_traits<element_allocator_type>::difference_type difference_type;
237 typedef element_type & reference;
238 typedef const element_type & const_reference;
239 typedef typename std::allocator_traits<element_allocator_type>::pointer pointer;
240 typedef typename std::allocator_traits<element_allocator_type>::const_pointer const_pointer;
242 typedef typename element_allocator_type::size_type size_type;
243 typedef typename element_allocator_type::difference_type difference_type;
244 typedef typename element_allocator_type::reference reference;
245 typedef typename element_allocator_type::const_reference const_reference;
246 typedef typename element_allocator_type::pointer pointer;
247 typedef typename element_allocator_type::const_pointer const_pointer;
270 #ifdef PLF_COLONY_ALLOCATOR_TRAITS_SUPPORT
271 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<aligned_element_type> aligned_element_allocator_type;
272 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<group> group_allocator_type;
273 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<skipfield_type> skipfield_allocator_type;
274 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<unsigned char> uchar_allocator_type;
276 typedef typename std::allocator_traits<aligned_element_allocator_type>::pointer aligned_pointer_type;
277 typedef typename std::allocator_traits<group_allocator_type>::pointer group_pointer_type;
278 typedef typename std::allocator_traits<skipfield_allocator_type>::pointer skipfield_pointer_type;
279 typedef typename std::allocator_traits<uchar_allocator_type>::pointer uchar_pointer_type;
281 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<pointer> pointer_allocator_type;
283 typedef typename element_allocator_type::template rebind<aligned_element_type>::other aligned_element_allocator_type;
284 typedef typename element_allocator_type::template rebind<group>::other group_allocator_type;
285 typedef typename element_allocator_type::template rebind<skipfield_type>::other skipfield_allocator_type;
286 typedef typename element_allocator_type::template rebind<unsigned char>::other uchar_allocator_type;
288 typedef typename aligned_element_allocator_type::pointer aligned_pointer_type;
289 typedef typename group_allocator_type::pointer group_pointer_type;
290 typedef typename skipfield_allocator_type::pointer skipfield_pointer_type;
291 typedef typename uchar_allocator_type::pointer uchar_pointer_type;
293 typedef typename element_allocator_type::template rebind<pointer>::other pointer_allocator_type;
299 struct group :
private uchar_allocator_type
301 aligned_pointer_type last_endpoint;
302 group_pointer_type next_group;
303 const aligned_pointer_type elements;
304 const skipfield_pointer_type skipfield;
305 group_pointer_type previous_group;
306 skipfield_type free_list_head;
307 const skipfield_type capacity;
308 skipfield_type number_of_elements;
309 group_pointer_type erasures_list_next_group;
310 size_type group_number;
313 #ifdef PLF_COLONY_VARIADICS_SUPPORT
314 group(
const skipfield_type elements_per_group, group_pointer_type
const previous = NULL):
315 last_endpoint(
reinterpret_cast<aligned_pointer_type
>(PLF_COLONY_ALLOCATE_INITIALIZATION(uchar_allocator_type, ((elements_per_group * (
sizeof(aligned_element_type))) + ((
static_cast<size_type
>(elements_per_group) + 1u) *
sizeof(skipfield_type))), (previous == NULL) ? 0 : previous->elements))),
317 elements(last_endpoint++),
318 skipfield(
reinterpret_cast<skipfield_pointer_type
>(elements + elements_per_group)),
319 previous_group(previous),
320 free_list_head(std::numeric_limits<skipfield_type>::max()),
321 capacity(elements_per_group),
322 number_of_elements(1),
323 erasures_list_next_group(NULL),
324 group_number((previous == NULL) ? 0 : previous->group_number + 1u)
327 std::memset(&*skipfield, 0,
sizeof(skipfield_type) * (
static_cast<size_type
>(elements_per_group) + 1u));
332 group(
const skipfield_type elements_per_group, group_pointer_type
const previous = NULL):
333 last_endpoint(
reinterpret_cast<aligned_pointer_type
>(PLF_COLONY_ALLOCATE_INITIALIZATION(uchar_allocator_type, ((elements_per_group * (
sizeof(aligned_element_type))) + (
static_cast<size_type
>(elements_per_group + 1) *
sizeof(skipfield_type))), (previous == NULL) ? 0 : previous->elements))),
335 skipfield(
reinterpret_cast<skipfield_pointer_type
>(last_endpoint + elements_per_group)),
336 previous_group(previous),
337 capacity(elements_per_group)
339 std::memset(&*skipfield, 0,
sizeof(skipfield_type) * (elements_per_group + 1u));
345 group(
const group &source) PLF_COLONY_NOEXCEPT:
346 uchar_allocator_type(source),
347 last_endpoint(source.last_endpoint + 1),
349 elements(source.last_endpoint),
350 skipfield(source.skipfield),
351 previous_group(source.previous_group),
352 free_list_head(std::numeric_limits<skipfield_type>::max()),
353 capacity(source.capacity),
354 number_of_elements(1),
355 erasures_list_next_group(NULL),
356 group_number((source.previous_group == NULL) ? 0 : source.previous_group->group_number + 1u)
362 ~group() PLF_COLONY_NOEXCEPT
365 PLF_COLONY_DEALLOCATE(uchar_allocator_type, (*
this),
reinterpret_cast<uchar_pointer_type
>(elements), (capacity *
sizeof(aligned_element_type)) + ((
static_cast<size_type
>(capacity) + 1u) *
sizeof(skipfield_type)));
373 template <
bool flag,
class is_true,
class is_false>
struct choose;
375 template <
class is_true,
class is_false>
struct choose<true, is_true, is_false>
377 typedef is_true type;
380 template <
class is_true,
class is_false>
struct choose<false, is_true, is_false>
382 typedef is_false type;
393 group_pointer_type group_pointer;
394 aligned_pointer_type element_pointer;
395 skipfield_pointer_type skipfield_pointer;
398 typedef std::bidirectional_iterator_tag iterator_category;
399 typedef typename colony::value_type value_type;
400 typedef typename colony::difference_type difference_type;
401 typedef typename choose<is_const, typename colony::const_pointer, typename colony::pointer>::type pointer;
402 typedef typename choose<is_const, typename colony::const_reference, typename colony::reference>::type reference;
412 group_pointer = source.group_pointer;
413 element_pointer = source.element_pointer;
414 skipfield_pointer = source.skipfield_pointer;
422 group_pointer = source.group_pointer;
423 element_pointer = source.element_pointer;
424 skipfield_pointer = source.skipfield_pointer;
430 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
434 assert (&source !=
this);
435 group_pointer = std::move(source.group_pointer);
436 element_pointer = std::move(source.element_pointer);
437 skipfield_pointer = std::move(source.skipfield_pointer);
445 group_pointer = std::move(source.group_pointer);
446 element_pointer = std::move(source.element_pointer);
447 skipfield_pointer = std::move(source.skipfield_pointer);
454 inline PLF_COLONY_FORCE_INLINE
bool operator == (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
456 return (element_pointer == rh.element_pointer);
463 return (element_pointer == rh.element_pointer);
468 inline PLF_COLONY_FORCE_INLINE
bool operator != (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
470 return (element_pointer != rh.element_pointer);
477 return (element_pointer != rh.element_pointer);
482 inline PLF_COLONY_FORCE_INLINE reference operator * ()
const
484 return *(
reinterpret_cast<pointer
>(element_pointer));
489 inline PLF_COLONY_FORCE_INLINE pointer operator -> ()
const PLF_COLONY_NOEXCEPT
491 return reinterpret_cast<pointer
>(element_pointer);
496#if defined(_MSC_VER) && _MSC_VER <= 1600
502 assert(group_pointer != NULL);
503 assert(!(element_pointer == group_pointer->last_endpoint && group_pointer->next_group != NULL));
505 skipfield_type skip = *(++skipfield_pointer);
507 if ((element_pointer +=
static_cast<size_type
>(skip) + 1u) == group_pointer->last_endpoint && group_pointer->next_group != NULL)
509 group_pointer = group_pointer->next_group;
510 const aligned_pointer_type elements = group_pointer->elements;
511 const skipfield_pointer_type skipfield = group_pointer->skipfield;
513 element_pointer = elements + skip;
514 skipfield_pointer = skipfield;
517 skipfield_pointer += skip;
533 inline PLF_COLONY_FORCE_INLINE
void check_for_end_of_group_and_progress()
535 if (element_pointer == group_pointer->last_endpoint && group_pointer->next_group != NULL)
537 group_pointer = group_pointer->next_group;
538 const aligned_pointer_type elements = group_pointer->elements;
539 const skipfield_pointer_type skipfield = group_pointer->skipfield;
540 const skipfield_type skip = *skipfield;
541 element_pointer = elements + skip;
542 skipfield_pointer = skipfield + skip;
552 assert(group_pointer != NULL);
553 assert(!(element_pointer == group_pointer->elements && group_pointer->previous_group == NULL));
555 if (element_pointer != group_pointer->elements)
557 const skipfield_type skip = *(--skipfield_pointer);
558 skipfield_pointer -= skip;
560 if ((element_pointer -=
static_cast<size_type
>(skip) + 1u) != group_pointer->elements - 1)
566 group_pointer = group_pointer->previous_group;
567 const skipfield_pointer_type skipfield = group_pointer->skipfield + group_pointer->capacity - 1;
568 const skipfield_type skip = *skipfield;
569 element_pointer = (
reinterpret_cast<colony::aligned_pointer_type
>(group_pointer->skipfield) - 1) - skip;
570 skipfield_pointer = skipfield - skip;
586 inline bool operator > (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
588 return ((group_pointer == rh.group_pointer) & (element_pointer > rh.element_pointer)) || (group_pointer != rh.group_pointer && group_pointer->group_number > rh.group_pointer->group_number);
593 inline bool operator < (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
600 inline bool operator >= (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
602 return !(rh > *
this);
607 inline bool operator <= (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
609 return !(*
this > rh);
616 return ((group_pointer == rh.group_pointer) & (element_pointer > rh.element_pointer)) || (group_pointer != rh.group_pointer && group_pointer->group_number > rh.group_pointer->group_number);
630 return !(rh > *
this);
637 return !(*
this > rh);
642 #ifdef PLF_COLONY_CPP20_SUPPORT
643 inline int operator <=> (
const colony_iterator &rh)
const PLF_COLONY_NOEXCEPT
645 return (element_pointer == rh.element_pointer) ? 0 : ((*
this > rh) ? 1 : -1);
651 return (element_pointer == rh.element_pointer) ? 0 : ((*
this > rh) ? 1 : -1);
657 colony_iterator() PLF_COLONY_NOEXCEPT: group_pointer(NULL), element_pointer(NULL), skipfield_pointer(NULL) {}
663 colony_iterator(
const group_pointer_type group_p,
const aligned_pointer_type element_p,
const skipfield_pointer_type skipfield_p) PLF_COLONY_NOEXCEPT: group_pointer(group_p), element_pointer(element_p), skipfield_pointer(skipfield_p) {}
670 group_pointer(source.group_pointer),
671 element_pointer(source.element_pointer),
672 skipfield_pointer(source.skipfield_pointer)
677 group_pointer(source.group_pointer),
678 element_pointer(source.element_pointer),
679 skipfield_pointer(source.skipfield_pointer)
684 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
687 group_pointer(std::move(source.group_pointer)),
688 element_pointer(std::move(source.element_pointer)),
689 skipfield_pointer(std::move(source.skipfield_pointer))
691 assert (&source !=
this);
696 group_pointer(std::move(source.group_pointer)),
697 element_pointer(std::move(source.element_pointer)),
698 skipfield_pointer(std::move(source.skipfield_pointer))
717 typedef std::bidirectional_iterator_tag iterator_category;
718 typedef typename colony::value_type value_type;
719 typedef typename colony::difference_type difference_type;
720 typedef typename choose<r_is_const, typename colony::const_pointer, typename colony::pointer>::type pointer;
721 typedef typename choose<r_is_const, typename colony::const_reference, typename colony::reference>::type reference;
742 template<
bool is_const>
751 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
755 assert (&source !=
this);
756 it = std::move(source.it);
763 it = std::move(source.it);
772 return (it == rh.it);
779 return (it == rh.it);
786 return (it != rh.it);
793 return (it != rh.it);
798 inline PLF_COLONY_FORCE_INLINE reference operator * ()
const PLF_COLONY_NOEXCEPT
800 return *(
reinterpret_cast<pointer
>(it.element_pointer));
805 inline PLF_COLONY_FORCE_INLINE pointer * operator -> ()
const PLF_COLONY_NOEXCEPT
807 return reinterpret_cast<pointer
>(it.element_pointer);
815 colony::group_pointer_type &group_pointer = it.group_pointer;
816 colony::aligned_pointer_type &element_pointer = it.element_pointer;
817 colony::skipfield_pointer_type &skipfield_pointer = it.skipfield_pointer;
819 assert(group_pointer != NULL);
820 assert(!(element_pointer == group_pointer->elements - 1 && group_pointer->previous_group == NULL));
822 if (element_pointer != group_pointer->elements)
824 element_pointer -=
static_cast<size_type
>(*(--skipfield_pointer)) + 1u;
825 skipfield_pointer -= *skipfield_pointer;
827 if (!(element_pointer == group_pointer->elements - 1 && group_pointer->previous_group == NULL))
833 if (group_pointer->previous_group != NULL)
835 group_pointer = group_pointer->previous_group;
836 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity - 1;
837 element_pointer = (
reinterpret_cast<colony::aligned_pointer_type
>(group_pointer->skipfield) - 1) - *skipfield_pointer;
838 skipfield_pointer -= *skipfield_pointer;
862 assert(!(it.element_pointer == it.group_pointer->last_endpoint - 1 && it.group_pointer->next_group == NULL));
901 return !(it > rh.it);
908 return !(rh.it > it);
929 return !(it > rh.it);
936 return !(rh.it > it);
942 #ifdef PLF_COLONY_CPP20_SUPPORT
945 return (rh.it <=> it);
951 return (rh.it <=> it);
974 template<
bool is_const>
984 colony_reverse_iterator(
const group_pointer_type group_p,
const aligned_pointer_type element_p,
const skipfield_pointer_type skipfield_p) PLF_COLONY_NOEXCEPT: it(group_p, element_p, skipfield_p) {}
990 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
993 it(std::move(source.it))
995 assert (&source !=
this);
999 it(std::move(source.it))
1011 template <
bool condition,
class T =
void>
1012 struct plf_enable_if_c
1018 struct plf_enable_if_c<false, T>
1022 iterator end_iterator, begin_iterator;
1023 group_pointer_type groups_with_erasures_list_head;
1024 size_type total_number_of_elements, total_capacity;
1026 struct ebco_pair2 : pointer_allocator_type
1028 skipfield_type min_elements_per_group;
1029 explicit ebco_pair2(
const skipfield_type min_elements) PLF_COLONY_NOEXCEPT: min_elements_per_group(min_elements) {}
1030 } pointer_allocator_pair;
1032 struct ebco_pair : group_allocator_type
1034 skipfield_type max_elements_per_group;
1035 explicit ebco_pair(
const skipfield_type max_elements) PLF_COLONY_NOEXCEPT: max_elements_per_group(max_elements) {}
1036 } group_allocator_pair;
1041 #define PLF_COLONY_MIN_BLOCK_CAPACITY (sizeof(aligned_element_type) * 8 > (sizeof(plf::colony<element_type>) + sizeof(group)) * 2) ? 8 : (((sizeof(plf::colony<element_type>) + sizeof(group)) * 2) / sizeof(aligned_element_type))
1048 colony() PLF_COLONY_NOEXCEPT:
1049 element_allocator_type(element_allocator_type()),
1050 groups_with_erasures_list_head(NULL),
1051 total_number_of_elements(0),
1053 pointer_allocator_pair(PLF_COLONY_MIN_BLOCK_CAPACITY),
1054 group_allocator_pair(std::numeric_limits<skipfield_type>::max())
1056 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1058 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1059 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1065 colony(
const plf::limits capacities) PLF_COLONY_NOEXCEPT:
1066 element_allocator_type(element_allocator_type()),
1067 groups_with_erasures_list_head(NULL),
1068 total_number_of_elements(0),
1070 pointer_allocator_pair(
static_cast<skipfield_type
>(capacities.min)),
1071 group_allocator_pair(
static_cast<skipfield_type
>(capacities.max))
1073 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1074 assert((capacities.min > 2) & (capacities.min <= capacities.max));
1075 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
1077 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1078 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1086 explicit colony(
const element_allocator_type &alloc):
1087 element_allocator_type(alloc),
1088 groups_with_erasures_list_head(NULL),
1089 total_number_of_elements(0),
1091 pointer_allocator_pair(PLF_COLONY_MIN_BLOCK_CAPACITY),
1092 group_allocator_pair(std::numeric_limits<skipfield_type>::max())
1094 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1096 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1097 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1103 explicit colony(
const plf::limits capacities,
const element_allocator_type &alloc):
1104 element_allocator_type(alloc),
1105 groups_with_erasures_list_head(NULL),
1106 total_number_of_elements(0),
1108 pointer_allocator_pair(static_cast<skipfield_type>(capacities.min)),
1109 group_allocator_pair(static_cast<skipfield_type>(capacities.max))
1111 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1112 assert((capacities.min > 2) & (capacities.min <= capacities.max));
1113 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
1115 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1116 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1124 colony(
const colony &source):
1125 element_allocator_type(source),
1126 groups_with_erasures_list_head(NULL),
1127 total_number_of_elements(0),
1129 pointer_allocator_pair(static_cast<skipfield_type>((source.pointer_allocator_pair.min_elements_per_group > source.total_number_of_elements) ? source.pointer_allocator_pair.min_elements_per_group : ((source.total_number_of_elements > source.group_allocator_pair.max_elements_per_group) ? source.group_allocator_pair.max_elements_per_group : source.total_number_of_elements))),
1130 group_allocator_pair(source.group_allocator_pair.max_elements_per_group)
1132 insert(source.begin_iterator, source.end_iterator);
1133 pointer_allocator_pair.min_elements_per_group = source.pointer_allocator_pair.min_elements_per_group;
1140 colony(
const colony &source,
const allocator_type &alloc):
1141 element_allocator_type(alloc),
1142 groups_with_erasures_list_head(NULL),
1143 total_number_of_elements(0),
1145 pointer_allocator_pair(static_cast<skipfield_type>((source.pointer_allocator_pair.min_elements_per_group > source.total_number_of_elements) ? source.pointer_allocator_pair.min_elements_per_group : ((source.total_number_of_elements > source.group_allocator_pair.max_elements_per_group) ? source.group_allocator_pair.max_elements_per_group : source.total_number_of_elements))),
1146 group_allocator_pair(source.group_allocator_pair.max_elements_per_group)
1148 insert(source.begin_iterator, source.end_iterator);
1149 pointer_allocator_pair.min_elements_per_group = source.pointer_allocator_pair.min_elements_per_group;
1157 inline void blank() PLF_COLONY_NOEXCEPT
1159 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1160 if PLF_COLONY_CONSTEXPR (std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
1162 std::memset(
static_cast<void *
>(
this), 0, offsetof(colony, pointer_allocator_pair));
1167 end_iterator.group_pointer = NULL;
1168 end_iterator.element_pointer = NULL;
1169 end_iterator.skipfield_pointer = NULL;
1170 begin_iterator.group_pointer = NULL;
1171 begin_iterator.element_pointer = NULL;
1172 begin_iterator.skipfield_pointer = NULL;
1173 groups_with_erasures_list_head = NULL;
1174 total_number_of_elements = 0;
1185 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
1188 colony(colony &&source) PLF_COLONY_NOEXCEPT:
1189 element_allocator_type(source),
1190 end_iterator(std::move(source.end_iterator)),
1191 begin_iterator(std::move(source.begin_iterator)),
1192 groups_with_erasures_list_head(std::move(source.groups_with_erasures_list_head)),
1193 total_number_of_elements(source.total_number_of_elements),
1194 total_capacity(source.total_capacity),
1195 pointer_allocator_pair(source.pointer_allocator_pair.min_elements_per_group),
1196 group_allocator_pair(source.group_allocator_pair.max_elements_per_group)
1198 assert (&source !=
this);
1205 colony(colony &&source,
const allocator_type &alloc):
1206 element_allocator_type(alloc),
1207 end_iterator(std::move(source.end_iterator)),
1208 begin_iterator(std::move(source.begin_iterator)),
1209 groups_with_erasures_list_head(std::move(source.groups_with_erasures_list_head)),
1210 total_number_of_elements(source.total_number_of_elements),
1211 total_capacity(source.total_capacity),
1212 pointer_allocator_pair(source.pointer_allocator_pair.min_elements_per_group),
1213 group_allocator_pair(source.group_allocator_pair.max_elements_per_group)
1215 assert (&source !=
this);
1224 colony(
const size_type fill_number,
const element_type &element,
const plf::limits capacities =
plf::limits(PLF_COLONY_MIN_BLOCK_CAPACITY, std::numeric_limits<skipfield_type>::max()),
const element_allocator_type &alloc = element_allocator_type()):
1225 element_allocator_type(alloc),
1226 groups_with_erasures_list_head(NULL),
1227 total_number_of_elements(0),
1229 pointer_allocator_pair(static_cast<skipfield_type>(capacities.min)),
1230 group_allocator_pair(static_cast<skipfield_type>(capacities.max))
1232 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1233 assert((capacities.min > 2) & (capacities.min <= capacities.max));
1234 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
1236 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1237 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1240 insert(fill_number, element);
1247 template<
typename iterator_type>
1248 colony(
const typename plf_enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type &first,
const iterator_type &last,
const plf::limits capacities =
plf::limits(PLF_COLONY_MIN_BLOCK_CAPACITY, std::numeric_limits<skipfield_type>::max()),
const element_allocator_type &alloc = element_allocator_type()):
1249 element_allocator_type(alloc),
1250 groups_with_erasures_list_head(NULL),
1251 total_number_of_elements(0),
1253 pointer_allocator_pair(static_cast<skipfield_type>(capacities.min)),
1254 group_allocator_pair(static_cast<skipfield_type>(capacities.max))
1256 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1257 assert((capacities.min > 2) & (capacities.min <= capacities.max));
1258 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
1260 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1261 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1264 insert<iterator_type>(first, last);
1271 #ifdef PLF_COLONY_INITIALIZER_LIST_SUPPORT
1272 colony(
const std::initializer_list<element_type> &element_list,
const plf::limits capacities =
plf::limits(PLF_COLONY_MIN_BLOCK_CAPACITY, std::numeric_limits<skipfield_type>::max()),
const element_allocator_type &alloc = element_allocator_type()):
1273 element_allocator_type(alloc),
1274 groups_with_erasures_list_head(NULL),
1275 total_number_of_elements(0),
1277 pointer_allocator_pair(static_cast<skipfield_type>(capacities.min)),
1278 group_allocator_pair(static_cast<skipfield_type>(capacities.max))
1280 assert(std::numeric_limits<skipfield_type>::is_integer & !std::numeric_limits<skipfield_type>::is_signed);
1281 assert((capacities.min > 2) & (capacities.min <= capacities.max));
1282 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
1284 #ifndef PLF_COLONY_ALIGNMENT_SUPPORT
1285 assert(
sizeof(element_type) >=
sizeof(skipfield_type) * 2);
1288 insert(element_list);
1295 inline PLF_COLONY_FORCE_INLINE iterator begin() PLF_COLONY_NOEXCEPT
1297 return begin_iterator;
1302 inline PLF_COLONY_FORCE_INLINE const_iterator begin() const PLF_COLONY_NOEXCEPT
1304 return begin_iterator;
1309 inline PLF_COLONY_FORCE_INLINE iterator end() PLF_COLONY_NOEXCEPT
1311 return end_iterator;
1316 inline PLF_COLONY_FORCE_INLINE const_iterator end() const PLF_COLONY_NOEXCEPT
1318 return end_iterator;
1323 inline PLF_COLONY_FORCE_INLINE const_iterator cbegin() const PLF_COLONY_NOEXCEPT
1325 return begin_iterator;
1330 inline PLF_COLONY_FORCE_INLINE const_iterator cend() const PLF_COLONY_NOEXCEPT
1332 return end_iterator;
1337 inline reverse_iterator rbegin() const PLF_COLONY_NOEXCEPT
1339 return (end_iterator.group_pointer != NULL) ? ++reverse_iterator(end_iterator) : reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
1344 inline reverse_iterator rend() const PLF_COLONY_NOEXCEPT
1346 return reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
1351 inline const_reverse_iterator crbegin() const PLF_COLONY_NOEXCEPT
1353 return (end_iterator.group_pointer != NULL) ? ++const_reverse_iterator(end_iterator) : const_reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
1358 inline const_reverse_iterator crend() const PLF_COLONY_NOEXCEPT
1360 return const_reverse_iterator(begin_iterator.group_pointer, begin_iterator.element_pointer - 1, begin_iterator.skipfield_pointer - 1);
1365 ~colony() PLF_COLONY_NOEXCEPT
1374 void destroy_all_data() PLF_COLONY_NOEXCEPT
1376 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1377 if PLF_COLONY_CONSTEXPR (!(std::is_trivially_destructible<element_type>::value))
1380 if (total_number_of_elements != 0)
1382 total_number_of_elements = 0;
1386 const aligned_pointer_type end_pointer = begin_iterator.group_pointer->last_endpoint;
1390 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(begin_iterator.element_pointer));
1391 ++begin_iterator.skipfield_pointer;
1392 begin_iterator.element_pointer +=
static_cast<size_type
>(*begin_iterator.skipfield_pointer) + 1u;
1393 begin_iterator.skipfield_pointer +=
static_cast<size_type
>(*begin_iterator.skipfield_pointer);
1394 }
while(begin_iterator.element_pointer != end_pointer);
1396 const group_pointer_type next_group = begin_iterator.group_pointer->next_group;
1397 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer);
1398 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, 1);
1399 begin_iterator.group_pointer = next_group;
1401 if (next_group == NULL)
1406 begin_iterator.element_pointer = next_group->elements + *(next_group->skipfield);
1407 begin_iterator.skipfield_pointer = next_group->skipfield + *(next_group->skipfield);
1414 while (begin_iterator.group_pointer != NULL)
1416 const group_pointer_type next_group = begin_iterator.group_pointer->next_group;
1417 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer);
1418 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, 1);
1419 begin_iterator.group_pointer = next_group;
1425 void initialize(
const skipfield_type first_group_size)
1427 begin_iterator.group_pointer = PLF_COLONY_ALLOCATE(group_allocator_type, group_allocator_pair, 1, 0);
1431 #ifdef PLF_COLONY_VARIADICS_SUPPORT
1432 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, first_group_size);
1434 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, group(first_group_size));
1439 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, 1);
1440 begin_iterator.group_pointer = NULL;
1444 end_iterator.group_pointer = begin_iterator.group_pointer;
1445 end_iterator.element_pointer = begin_iterator.element_pointer = begin_iterator.group_pointer->elements;
1446 end_iterator.skipfield_pointer = begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield;
1447 total_capacity = first_group_size;
1452 void update_skipblock(
const iterator &new_location,
const skipfield_type prev_free_list_index)
1454 const skipfield_type new_value =
static_cast<skipfield_type
>(*(new_location.skipfield_pointer) - 1);
1459 *(new_location.skipfield_pointer + new_value) = *(new_location.skipfield_pointer + 1) = new_value;
1462 ++(groups_with_erasures_list_head->free_list_head);
1464 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
1466 *(
reinterpret_cast<skipfield_pointer_type
>(new_location.group_pointer->elements + prev_free_list_index) + 1) = groups_with_erasures_list_head->free_list_head;
1469 *(
reinterpret_cast<skipfield_pointer_type
>(new_location.element_pointer + 1)) = prev_free_list_index;
1470 *(
reinterpret_cast<skipfield_pointer_type
>(new_location.element_pointer + 1) + 1) = std::numeric_limits<skipfield_type>::max();
1474 groups_with_erasures_list_head->free_list_head = prev_free_list_index;
1476 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
1478 *(
reinterpret_cast<skipfield_pointer_type
>(new_location.group_pointer->elements + prev_free_list_index) + 1) = std::numeric_limits<skipfield_type>::max();
1482 groups_with_erasures_list_head = groups_with_erasures_list_head->erasures_list_next_group;
1486 *(new_location.skipfield_pointer) = 0;
1487 ++(new_location.group_pointer->number_of_elements);
1489 if (new_location.group_pointer == begin_iterator.group_pointer && new_location.element_pointer < begin_iterator.element_pointer)
1491 begin_iterator = new_location;
1494 ++total_number_of_elements;
1502 iterator insert(
const element_type &element)
1504 if (end_iterator.element_pointer != NULL)
1506 switch(((groups_with_erasures_list_head != NULL) << 1) | (end_iterator.element_pointer ==
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield)))
1510 const iterator return_iterator = end_iterator;
1512 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1513 if PLF_COLONY_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
1515 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), element);
1516 end_iterator.group_pointer->last_endpoint = end_iterator.element_pointer;
1521 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer), element);
1522 end_iterator.group_pointer->last_endpoint = ++end_iterator.element_pointer;
1525 ++(end_iterator.group_pointer->number_of_elements);
1526 ++end_iterator.skipfield_pointer;
1527 ++total_number_of_elements;
1529 return return_iterator;
1533 end_iterator.group_pointer->next_group = PLF_COLONY_ALLOCATE(group_allocator_type, group_allocator_pair, 1, end_iterator.group_pointer);
1534 group &next_group = *(end_iterator.group_pointer->next_group);
1535 const skipfield_type new_group_size = (total_number_of_elements < static_cast<size_type>(group_allocator_pair.max_elements_per_group)) ?
static_cast<skipfield_type
>(total_number_of_elements) : group_allocator_pair.max_elements_per_group;
1539 #ifdef PLF_COLONY_VARIADICS_SUPPORT
1540 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, &next_group, new_group_size, end_iterator.group_pointer);
1542 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, &next_group, group(new_group_size, end_iterator.group_pointer));
1547 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1548 end_iterator.group_pointer->next_group = NULL;
1552 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1553 if PLF_COLONY_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
1555 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), element);
1562 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), element);
1566 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, &next_group);
1567 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1568 end_iterator.group_pointer->next_group = NULL;
1573 end_iterator.group_pointer = &next_group;
1574 end_iterator.element_pointer = next_group.last_endpoint;
1575 end_iterator.skipfield_pointer = next_group.skipfield + 1;
1576 ++total_number_of_elements;
1577 total_capacity += new_group_size;
1579 return iterator(end_iterator.group_pointer, next_group.elements, next_group.skipfield);
1583 iterator new_location(groups_with_erasures_list_head, groups_with_erasures_list_head->elements + groups_with_erasures_list_head->free_list_head, groups_with_erasures_list_head->skipfield + groups_with_erasures_list_head->free_list_head);
1586 const skipfield_type prev_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(new_location.element_pointer));
1587 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(new_location.element_pointer), element);
1589 update_skipblock(new_location, prev_free_list_index);
1591 return new_location;
1597 initialize(pointer_allocator_pair.min_elements_per_group);
1599 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1600 if PLF_COLONY_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
1602 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), element);
1609 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), element);
1618 ++end_iterator.skipfield_pointer;
1619 total_number_of_elements = 1;
1620 return begin_iterator;
1626 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
1627 iterator insert(element_type &&element)
1629 if (end_iterator.element_pointer != NULL)
1631 switch(((groups_with_erasures_list_head != NULL) << 1) | (end_iterator.element_pointer ==
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield)))
1635 const iterator return_iterator = end_iterator;
1637 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1638 if PLF_COLONY_CONSTEXPR (std::is_nothrow_move_constructible<element_type>::value)
1640 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::move(element));
1641 end_iterator.group_pointer->last_endpoint = end_iterator.element_pointer;
1646 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer), std::move(element));
1647 end_iterator.group_pointer->last_endpoint = ++end_iterator.element_pointer;
1650 ++(end_iterator.group_pointer->number_of_elements);
1651 ++end_iterator.skipfield_pointer;
1652 ++total_number_of_elements;
1654 return return_iterator;
1658 end_iterator.group_pointer->next_group = PLF_COLONY_ALLOCATE(group_allocator_type, group_allocator_pair, 1, end_iterator.group_pointer);
1659 group &next_group = *(end_iterator.group_pointer->next_group);
1660 const skipfield_type new_group_size = (total_number_of_elements < static_cast<size_type>(group_allocator_pair.max_elements_per_group)) ?
static_cast<skipfield_type
>(total_number_of_elements) : group_allocator_pair.max_elements_per_group;
1664 #ifdef PLF_COLONY_VARIADICS_SUPPORT
1665 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, &next_group, new_group_size, end_iterator.group_pointer);
1667 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, &next_group, group(new_group_size, end_iterator.group_pointer));
1672 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1673 end_iterator.group_pointer->next_group = NULL;
1677 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1678 if PLF_COLONY_CONSTEXPR (std::is_nothrow_move_constructible<element_type>::value)
1680 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), std::move(element));
1687 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), std::move(element));
1691 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, &next_group);
1692 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1693 end_iterator.group_pointer->next_group = NULL;
1698 end_iterator.group_pointer = &next_group;
1699 end_iterator.element_pointer = next_group.last_endpoint;
1700 end_iterator.skipfield_pointer = next_group.skipfield + 1;
1701 ++total_number_of_elements;
1702 total_capacity += new_group_size;
1704 return iterator(end_iterator.group_pointer, next_group.elements, next_group.skipfield);
1708 iterator new_location(groups_with_erasures_list_head, groups_with_erasures_list_head->elements + groups_with_erasures_list_head->free_list_head, groups_with_erasures_list_head->skipfield + groups_with_erasures_list_head->free_list_head);
1710 const skipfield_type prev_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(new_location.element_pointer));
1711 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(new_location.element_pointer), std::move(element));
1713 update_skipblock(new_location, prev_free_list_index);
1715 return new_location;
1721 initialize(pointer_allocator_pair.min_elements_per_group);
1723 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1724 if PLF_COLONY_CONSTEXPR (std::is_nothrow_move_constructible<element_type>::value)
1726 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::move(element));
1733 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::move(element));
1742 ++end_iterator.skipfield_pointer;
1743 total_number_of_elements = 1;
1744 return begin_iterator;
1752 #ifdef PLF_COLONY_VARIADICS_SUPPORT
1753 template<
typename... arguments>
1754 iterator emplace(arguments &&... parameters)
1756 if (end_iterator.element_pointer != NULL)
1758 switch(((groups_with_erasures_list_head != NULL) << 1) | (end_iterator.element_pointer ==
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield)))
1762 const iterator return_iterator = end_iterator;
1764 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1765 if PLF_COLONY_CONSTEXPR (std::is_nothrow_constructible<element_type, arguments ...>::value)
1767 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::forward<arguments>(parameters)...);
1768 end_iterator.group_pointer->last_endpoint = end_iterator.element_pointer;
1773 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer), std::forward<arguments>(parameters)...);
1774 end_iterator.group_pointer->last_endpoint = ++end_iterator.element_pointer;
1777 ++(end_iterator.group_pointer->number_of_elements);
1778 ++end_iterator.skipfield_pointer;
1779 ++total_number_of_elements;
1781 return return_iterator;
1785 end_iterator.group_pointer->next_group = PLF_COLONY_ALLOCATE(group_allocator_type, group_allocator_pair, 1, end_iterator.group_pointer);
1786 group &next_group = *(end_iterator.group_pointer->next_group);
1787 const skipfield_type new_group_size = (total_number_of_elements < static_cast<size_type>(group_allocator_pair.max_elements_per_group)) ?
static_cast<skipfield_type
>(total_number_of_elements) : group_allocator_pair.max_elements_per_group;
1791 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, &next_group, new_group_size, end_iterator.group_pointer);
1795 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1796 end_iterator.group_pointer->next_group = NULL;
1800 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1801 if PLF_COLONY_CONSTEXPR (std::is_nothrow_constructible<element_type, arguments ...>::value)
1803 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), std::forward<arguments>(parameters)...);
1810 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(next_group.elements), std::forward<arguments>(parameters)...);
1814 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, &next_group);
1815 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, &next_group, 1);
1816 end_iterator.group_pointer->next_group = NULL;
1821 end_iterator.group_pointer = &next_group;
1822 end_iterator.element_pointer = next_group.last_endpoint;
1823 end_iterator.skipfield_pointer = next_group.skipfield + 1;
1824 ++total_number_of_elements;
1825 total_capacity += new_group_size;
1827 return iterator(end_iterator.group_pointer, next_group.elements, next_group.skipfield);
1831 iterator new_location(groups_with_erasures_list_head, groups_with_erasures_list_head->elements + groups_with_erasures_list_head->free_list_head, groups_with_erasures_list_head->skipfield + groups_with_erasures_list_head->free_list_head);
1833 const skipfield_type prev_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(new_location.element_pointer));
1834 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(new_location.element_pointer), std::forward<arguments>(parameters) ...);
1836 update_skipblock(new_location, prev_free_list_index);
1838 return new_location;
1844 initialize(pointer_allocator_pair.min_elements_per_group);
1846 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1847 if PLF_COLONY_CONSTEXPR (std::is_nothrow_constructible<element_type, arguments ...>::value)
1849 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::forward<arguments>(parameters) ...);
1856 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), std::forward<arguments>(parameters) ...);
1865 ++end_iterator.skipfield_pointer;
1866 total_number_of_elements = 1;
1867 return begin_iterator;
1879 void group_create(
const skipfield_type number_of_elements)
1881 const group_pointer_type next_group = end_iterator.group_pointer->next_group = PLF_COLONY_ALLOCATE(group_allocator_type, group_allocator_pair, 1, end_iterator.group_pointer);
1885 #ifdef PLF_COLONY_VARIADICS_SUPPORT
1886 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, next_group, number_of_elements, end_iterator.group_pointer);
1888 PLF_COLONY_CONSTRUCT(group_allocator_type, group_allocator_pair, next_group, group(number_of_elements, end_iterator.group_pointer));
1893 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, next_group);
1894 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, next_group, 1);
1895 end_iterator.group_pointer->next_group = NULL;
1899 end_iterator.group_pointer = next_group;
1900 end_iterator.element_pointer = next_group->elements;
1901 next_group->number_of_elements = 0;
1902 total_capacity += number_of_elements;
1907 void group_fill(
const element_type &element,
const skipfield_type number_of_elements)
1909 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1910 if PLF_COLONY_CONSTEXPR (std::is_trivially_copyable<element_type>::value && std::is_trivially_copy_constructible<element_type>::value && std::is_nothrow_copy_constructible<element_type>::value)
1912 #ifdef PLF_COLONY_ALIGNMENT_SUPPORT
1913 if PLF_COLONY_CONSTEXPR (
sizeof(aligned_element_type) !=
sizeof(element_type))
1915 alignas (
alignof(aligned_element_type)) element_type aligned_copy = element;
1916 std::fill_n(end_iterator.element_pointer, number_of_elements, *(
reinterpret_cast<aligned_pointer_type
>(&aligned_copy)));
1921 std::fill_n(
reinterpret_cast<pointer
>(end_iterator.element_pointer), number_of_elements, element);
1924 end_iterator.element_pointer += number_of_elements;
1929 const aligned_pointer_type fill_end = end_iterator.element_pointer + number_of_elements;
1931 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1932 if PLF_COLONY_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
1936 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), element);
1937 }
while (end_iterator.element_pointer != fill_end);
1946 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(end_iterator.element_pointer++), element);
1950 end_iterator.group_pointer->last_endpoint = --end_iterator.element_pointer;
1951 const skipfield_type elements_constructed_before_exception =
static_cast<skipfield_type
>(end_iterator.element_pointer - end_iterator.group_pointer->elements);
1952 end_iterator.group_pointer->number_of_elements = elements_constructed_before_exception;
1953 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + elements_constructed_before_exception;
1956 }
while (end_iterator.element_pointer != fill_end);
1960 end_iterator.group_pointer->last_endpoint = end_iterator.element_pointer;
1961 end_iterator.group_pointer->number_of_elements =
static_cast<skipfield_type
>(end_iterator.group_pointer->number_of_elements + number_of_elements);
1966 void fill_skipblock(
const element_type &element, aligned_pointer_type
const location, skipfield_pointer_type
const skipfield_pointer,
const skipfield_type number_of_elements)
1968 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1969 if PLF_COLONY_CONSTEXPR (std::is_trivially_copyable<element_type>::value && std::is_trivially_copy_constructible<element_type>::value && std::is_nothrow_copy_constructible<element_type>::value)
1971 #ifdef PLF_COLONY_ALIGNMENT_SUPPORT
1972 if PLF_COLONY_CONSTEXPR (
sizeof(aligned_element_type) !=
sizeof(element_type))
1974 alignas (
alignof(aligned_element_type)) element_type aligned_copy = element;
1975 std::fill_n(location, number_of_elements, *(
reinterpret_cast<aligned_pointer_type
>(&aligned_copy)));
1980 std::fill_n(
reinterpret_cast<pointer
>(location), number_of_elements, element);
1986 const aligned_pointer_type fill_end = location + number_of_elements;
1988 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
1989 if PLF_COLONY_CONSTEXPR (std::is_nothrow_copy_constructible<element_type>::value)
1991 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
1993 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current_location), element);
1999 const skipfield_type prev_free_list_node = *(
reinterpret_cast<skipfield_pointer_type
>(location));
2001 for (aligned_pointer_type current_location = location; current_location != fill_end; ++current_location)
2005 PLF_COLONY_CONSTRUCT(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current_location), element);
2010 const skipfield_type elements_constructed_before_exception =
static_cast<skipfield_type
>((current_location - 1) - location);
2011 groups_with_erasures_list_head->number_of_elements =
static_cast<skipfield_type
>(groups_with_erasures_list_head->number_of_elements + elements_constructed_before_exception);
2012 total_number_of_elements += elements_constructed_before_exception;
2014 std::memset(skipfield_pointer, 0, elements_constructed_before_exception *
sizeof(skipfield_type));
2016 *(
reinterpret_cast<skipfield_pointer_type
>(location + elements_constructed_before_exception)) = prev_free_list_node;
2017 *(
reinterpret_cast<skipfield_pointer_type
>(location + elements_constructed_before_exception) + 1) = std::numeric_limits<skipfield_type>::max();
2019 const skipfield_type new_skipblock_head_index =
static_cast<skipfield_type
>(
static_cast<skipfield_type
>(location - groups_with_erasures_list_head->elements) + elements_constructed_before_exception);
2020 groups_with_erasures_list_head->free_list_head = new_skipblock_head_index;
2022 if (prev_free_list_node != std::numeric_limits<skipfield_type>::max())
2024 *(
reinterpret_cast<skipfield_pointer_type
>(groups_with_erasures_list_head->elements + prev_free_list_node) + 1) = new_skipblock_head_index;
2033 std::memset(skipfield_pointer, 0, number_of_elements *
sizeof(skipfield_type));
2034 groups_with_erasures_list_head->number_of_elements =
static_cast<skipfield_type
>(groups_with_erasures_list_head->number_of_elements + number_of_elements);
2035 total_number_of_elements += number_of_elements;
2044 void insert(size_type number_of_elements,
const element_type &element)
2046 if (number_of_elements == 0)
2050 else if (number_of_elements == 1)
2056 if (begin_iterator.group_pointer == NULL)
2058 initialize((number_of_elements > group_allocator_pair.max_elements_per_group) ? group_allocator_pair.max_elements_per_group : (number_of_elements < pointer_allocator_pair.min_elements_per_group) ? pointer_allocator_pair.min_elements_per_group : static_cast<skipfield_type>(number_of_elements));
2059 begin_iterator.group_pointer->number_of_elements = 0;
2062 if (total_number_of_elements != 0)
2065 if (groups_with_erasures_list_head != NULL)
2069 aligned_pointer_type
const element_pointer = groups_with_erasures_list_head->elements + groups_with_erasures_list_head->free_list_head;
2070 skipfield_pointer_type
const skipfield_pointer = groups_with_erasures_list_head->skipfield + groups_with_erasures_list_head->free_list_head;
2071 const skipfield_type skipblock_size = *skipfield_pointer;
2073 if (groups_with_erasures_list_head == begin_iterator.group_pointer && element_pointer < begin_iterator.element_pointer)
2075 begin_iterator.element_pointer = element_pointer;
2076 begin_iterator.skipfield_pointer = skipfield_pointer;
2079 if (skipblock_size <= number_of_elements)
2081 groups_with_erasures_list_head->free_list_head = *(
reinterpret_cast<skipfield_pointer_type
>(element_pointer));
2082 fill_skipblock(element, element_pointer, skipfield_pointer, skipblock_size);
2083 number_of_elements -= skipblock_size;
2085 if (groups_with_erasures_list_head->free_list_head != std::numeric_limits<skipfield_type>::max())
2087 *(
reinterpret_cast<skipfield_pointer_type
>(groups_with_erasures_list_head->elements + groups_with_erasures_list_head->free_list_head) + 1) = std::numeric_limits<skipfield_type>::max();
2091 groups_with_erasures_list_head = groups_with_erasures_list_head->erasures_list_next_group;
2093 if (groups_with_erasures_list_head == NULL)
2101 const skipfield_type prev_index = *(
reinterpret_cast<skipfield_pointer_type
>(element_pointer));
2102 fill_skipblock(element, element_pointer, skipfield_pointer,
static_cast<skipfield_type
>(number_of_elements));
2103 const skipfield_type new_skipblock_size =
static_cast<skipfield_type
>(skipblock_size - number_of_elements);
2106 *(skipfield_pointer + number_of_elements) = new_skipblock_size;
2107 *(skipfield_pointer + skipblock_size - 1) = new_skipblock_size;
2108 groups_with_erasures_list_head->free_list_head =
static_cast<skipfield_type
>(groups_with_erasures_list_head->free_list_head + number_of_elements);
2111 *(
reinterpret_cast<skipfield_pointer_type
>(element_pointer + number_of_elements)) = prev_index;
2112 *(
reinterpret_cast<skipfield_pointer_type
>(element_pointer + number_of_elements) + 1) = std::numeric_limits<skipfield_type>::max();
2114 if (prev_index != std::numeric_limits<skipfield_type>::max())
2116 *(
reinterpret_cast<skipfield_pointer_type
>(groups_with_erasures_list_head->elements + prev_index) + 1) = groups_with_erasures_list_head->free_list_head;
2121 }
while(number_of_elements != 0);
2126 const skipfield_type group_remainder = (
static_cast<skipfield_type
>(
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer) > number_of_elements) ?
static_cast<skipfield_type
>(number_of_elements) :
static_cast<skipfield_type
>(
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer);
2128 if (group_remainder != 0)
2130 group_fill(element, group_remainder);
2131 total_number_of_elements += group_remainder;
2132 number_of_elements -= group_remainder;
2135 else if (end_iterator.group_pointer->capacity >= number_of_elements)
2137 group_fill(element,
static_cast<skipfield_type
>(number_of_elements));
2138 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + number_of_elements;
2139 total_number_of_elements = number_of_elements;
2144 group_fill(element, end_iterator.group_pointer->capacity);
2145 total_number_of_elements = end_iterator.group_pointer->capacity;
2146 number_of_elements -= end_iterator.group_pointer->capacity;
2151 if (number_of_elements > group_allocator_pair.max_elements_per_group)
2153 size_type multiples = (number_of_elements /
static_cast<size_type
>(group_allocator_pair.max_elements_per_group));
2154 const skipfield_type element_remainder =
static_cast<skipfield_type
>(number_of_elements - (multiples *
static_cast<size_type
>(group_allocator_pair.max_elements_per_group)));
2156 while (multiples-- != 0)
2158 group_create(group_allocator_pair.max_elements_per_group);
2159 group_fill(element, group_allocator_pair.max_elements_per_group);
2162 if (element_remainder != 0)
2164 group_create(group_allocator_pair.max_elements_per_group);
2165 group_fill(element, element_remainder);
2168 else if (number_of_elements != 0)
2170 group_create(
static_cast<skipfield_type
>((number_of_elements > total_number_of_elements) ? number_of_elements : total_number_of_elements));
2171 group_fill(element,
static_cast<skipfield_type
>(number_of_elements));
2174 total_number_of_elements += number_of_elements;
2175 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + (end_iterator.element_pointer - end_iterator.group_pointer->elements);
2182 template <
class iterator_type>
2183 #if defined(PLF_COLONY_TYPE_TRAITS_SUPPORT)
2184 inline void insert (
typename plf_enable_if_c<(!std::numeric_limits<iterator_type>::is_integer) && (!std::is_same<
typename std::iterator_traits<iterator_type>::iterator_category, std::random_access_iterator_tag>::value), iterator_type>::type first,
const iterator_type last)
2186 inline void insert (
typename plf_enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type first,
const iterator_type last)
2189 while (first != last)
2197 #if defined(PLF_COLONY_TYPE_TRAITS_SUPPORT)
2198 template <
class iterator_type>
2199 inline void insert (
typename plf_enable_if_c<(!std::numeric_limits<iterator_type>::is_integer) && (std::is_same<
typename std::iterator_traits<iterator_type>::iterator_category, std::random_access_iterator_tag>::value), iterator_type>::type first,
const iterator_type last)
2201 if (total_number_of_elements == 0)
2203 reserve(
static_cast<size_type
>(last - first));
2206 while (first != last)
2217 #ifdef PLF_COLONY_INITIALIZER_LIST_SUPPORT
2218 inline void insert (
const std::initializer_list<element_type> &element_list)
2220 insert(element_list.begin(), element_list.end());
2228 inline PLF_COLONY_FORCE_INLINE
void update_subsequent_group_numbers(group_pointer_type current_group) PLF_COLONY_NOEXCEPT
2232 --(current_group->group_number);
2233 current_group = current_group->next_group;
2234 }
while (current_group != NULL);
2239 inline PLF_COLONY_FORCE_INLINE
void consolidate()
2241 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
2245 temp.pointer_allocator_pair.min_elements_per_group =
static_cast<skipfield_type
>((pointer_allocator_pair.min_elements_per_group > total_number_of_elements) ? pointer_allocator_pair.min_elements_per_group : ((total_number_of_elements > group_allocator_pair.max_elements_per_group) ? group_allocator_pair.max_elements_per_group : total_number_of_elements));
2246 temp.group_allocator_pair.max_elements_per_group = group_allocator_pair.max_elements_per_group;
2248 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2249 if PLF_COLONY_CONSTEXPR (std::is_move_assignable<element_type>::value && std::is_move_constructible<element_type>::value)
2251 temp.insert(std::make_move_iterator(begin_iterator), std::make_move_iterator(end_iterator));
2256 temp.insert(begin_iterator, end_iterator);
2259 temp.pointer_allocator_pair.min_elements_per_group = pointer_allocator_pair.min_elements_per_group;
2260 *
this = std::move(temp);
2269 void remove_from_groups_with_erasures_list(
const group_pointer_type group_to_remove) PLF_COLONY_NOEXCEPT
2271 if (group_to_remove == groups_with_erasures_list_head)
2273 groups_with_erasures_list_head = groups_with_erasures_list_head->erasures_list_next_group;
2277 group_pointer_type previous_group = groups_with_erasures_list_head, current_group = groups_with_erasures_list_head->erasures_list_next_group;
2279 while (group_to_remove != current_group)
2281 previous_group = current_group;
2282 current_group = current_group->erasures_list_next_group;
2285 previous_group->erasures_list_next_group = current_group->erasures_list_next_group;
2293 iterator erase(
const const_iterator &it)
2296 const group_pointer_type group_pointer = it.group_pointer;
2297 assert(group_pointer != NULL);
2298 assert(it.element_pointer != group_pointer->last_endpoint);
2299 assert(*(it.skipfield_pointer) == 0);
2301 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2302 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2305 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(it.element_pointer));
2308 --total_number_of_elements;
2310 if (group_pointer->number_of_elements-- != 1)
2322 const char prev_skipfield = *(it.skipfield_pointer - (it.skipfield_pointer != group_pointer->skipfield)) != 0;
2323 const char after_skipfield = *(it.skipfield_pointer + 1) != 0;
2324 skipfield_type update_value = 1;
2326 switch ((after_skipfield << 1) | prev_skipfield)
2330 *it.skipfield_pointer = 1;
2331 const skipfield_type index =
static_cast<skipfield_type
>(it.element_pointer - group_pointer->elements);
2333 if (group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2335 *(
reinterpret_cast<skipfield_pointer_type
>(group_pointer->elements + group_pointer->free_list_head) + 1) = index;
2339 group_pointer->erasures_list_next_group = groups_with_erasures_list_head;
2340 groups_with_erasures_list_head = group_pointer;
2343 *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer)) = group_pointer->free_list_head;
2344 *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer) + 1) = std::numeric_limits<skipfield_type>::max();
2345 group_pointer->free_list_head = index;
2350 *(it.skipfield_pointer - *(it.skipfield_pointer - 1)) = *it.skipfield_pointer =
static_cast<skipfield_type
>(*(it.skipfield_pointer - 1) + 1);
2355 const skipfield_type following_value =
static_cast<skipfield_type
>(*(it.skipfield_pointer + 1) + 1);
2356 *(it.skipfield_pointer + following_value - 1) = *(it.skipfield_pointer) = following_value;
2358 const skipfield_type following_previous = *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer + 1));
2359 const skipfield_type following_next = *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer + 1) + 1);
2360 *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer)) = following_previous;
2361 *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer) + 1) = following_next;
2363 const skipfield_type index =
static_cast<skipfield_type
>(it.element_pointer - group_pointer->elements);
2365 if (following_previous != std::numeric_limits<skipfield_type>::max())
2367 *(
reinterpret_cast<skipfield_pointer_type
>(group_pointer->elements + following_previous) + 1) = index;
2370 if (following_next != std::numeric_limits<skipfield_type>::max())
2372 *(
reinterpret_cast<skipfield_pointer_type
>(group_pointer->elements + following_next)) = index;
2376 group_pointer->free_list_head = index;
2379 update_value = following_value;
2384 *(it.skipfield_pointer) = 1;
2385 const skipfield_type preceding_value = *(it.skipfield_pointer - 1);
2386 const skipfield_type following_value =
static_cast<skipfield_type
>(*(it.skipfield_pointer + 1) + 1);
2389 *(it.skipfield_pointer - preceding_value) = *(it.skipfield_pointer + following_value - 1) =
static_cast<skipfield_type
>(preceding_value + following_value);
2392 const skipfield_type following_previous = *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer + 1));
2393 const skipfield_type following_next = *(
reinterpret_cast<skipfield_pointer_type
>(it.element_pointer + 1) + 1);
2395 if (following_previous != std::numeric_limits<skipfield_type>::max())
2397 *(
reinterpret_cast<skipfield_pointer_type
>(group_pointer->elements + following_previous) + 1) = following_next;
2400 if (following_next != std::numeric_limits<skipfield_type>::max())
2402 *(
reinterpret_cast<skipfield_pointer_type
>(group_pointer->elements + following_next)) = following_previous;
2406 group_pointer->free_list_head = following_previous;
2409 update_value = following_value;
2414 iterator return_iterator(it.group_pointer, it.element_pointer + update_value, it.skipfield_pointer + update_value);
2415 return_iterator.check_for_end_of_group_and_progress();
2417 if (it.element_pointer == begin_iterator.element_pointer)
2419 begin_iterator = return_iterator;
2422 return return_iterator;
2426 switch((group_pointer->next_group != NULL) | ((group_pointer != begin_iterator.group_pointer) << 1))
2431 std::memset(&*(group_pointer->skipfield), 0,
sizeof(skipfield_type) * group_pointer->capacity);
2432 group_pointer->free_list_head = std::numeric_limits<skipfield_type>::max();
2433 groups_with_erasures_list_head = NULL;
2436 end_iterator.element_pointer = begin_iterator.element_pointer = group_pointer->last_endpoint = group_pointer->elements;
2437 end_iterator.skipfield_pointer = begin_iterator.skipfield_pointer = group_pointer->skipfield;
2439 return end_iterator;
2443 group_pointer->next_group->previous_group = NULL;
2444 begin_iterator.group_pointer = group_pointer->next_group;
2446 update_subsequent_group_numbers(begin_iterator.group_pointer);
2448 if (group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2450 remove_from_groups_with_erasures_list(group_pointer);
2453 total_capacity -= group_pointer->capacity;
2454 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, group_pointer);
2455 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, group_pointer, 1);
2458 begin_iterator.element_pointer = begin_iterator.group_pointer->elements + *(begin_iterator.group_pointer->skipfield);
2459 begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield + *(begin_iterator.group_pointer->skipfield);
2461 return begin_iterator;
2465 group_pointer->next_group->previous_group = group_pointer->previous_group;
2466 const group_pointer_type return_group = group_pointer->previous_group->next_group = group_pointer->next_group;
2468 update_subsequent_group_numbers(return_group);
2470 if (group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2472 remove_from_groups_with_erasures_list(group_pointer);
2475 total_capacity -= group_pointer->capacity;
2476 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, group_pointer);
2477 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, group_pointer, 1);
2480 return iterator(return_group, return_group->elements + *(return_group->skipfield), return_group->skipfield + *(return_group->skipfield));
2484 if (group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2486 remove_from_groups_with_erasures_list(group_pointer);
2489 group_pointer->previous_group->next_group = NULL;
2490 end_iterator.group_pointer = group_pointer->previous_group;
2491 end_iterator.element_pointer =
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield);
2492 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->capacity;
2494 total_capacity -= group_pointer->capacity;
2495 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, group_pointer);
2496 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, group_pointer, 1);
2498 return end_iterator;
2507 void erase(
const const_iterator &iterator1,
const const_iterator &iterator2)
2509 assert(iterator1 <= iterator2);
2511 const_iterator current = iterator1;
2513 if (current.group_pointer != iterator2.group_pointer)
2515 if (current.element_pointer != current.group_pointer->elements + *(current.group_pointer->skipfield))
2517 size_type number_of_group_erasures = 0;
2520 const aligned_pointer_type end = iterator1.group_pointer->last_endpoint;
2524 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2525 if ((std::is_trivially_destructible<element_type>::value) & (current.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max()))
2527 number_of_group_erasures +=
static_cast<size_type
>(end - current.element_pointer);
2532 while (current.element_pointer != end)
2534 if (*current.skipfield_pointer == 0)
2536 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2537 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2540 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer));
2543 ++number_of_group_erasures;
2544 ++current.element_pointer;
2545 ++current.skipfield_pointer;
2549 const skipfield_type prev_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(current.element_pointer));
2550 const skipfield_type next_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(current.element_pointer) + 1);
2552 current.element_pointer += *(current.skipfield_pointer);
2553 current.skipfield_pointer += *(current.skipfield_pointer);
2555 if (next_free_list_index == std::numeric_limits<skipfield_type>::max() && prev_free_list_index == std::numeric_limits<skipfield_type>::max())
2557 remove_from_groups_with_erasures_list(iterator1.group_pointer);
2558 iterator1.group_pointer->free_list_head = std::numeric_limits<skipfield_type>::max();
2559 number_of_group_erasures +=
static_cast<size_type
>(end - current.element_pointer);
2561 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2562 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2565 while (current.element_pointer != end)
2567 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer++));
2573 else if (next_free_list_index == std::numeric_limits<skipfield_type>::max())
2575 current.group_pointer->free_list_head = prev_free_list_index;
2576 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + prev_free_list_index) + 1) = std::numeric_limits<skipfield_type>::max();
2580 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + next_free_list_index)) = prev_free_list_index;
2582 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
2584 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + prev_free_list_index) + 1) = next_free_list_index;
2592 const skipfield_type previous_node_value = *(iterator1.skipfield_pointer - 1);
2593 const skipfield_type distance_to_end =
static_cast<skipfield_type
>(end - iterator1.element_pointer);
2595 std::memset(&*(iterator1.skipfield_pointer), 1,
sizeof(skipfield_type) * (
static_cast<size_type
>(distance_to_end) - 1));
2598 if (previous_node_value == 0)
2600 *iterator1.skipfield_pointer = distance_to_end;
2601 *(iterator1.skipfield_pointer + distance_to_end - 1) = distance_to_end;
2603 const skipfield_type index =
static_cast<skipfield_type
>(iterator1.element_pointer - iterator1.group_pointer->elements);
2605 if (iterator1.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2607 *(
reinterpret_cast<skipfield_pointer_type
>(iterator1.group_pointer->elements + iterator1.group_pointer->free_list_head) + 1) = index;
2611 iterator1.group_pointer->erasures_list_next_group = groups_with_erasures_list_head;
2612 groups_with_erasures_list_head = iterator1.group_pointer;
2615 *(
reinterpret_cast<skipfield_pointer_type
>(iterator1.element_pointer)) = iterator1.group_pointer->free_list_head;
2616 *(
reinterpret_cast<skipfield_pointer_type
>(iterator1.element_pointer) + 1) = std::numeric_limits<skipfield_type>::max();
2617 iterator1.group_pointer->free_list_head = index;
2621 *(iterator1.skipfield_pointer - previous_node_value) = *(iterator1.skipfield_pointer + distance_to_end - 1) =
static_cast<skipfield_type
>(previous_node_value + distance_to_end);
2624 iterator1.group_pointer->number_of_elements =
static_cast<skipfield_type
>(iterator1.group_pointer->number_of_elements - number_of_group_erasures);
2625 total_number_of_elements -= number_of_group_erasures;
2627 current.group_pointer = current.group_pointer->next_group;
2632 const group_pointer_type previous_group = current.group_pointer->previous_group;
2634 while (current.group_pointer != iterator2.group_pointer)
2636 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2637 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2640 current.element_pointer = current.group_pointer->elements + *(current.group_pointer->skipfield);
2641 current.skipfield_pointer = current.group_pointer->skipfield + *(current.group_pointer->skipfield);
2642 const aligned_pointer_type end = current.group_pointer->last_endpoint;
2646 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer));
2647 const skipfield_type skip = *(++current.skipfield_pointer);
2648 current.element_pointer +=
static_cast<size_type
>(skip) + 1u;
2649 current.skipfield_pointer += skip;
2650 }
while (current.element_pointer != end);
2653 if (current.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2655 remove_from_groups_with_erasures_list(current.group_pointer);
2658 total_number_of_elements -= current.group_pointer->number_of_elements;
2659 const group_pointer_type current_group = current.group_pointer;
2660 current.group_pointer = current.group_pointer->next_group;
2662 total_capacity -= current_group->capacity;
2663 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, current_group);
2664 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, current_group, 1);
2667 current.element_pointer = current.group_pointer->elements + *(current.group_pointer->skipfield);
2668 current.skipfield_pointer = current.group_pointer->skipfield + *(current.group_pointer->skipfield);
2669 current.group_pointer->previous_group = previous_group;
2671 if (previous_group != NULL)
2673 previous_group->next_group = current.group_pointer;
2677 begin_iterator = iterator2;
2681 if (current.element_pointer == iterator2.element_pointer)
2692 if (iterator2.element_pointer != end_iterator.element_pointer || current.element_pointer != current.group_pointer->elements + *(current.group_pointer->skipfield))
2694 size_type number_of_group_erasures = 0;
2697 const const_iterator current_saved = current;
2699 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2700 if ((std::is_trivially_destructible<element_type>::value) & (current.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max()))
2702 number_of_group_erasures +=
static_cast<size_type
>(iterator2.element_pointer - current.element_pointer);
2707 while (current.element_pointer != iterator2.element_pointer)
2709 if (*current.skipfield_pointer == 0)
2711 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2712 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2715 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer));
2718 ++number_of_group_erasures;
2719 ++current.element_pointer;
2720 ++current.skipfield_pointer;
2724 const skipfield_type prev_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(current.element_pointer));
2725 const skipfield_type next_free_list_index = *(
reinterpret_cast<skipfield_pointer_type
>(current.element_pointer) + 1);
2727 current.element_pointer += *(current.skipfield_pointer);
2728 current.skipfield_pointer += *(current.skipfield_pointer);
2730 if (next_free_list_index == std::numeric_limits<skipfield_type>::max() && prev_free_list_index == std::numeric_limits<skipfield_type>::max())
2732 remove_from_groups_with_erasures_list(iterator2.group_pointer);
2733 iterator2.group_pointer->free_list_head = std::numeric_limits<skipfield_type>::max();
2734 number_of_group_erasures +=
static_cast<size_type
>(iterator2.element_pointer - current.element_pointer);
2736 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2737 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2740 while (current.element_pointer != iterator2.element_pointer)
2742 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer++));
2748 else if (next_free_list_index == std::numeric_limits<skipfield_type>::max())
2750 current.group_pointer->free_list_head = prev_free_list_index;
2751 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + prev_free_list_index) + 1) = std::numeric_limits<skipfield_type>::max();
2755 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + next_free_list_index)) = prev_free_list_index;
2757 if (prev_free_list_index != std::numeric_limits<skipfield_type>::max())
2759 *(
reinterpret_cast<skipfield_pointer_type
>(current.group_pointer->elements + prev_free_list_index) + 1) = next_free_list_index;
2767 const skipfield_type distance_to_iterator2 =
static_cast<skipfield_type
>(iterator2.element_pointer - current_saved.element_pointer);
2768 const skipfield_type index =
static_cast<skipfield_type
>(current_saved.element_pointer - iterator2.group_pointer->elements);
2770 std::memset(&*(current_saved.skipfield_pointer + 1), 1,
sizeof(skipfield_type) * (
static_cast<size_type
>(distance_to_iterator2) - 1));
2773 if (index == 0 || *(current_saved.skipfield_pointer - 1) == 0)
2775 *(current_saved.skipfield_pointer) = distance_to_iterator2;
2776 *(iterator2.skipfield_pointer - 1) = distance_to_iterator2;
2778 if (iterator2.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2780 *(
reinterpret_cast<skipfield_pointer_type
>(iterator2.group_pointer->elements + iterator2.group_pointer->free_list_head) + 1) = index;
2784 iterator2.group_pointer->erasures_list_next_group = groups_with_erasures_list_head;
2785 groups_with_erasures_list_head = iterator2.group_pointer;
2788 *(
reinterpret_cast<skipfield_pointer_type
>(current_saved.element_pointer)) = iterator2.group_pointer->free_list_head;
2789 *(
reinterpret_cast<skipfield_pointer_type
>(current_saved.element_pointer) + 1) = std::numeric_limits<skipfield_type>::max();
2790 iterator2.group_pointer->free_list_head = index;
2795 const skipfield_type prev_node_value = *(current_saved.skipfield_pointer - 1);
2796 *(current_saved.skipfield_pointer - prev_node_value) =
static_cast<skipfield_type
>(prev_node_value + distance_to_iterator2);
2797 *(iterator2.skipfield_pointer - 1) =
static_cast<skipfield_type
>(prev_node_value + distance_to_iterator2);
2801 if (iterator1.element_pointer == begin_iterator.element_pointer)
2803 begin_iterator = iterator2;
2806 iterator2.group_pointer->number_of_elements =
static_cast<skipfield_type
>(iterator2.group_pointer->number_of_elements - number_of_group_erasures);
2807 total_number_of_elements -= number_of_group_erasures;
2811 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2812 if PLF_COLONY_CONSTEXPR (!std::is_trivially_destructible<element_type>::value)
2815 while(current.element_pointer != iterator2.element_pointer)
2817 PLF_COLONY_DESTROY(element_allocator_type, (*
this),
reinterpret_cast<pointer
>(current.element_pointer));
2818 current.element_pointer +=
static_cast<size_type
>(*(++current.skipfield_pointer)) + 1u;
2819 current.skipfield_pointer += *current.skipfield_pointer;
2824 if ((total_number_of_elements -= current.group_pointer->number_of_elements) != 0)
2826 current.group_pointer->previous_group->next_group = current.group_pointer->next_group;
2828 if (current.group_pointer == end_iterator.group_pointer)
2830 end_iterator.group_pointer = current.group_pointer->previous_group;
2831 end_iterator.element_pointer = end_iterator.group_pointer->last_endpoint;
2832 end_iterator.skipfield_pointer = end_iterator.group_pointer->skipfield + end_iterator.group_pointer->capacity;
2834 else if (current.group_pointer == begin_iterator.group_pointer)
2836 begin_iterator.group_pointer = current.group_pointer->next_group;
2837 const skipfield_type skip = *(begin_iterator.group_pointer->skipfield);
2838 begin_iterator.element_pointer = begin_iterator.group_pointer->elements + skip;
2839 begin_iterator.skipfield_pointer = begin_iterator.group_pointer->skipfield + skip;
2842 total_capacity -= current.group_pointer->capacity;
2844 if (current.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
2846 remove_from_groups_with_erasures_list(current.group_pointer);
2854 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, current.group_pointer);
2855 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, current.group_pointer, 1);
2861 #ifdef PLF_COLONY_CPP20_SUPPORT
2864 inline PLF_COLONY_FORCE_INLINE
bool empty() const PLF_COLONY_NOEXCEPT
2866 return total_number_of_elements == 0;
2871 inline size_type size() const PLF_COLONY_NOEXCEPT
2873 return total_number_of_elements;
2878 #ifdef PLF_COLONY_TEST_DEBUG
2879 inline size_type group_size_sum() const PLF_COLONY_NOEXCEPT
2883 for (group_pointer_type current = begin_iterator.group_pointer; current != NULL; current = current->next_group)
2885 temp += current->number_of_elements;
2893 inline size_type max_size() const PLF_COLONY_NOEXCEPT
2895 #ifdef PLF_COLONY_ALLOCATOR_TRAITS_SUPPORT
2896 return std::allocator_traits<element_allocator_type>::max_size(*
this);
2898 return element_allocator_type::max_size();
2904 inline size_type capacity() const PLF_COLONY_NOEXCEPT
2906 return total_capacity;
2911 inline size_type approximate_memory_use() const PLF_COLONY_NOEXCEPT
2915 (total_capacity * (
sizeof(aligned_element_type) +
sizeof(skipfield_type))) +
2916 ((end_iterator.group_pointer == NULL) ? 0 : ((end_iterator.group_pointer->group_number + 1) * (sizeof(group) + sizeof(skipfield_type))));
2921 void set_block_capacity_limits(
const plf::limits capacities)
2923 assert((capacities.min > 2) & (capacities.min <= capacities.max));
2924 assert(capacities.max <= std::numeric_limits<skipfield_type>::max());
2926 pointer_allocator_pair.min_elements_per_group =
static_cast<skipfield_type
>(capacities.min);
2927 group_allocator_pair.max_elements_per_group =
static_cast<skipfield_type
>(capacities.max);
2930 for (group_pointer_type current = begin_iterator.group_pointer; current != NULL; current = current->next_group)
2932 if (current->capacity < capacities.min || current->capacity > capacities.max)
2934 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
2935 if PLF_COLONY_CONSTEXPR (!((std::is_copy_constructible<element_type>::value && std::is_copy_assignable<element_type>::value) || (std::is_move_constructible<element_type>::value && std::is_move_assignable<element_type>::value)))
2952 inline void set_minimum_block_capacity(
const size_t min_allocation_amount)
2954 set_block_capacity_limits(
plf::limits(min_allocation_amount,
static_cast<size_t>(group_allocator_pair.max_elements_per_group)));
2959 inline void set_maximum_block_capacity(
const size_t max_allocation_amount)
2961 set_block_capacity_limits(
plf::limits(
static_cast<size_t>(pointer_allocator_pair.min_elements_per_group), max_allocation_amount));
2966 inline plf::limits get_block_capacity_limits() const PLF_COLONY_NOEXCEPT
2968 return plf::limits(
static_cast<size_t>(pointer_allocator_pair.min_elements_per_group),
static_cast<size_t>(group_allocator_pair.max_elements_per_group));
2973 inline PLF_COLONY_FORCE_INLINE
void clear() PLF_COLONY_NOEXCEPT
2981 inline colony & operator = (
const colony &source)
2983 if (&source ==
this){
2987 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
2989 colony temp(source);
2990 *
this = std::move(temp);
2993 colony temp(source);
3002 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
3004 colony & operator = (colony &&source) PLF_COLONY_NOEXCEPT_MOVE_ASSIGNMENT(allocator_type)
3006 assert (&source !=
this);
3009 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
3010 if PLF_COLONY_CONSTEXPR (std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
3012 std::memcpy(
static_cast<void *
>(
this), &source,
sizeof(colony));
3017 end_iterator = std::move(source.end_iterator);
3018 begin_iterator = std::move(source.begin_iterator);
3019 groups_with_erasures_list_head = std::move(source.groups_with_erasures_list_head);
3020 total_number_of_elements = source.total_number_of_elements;
3021 total_capacity = source.total_capacity;
3022 pointer_allocator_pair.min_elements_per_group = source.pointer_allocator_pair.min_elements_per_group;
3023 group_allocator_pair.max_elements_per_group = source.group_allocator_pair.max_elements_per_group;
3033 #ifdef PLF_COLONY_INITIALIZER_LIST_SUPPORT
3034 inline colony & operator = (
const std::initializer_list<element_type> &element_list)
3037 insert(element_list);
3044 bool operator == (
const colony &rh)
const PLF_COLONY_NOEXCEPT
3046 assert (
this != &rh);
3048 if (total_number_of_elements != rh.total_number_of_elements)
3053 for (const_iterator lh_iterator = begin_iterator, rh_iterator = rh.begin_iterator; lh_iterator != end_iterator; ++lh_iterator, ++rh_iterator)
3055 if (*lh_iterator != *rh_iterator)
3066 inline bool operator != (
const colony &rh)
const PLF_COLONY_NOEXCEPT
3068 return !(*
this == rh);
3073 void shrink_to_fit()
3075 if (total_number_of_elements == total_capacity)
3079 else if (total_number_of_elements == 0)
3091 void reserve(
const size_type original_reserve_amount)
3093 if (original_reserve_amount == 0 || original_reserve_amount <= total_capacity)
3098 skipfield_type reserve_amount;
3100 if (original_reserve_amount >
static_cast<size_type
>(group_allocator_pair.max_elements_per_group))
3102 reserve_amount = group_allocator_pair.max_elements_per_group;
3104 else if (original_reserve_amount <
static_cast<size_type
>(pointer_allocator_pair.min_elements_per_group))
3106 reserve_amount = pointer_allocator_pair.min_elements_per_group;
3108 else if (original_reserve_amount > max_size())
3110 reserve_amount =
static_cast<skipfield_type
>(max_size());
3114 reserve_amount =
static_cast<skipfield_type
>(original_reserve_amount);
3117 if (total_number_of_elements == 0)
3119 if (begin_iterator.group_pointer != NULL)
3121 PLF_COLONY_DESTROY(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer);
3122 PLF_COLONY_DEALLOCATE(group_allocator_type, group_allocator_pair, begin_iterator.group_pointer, 1);
3125 initialize(reserve_amount);
3126 begin_iterator.group_pointer->last_endpoint = begin_iterator.group_pointer->elements;
3127 begin_iterator.group_pointer->number_of_elements = 0;
3131 const skipfield_type original_min_elements = pointer_allocator_pair.min_elements_per_group;
3132 pointer_allocator_pair.min_elements_per_group =
static_cast<skipfield_type
>(reserve_amount);
3134 pointer_allocator_pair.min_elements_per_group = original_min_elements;
3141 template <
bool is_const>
3142 void advance(colony_iterator<is_const> &it, difference_type distance)
const
3145 group_pointer_type &group_pointer = it.group_pointer;
3146 aligned_pointer_type &element_pointer = it.element_pointer;
3147 skipfield_pointer_type &skipfield_pointer = it.skipfield_pointer;
3149 assert(group_pointer != NULL);
3168 assert (!(element_pointer == group_pointer->last_endpoint && group_pointer->next_group == NULL));
3171 if (element_pointer != group_pointer->elements + *(group_pointer->skipfield))
3173 const difference_type distance_from_end =
static_cast<difference_type
>(group_pointer->last_endpoint - element_pointer);
3175 if (group_pointer->number_of_elements ==
static_cast<skipfield_type
>(distance_from_end))
3177 if (distance < distance_from_end)
3179 element_pointer += distance;
3180 skipfield_pointer += distance;
3183 else if (group_pointer->next_group == NULL)
3185 element_pointer = group_pointer->last_endpoint;
3186 skipfield_pointer += distance_from_end;
3191 distance -= distance_from_end;
3196 const skipfield_pointer_type endpoint = skipfield_pointer + distance_from_end;
3200 ++skipfield_pointer;
3201 skipfield_pointer += *skipfield_pointer;
3204 if (skipfield_pointer == endpoint)
3208 else if (distance == 0)
3210 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3215 if (group_pointer->next_group == NULL)
3217 element_pointer = group_pointer->last_endpoint;
3222 group_pointer = group_pointer->next_group;
3226 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3227 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3234 while (
static_cast<difference_type
>(group_pointer->number_of_elements) <= distance)
3236 if (group_pointer->next_group == NULL)
3238 element_pointer = group_pointer->last_endpoint;
3239 skipfield_pointer = group_pointer->skipfield + (group_pointer->last_endpoint - group_pointer->elements);
3242 else if ((distance -= group_pointer->number_of_elements) == 0)
3244 group_pointer = group_pointer->next_group;
3245 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3246 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3251 group_pointer = group_pointer->next_group;
3257 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3259 element_pointer = group_pointer->elements + distance;
3260 skipfield_pointer = group_pointer->skipfield + distance;
3265 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3269 ++skipfield_pointer;
3270 skipfield_pointer += *skipfield_pointer;
3271 }
while(--distance != 0);
3273 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3279 else if (distance < 0)
3282 assert(!((element_pointer == group_pointer->elements + *(group_pointer->skipfield)) && group_pointer->previous_group == NULL));
3283 distance = -distance;
3286 if (element_pointer != group_pointer->last_endpoint)
3288 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3290 const difference_type distance_from_beginning =
static_cast<difference_type
>(element_pointer - group_pointer->elements);
3292 if (distance <= distance_from_beginning)
3294 element_pointer -= distance;
3295 skipfield_pointer -= distance;
3298 else if (group_pointer->previous_group == NULL)
3300 element_pointer = group_pointer->elements;
3301 skipfield_pointer = group_pointer->skipfield;
3306 distance -= distance_from_beginning;
3311 const skipfield_pointer_type beginning_point = group_pointer->skipfield + *(group_pointer->skipfield);
3313 while(skipfield_pointer != beginning_point)
3315 --skipfield_pointer;
3316 skipfield_pointer -= *skipfield_pointer;
3318 if (--distance == 0)
3320 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3325 if (group_pointer->previous_group == NULL)
3327 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3328 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3333 group_pointer = group_pointer->previous_group;
3338 while(
static_cast<difference_type
>(group_pointer->number_of_elements) < distance)
3340 if (group_pointer->previous_group == NULL)
3342 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3343 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3347 distance -= group_pointer->number_of_elements;
3348 group_pointer = group_pointer->previous_group;
3353 if (
static_cast<difference_type
>(group_pointer->number_of_elements) == distance)
3355 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3356 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3359 else if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3361 element_pointer =
reinterpret_cast<aligned_pointer_type
>(group_pointer->skipfield) - distance;
3362 skipfield_pointer = (group_pointer->skipfield + group_pointer->capacity) - distance;
3367 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity;
3371 --skipfield_pointer;
3372 skipfield_pointer -= *skipfield_pointer;
3373 }
while(--distance != 0);
3375 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3387 template <
bool is_const>
3388 void advance(colony_reverse_iterator<is_const> &reverse_it, difference_type distance)
const
3390 group_pointer_type &group_pointer = reverse_it.it.group_pointer;
3391 aligned_pointer_type &element_pointer = reverse_it.it.element_pointer;
3392 skipfield_pointer_type &skipfield_pointer = reverse_it.it.skipfield_pointer;
3394 assert(element_pointer != NULL);
3398 assert (!(element_pointer == group_pointer->elements - 1 && group_pointer->previous_group == NULL));
3401 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3403 difference_type distance_from_beginning =
static_cast<difference_type
>(element_pointer - group_pointer->elements);
3405 if (distance <= distance_from_beginning)
3407 element_pointer -= distance;
3408 skipfield_pointer -= distance;
3411 else if (group_pointer->previous_group == NULL)
3413 element_pointer = group_pointer->elements - 1;
3414 skipfield_pointer = group_pointer->skipfield - 1;
3419 distance -= distance_from_beginning;
3424 const skipfield_pointer_type beginning_point = group_pointer->skipfield + *(group_pointer->skipfield);
3426 while(skipfield_pointer != beginning_point)
3428 --skipfield_pointer;
3429 skipfield_pointer -= *skipfield_pointer;
3431 if (--distance == 0)
3433 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3438 if (group_pointer->previous_group == NULL)
3440 element_pointer = group_pointer->elements - 1;
3441 skipfield_pointer = group_pointer->skipfield - 1;
3446 group_pointer = group_pointer->previous_group;
3450 while(
static_cast<difference_type
>(group_pointer->number_of_elements) < distance)
3452 if (group_pointer->previous_group == NULL)
3454 element_pointer = group_pointer->elements - 1;
3455 skipfield_pointer = group_pointer->skipfield - 1;
3459 distance -=
static_cast<difference_type
>(group_pointer->number_of_elements);
3460 group_pointer = group_pointer->previous_group;
3465 if (
static_cast<difference_type
>(group_pointer->number_of_elements) == distance)
3467 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3468 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3471 else if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3473 element_pointer =
reinterpret_cast<aligned_pointer_type
>(group_pointer->skipfield) - distance;
3474 skipfield_pointer = (group_pointer->skipfield + group_pointer->capacity) - distance;
3479 skipfield_pointer = group_pointer->skipfield + group_pointer->capacity;
3483 --skipfield_pointer;
3484 skipfield_pointer -= *skipfield_pointer;
3485 }
while(--distance != 0);
3487 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3491 else if (distance < 0)
3493 assert (!((element_pointer == (group_pointer->last_endpoint - 1) - *(group_pointer->skipfield + (group_pointer->last_endpoint - group_pointer->elements) - 1)) && group_pointer->next_group == NULL));
3495 if (element_pointer != group_pointer->elements + *(group_pointer->skipfield))
3497 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3499 const difference_type distance_from_end =
static_cast<difference_type
>(group_pointer->last_endpoint - element_pointer);
3501 if (distance < distance_from_end)
3503 element_pointer += distance;
3504 skipfield_pointer += distance;
3507 else if (group_pointer->next_group == NULL)
3509 element_pointer = group_pointer->last_endpoint - 1;
3510 skipfield_pointer += distance_from_end - 1;
3515 distance -= distance_from_end;
3520 const skipfield_pointer_type endpoint = skipfield_pointer + (group_pointer->last_endpoint - element_pointer);
3524 ++skipfield_pointer;
3525 skipfield_pointer += *skipfield_pointer;
3528 if (skipfield_pointer == endpoint)
3532 else if (distance == 0)
3534 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3539 if (group_pointer->next_group == NULL)
3541 --skipfield_pointer;
3542 element_pointer = (group_pointer->last_endpoint - 1) - *skipfield_pointer;
3543 skipfield_pointer -= *skipfield_pointer;
3548 group_pointer = group_pointer->next_group;
3552 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3553 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3560 while(
static_cast<difference_type
>(group_pointer->number_of_elements) <= distance)
3562 if (group_pointer->next_group == NULL)
3564 skipfield_pointer = group_pointer->skipfield + (group_pointer->last_endpoint - group_pointer->elements) - 1;
3565 element_pointer = (group_pointer->last_endpoint - 1) - *skipfield_pointer;
3566 skipfield_pointer -= *skipfield_pointer;
3569 else if ((distance -= group_pointer->number_of_elements) == 0)
3571 group_pointer = group_pointer->next_group;
3572 element_pointer = group_pointer->elements + *(group_pointer->skipfield);
3573 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3578 group_pointer = group_pointer->next_group;
3584 if (group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3586 element_pointer = group_pointer->elements + distance;
3587 skipfield_pointer = group_pointer->skipfield + distance;
3592 skipfield_pointer = group_pointer->skipfield + *(group_pointer->skipfield);
3596 ++skipfield_pointer;
3597 skipfield_pointer += *skipfield_pointer;
3598 }
while(--distance != 0);
3600 element_pointer = group_pointer->elements + (skipfield_pointer - group_pointer->skipfield);
3612 template <
bool is_const>
3613 inline colony_iterator<is_const> next(
const colony_iterator<is_const> &it,
const typename colony_iterator<is_const>::difference_type distance = 1)
const
3615 colony_iterator<is_const> return_iterator(it);
3616 advance(return_iterator, distance);
3617 return return_iterator;
3622 template <
bool is_const>
3623 inline colony_reverse_iterator<is_const> next(
const colony_reverse_iterator<is_const> &it,
const typename colony_reverse_iterator<is_const>::difference_type distance = 1)
const
3625 colony_reverse_iterator<is_const> return_iterator(it);
3626 advance(return_iterator, distance);
3627 return return_iterator;
3633 template <
bool is_const>
3634 inline colony_iterator<is_const> prev(
const colony_iterator<is_const> &it,
const typename colony_iterator<is_const>::difference_type distance = 1)
const
3636 colony_iterator<is_const> return_iterator(it);
3637 advance(return_iterator, -distance);
3638 return return_iterator;
3643 template <
bool is_const>
3644 inline colony_reverse_iterator<is_const> prev(
const colony_reverse_iterator<is_const> &it,
const typename colony_reverse_iterator<is_const>::difference_type distance = 1)
const
3646 colony_reverse_iterator<is_const> return_iterator(it);
3647 advance(return_iterator, -distance);
3648 return return_iterator;
3655 template <
bool is_const>
3656 typename colony_iterator<is_const>::difference_type distance(
const colony_iterator<is_const> &first,
const colony_iterator<is_const> &last)
const
3666 assert(!(first.group_pointer == NULL) && !(last.group_pointer == NULL));
3668 if (last.element_pointer == first.element_pointer)
3673 typedef colony_iterator<is_const> iterator_type;
3674 typedef typename iterator_type::difference_type diff_type;
3675 diff_type distance = 0;
3677 iterator_type iterator1 = first, iterator2 = last;
3678 const bool swap = first > last;
3686 if (iterator1.group_pointer != iterator2.group_pointer)
3689 if (iterator1.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3691 distance +=
static_cast<diff_type
>(iterator1.group_pointer->last_endpoint - iterator1.element_pointer);
3693 else if (iterator1.element_pointer == iterator1.group_pointer->elements + *(iterator1.group_pointer->skipfield))
3695 distance +=
static_cast<diff_type
>(iterator1.group_pointer->number_of_elements);
3699 const skipfield_pointer_type endpoint = iterator1.skipfield_pointer + (iterator1.group_pointer->last_endpoint - iterator1.element_pointer);
3701 while (iterator1.skipfield_pointer != endpoint)
3703 ++iterator1.skipfield_pointer;
3704 iterator1.skipfield_pointer += *(iterator1.skipfield_pointer);
3710 iterator1.group_pointer = iterator1.group_pointer->next_group;
3712 while (iterator1.group_pointer != iterator2.group_pointer)
3714 distance +=
static_cast<diff_type
>(iterator1.group_pointer->number_of_elements);
3715 iterator1.group_pointer = iterator1.group_pointer->next_group;
3718 iterator1.skipfield_pointer = iterator1.group_pointer->skipfield;
3722 if (iterator2.group_pointer->free_list_head == std::numeric_limits<skipfield_type>::max())
3724 distance +=
static_cast<diff_type
>(iterator2.skipfield_pointer - iterator1.skipfield_pointer);
3726 else if (iterator2.group_pointer->last_endpoint - 1 >= iterator2.element_pointer || iterator2.element_pointer + *(iterator2.skipfield_pointer + 1) == iterator2.group_pointer->last_endpoint)
3728 distance +=
static_cast<diff_type
>(iterator2.group_pointer->number_of_elements - (iterator2.group_pointer->last_endpoint - iterator2.element_pointer));
3732 while (iterator1.skipfield_pointer != iterator2.skipfield_pointer)
3734 ++iterator1.skipfield_pointer;
3735 iterator1.skipfield_pointer += *(iterator1.skipfield_pointer);
3743 distance = -distance;
3751 template <
bool is_const>
3752 inline typename colony_reverse_iterator<is_const>::difference_type distance(
const colony_reverse_iterator<is_const> &iterator1,
const colony_reverse_iterator<is_const> &iterator2)
const
3754 return distance(iterator2.it, iterator1.it);
3759 iterator get_iterator_from_pointer(
const pointer element_pointer)
const PLF_COLONY_NOEXCEPT
3761 if (total_number_of_elements != 0)
3764 for (group_pointer_type current_group = end_iterator.group_pointer; current_group != NULL; current_group = current_group->previous_group)
3766 if (
reinterpret_cast<aligned_pointer_type
>(element_pointer) >= current_group->elements &&
reinterpret_cast<aligned_pointer_type
>(element_pointer) <
reinterpret_cast<aligned_pointer_type
>(current_group->skipfield))
3768 const skipfield_pointer_type skipfield_pointer = current_group->skipfield + (
reinterpret_cast<aligned_pointer_type
>(element_pointer) - current_group->elements);
3769 return (*skipfield_pointer == 0) ? iterator(current_group,
reinterpret_cast<aligned_pointer_type
>(element_pointer), skipfield_pointer) : end_iterator;
3774 return end_iterator;
3779 inline allocator_type get_allocator() const PLF_COLONY_NOEXCEPT
3781 return element_allocator_type();
3786 void splice(colony &source) PLF_COLONY_NOEXCEPT_SWAP(allocator_type)
3793 assert(&source !=
this);
3795 if (source.total_number_of_elements == 0)
3799 else if (total_number_of_elements == 0)
3801 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
3802 *
this = std::move(source);
3812 if ((
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer) > (
reinterpret_cast<aligned_pointer_type
>(source.end_iterator.group_pointer->skipfield) - source.end_iterator.element_pointer))
3819 if (source.pointer_allocator_pair.min_elements_per_group < pointer_allocator_pair.min_elements_per_group)
3821 pointer_allocator_pair.min_elements_per_group = source.pointer_allocator_pair.min_elements_per_group;
3824 if (source.group_allocator_pair.max_elements_per_group > group_allocator_pair.max_elements_per_group)
3826 group_allocator_pair.max_elements_per_group = source.group_allocator_pair.max_elements_per_group;
3830 if (source.groups_with_erasures_list_head != NULL)
3832 if (groups_with_erasures_list_head != NULL)
3834 group_pointer_type tail_group = groups_with_erasures_list_head;
3836 while (tail_group->erasures_list_next_group != NULL)
3838 tail_group = tail_group->erasures_list_next_group;
3841 tail_group->erasures_list_next_group = source.groups_with_erasures_list_head;
3845 groups_with_erasures_list_head = source.groups_with_erasures_list_head;
3850 const skipfield_type distance_to_end =
static_cast<skipfield_type
>(
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield) - end_iterator.element_pointer);
3852 if (distance_to_end != 0)
3856 const skipfield_type previous_node_value = *(end_iterator.skipfield_pointer - 1);
3857 end_iterator.group_pointer->last_endpoint =
reinterpret_cast<aligned_pointer_type
>(end_iterator.group_pointer->skipfield);
3859 if (previous_node_value == 0)
3861 *end_iterator.skipfield_pointer = distance_to_end;
3862 *(end_iterator.skipfield_pointer + distance_to_end - 1) = distance_to_end;
3864 const skipfield_type index =
static_cast<skipfield_type
>(end_iterator.element_pointer - end_iterator.group_pointer->elements);
3866 if (end_iterator.group_pointer->free_list_head != std::numeric_limits<skipfield_type>::max())
3868 *(
reinterpret_cast<skipfield_pointer_type
>(end_iterator.group_pointer->elements + end_iterator.group_pointer->free_list_head) + 1) = index;
3872 end_iterator.group_pointer->erasures_list_next_group = groups_with_erasures_list_head;
3873 groups_with_erasures_list_head = end_iterator.group_pointer;
3876 *(
reinterpret_cast<skipfield_pointer_type
>(end_iterator.element_pointer)) = end_iterator.group_pointer->free_list_head;
3877 *(
reinterpret_cast<skipfield_pointer_type
>(end_iterator.element_pointer) + 1) = std::numeric_limits<skipfield_type>::max();
3878 end_iterator.group_pointer->free_list_head = index;
3882 *(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);
3888 group_pointer_type current_group = source.begin_iterator.group_pointer;
3889 size_type current_group_number = end_iterator.group_pointer->group_number;
3893 current_group->group_number = ++current_group_number;
3894 current_group = current_group->next_group;
3895 }
while (current_group != NULL);
3899 end_iterator.group_pointer->next_group = source.begin_iterator.group_pointer;
3900 source.begin_iterator.group_pointer->previous_group = end_iterator.group_pointer;
3901 end_iterator = source.end_iterator;
3902 total_number_of_elements += source.total_number_of_elements;
3903 total_capacity += source.total_capacity;
3911 aligned_pointer_type *element_memory_block_pointers;
3912 skipfield_pointer_type *skipfield_memory_block_pointers;
3913 skipfield_type *block_capacities;
3914 size_type number_of_blocks;
3917 element_memory_block_pointers(
reinterpret_cast<aligned_pointer_type *
>(PLF_COLONY_ALLOCATE_INITIALIZATION(uchar_allocator_type, size *
sizeof(aligned_pointer_type), NULL))),
3918 skipfield_memory_block_pointers(
reinterpret_cast<skipfield_pointer_type *
>(PLF_COLONY_ALLOCATE_INITIALIZATION(uchar_allocator_type, size *
sizeof(skipfield_pointer_type), NULL))),
3919 block_capacities(
reinterpret_cast<skipfield_type *
>(PLF_COLONY_ALLOCATE_INITIALIZATION(uchar_allocator_type, size *
sizeof(skipfield_type *), NULL))),
3920 number_of_blocks(size)
3925 PLF_COLONY_DEALLOCATE(uchar_allocator_type, (*
this),
reinterpret_cast<uchar_pointer_type
>(element_memory_block_pointers), number_of_blocks *
sizeof(colony::pointer));
3926 PLF_COLONY_DEALLOCATE(uchar_allocator_type, (*
this),
reinterpret_cast<uchar_pointer_type
>(skipfield_memory_block_pointers), number_of_blocks *
sizeof(skipfield_pointer_type));
3927 PLF_COLONY_DEALLOCATE(uchar_allocator_type, (*
this),
reinterpret_cast<uchar_pointer_type
>(block_capacities), number_of_blocks *
sizeof(size_type));
3936 size_type group_number = 0;
3938 for (group_pointer_type current_group = begin_iterator.group_pointer; current_group != end_iterator.group_pointer; current_group = current_group->next_group)
3940 data->element_memory_block_pointers[group_number] = current_group->elements;
3941 data->skipfield_memory_block_pointers[group_number] = current_group->skipfield;
3942 data->block_capacities[group_number] = current_group->capacity;
3947 data->element_memory_block_pointers[group_number] = end_iterator.group_pointer->elements;
3948 data->skipfield_memory_block_pointers[group_number] = end_iterator.group_pointer->skipfield;
3949 data->block_capacities[group_number] =
static_cast<skipfield_type
>(end_iterator.group_pointer->last_endpoint - end_iterator.group_pointer->elements);
3960 bool operator() (
const element_type &a,
const element_type &b)
const PLF_COLONY_NOEXCEPT
3968 struct item_index_tuple
3970 pointer original_location;
3971 size_type original_index;
3973 item_index_tuple(
const pointer _item,
const size_type _index) PLF_COLONY_NOEXCEPT:
3974 original_location(_item),
3975 original_index(_index)
3981 template <
class comparison_function>
3982 struct sort_dereferencer
3984 comparison_function stored_instance;
3986 explicit sort_dereferencer(
const comparison_function &function_instance):
3987 stored_instance(function_instance)
3990 sort_dereferencer() PLF_COLONY_NOEXCEPT
3993 bool operator() (
const item_index_tuple first,
const item_index_tuple second)
3995 return stored_instance(*(first.original_location), *(second.original_location));
4004 template <
class comparison_function>
4005 void sort(comparison_function compare)
4007 if (total_number_of_elements < 2)
4012 #ifdef PLF_COLONY_ALLOCATOR_TRAITS_SUPPORT
4013 typedef typename std::allocator_traits<element_allocator_type>::template rebind_alloc<item_index_tuple> tuple_allocator_type;
4015 typedef typename element_allocator_type::template rebind<item_index_tuple>::other tuple_allocator_type;
4018 tuple_allocator_type tuple_allocator;
4020 item_index_tuple *
const sort_array = PLF_COLONY_ALLOCATE(tuple_allocator_type, tuple_allocator, total_number_of_elements, NULL);
4021 item_index_tuple *tuple_pointer = sort_array;
4024 size_type index = 0;
4026 for (iterator current_element = begin_iterator; current_element != end_iterator; ++current_element, ++tuple_pointer, ++index)
4028 #ifdef PLF_COLONY_VARIADICS_SUPPORT
4029 PLF_COLONY_CONSTRUCT(tuple_allocator_type, tuple_allocator, tuple_pointer, &*current_element, index);
4031 PLF_COLONY_CONSTRUCT(tuple_allocator_type, tuple_allocator, tuple_pointer, item_index_tuple(&*current_element, index));
4037 #ifndef PLF_COLONY_SORT_FUNCTION
4038 std::sort(sort_array, sort_array + total_number_of_elements, sort_dereferencer<comparison_function>(compare));
4040 PLF_COLONY_SORT_FUNCTION(sort_array, sort_array + total_number_of_elements, sort_dereferencer<comparison_function>(compare));
4047 for (item_index_tuple *current_tuple = sort_array; current_tuple != tuple_pointer; ++current_tuple, ++index)
4049 if (current_tuple->original_index != index)
4051 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
4052 element_type end_value = std::move(*(current_tuple->original_location));
4054 element_type end_value = *(current_tuple->original_location);
4057 size_type destination_index = index;
4058 size_type source_index = current_tuple->original_index;
4062 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
4063 *(sort_array[destination_index].original_location) = std::move(*(sort_array[source_index].original_location));
4065 *(sort_array[destination_index].original_location) = *(sort_array[source_index].original_location);
4068 destination_index = source_index;
4069 source_index = sort_array[destination_index].original_index;
4070 sort_array[destination_index].original_index = destination_index;
4071 }
while (source_index != index);
4073 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
4074 *(sort_array[destination_index].original_location) = std::move(end_value);
4076 *(sort_array[destination_index].original_location) = end_value;
4081 PLF_COLONY_DEALLOCATE(tuple_allocator_type, tuple_allocator, sort_array, total_number_of_elements);
4093 void swap(colony &source) PLF_COLONY_NOEXCEPT_SWAP(allocator_type)
4095 assert(&source !=
this);
4097 #ifdef PLF_COLONY_TYPE_TRAITS_SUPPORT
4098 if PLF_COLONY_CONSTEXPR (std::is_trivial<group_pointer_type>::value && std::is_trivial<aligned_pointer_type>::value && std::is_trivial<skipfield_pointer_type>::value)
4100 char temp[
sizeof(colony)];
4101 std::memcpy(&temp,
static_cast<void *
>(
this),
sizeof(colony));
4102 std::memcpy(
static_cast<void *
>(
this),
static_cast<void *
>(&source),
sizeof(colony));
4103 std::memcpy(
static_cast<void *
>(&source), &temp,
sizeof(colony));
4105 #ifdef PLF_COLONY_MOVE_SEMANTICS_SUPPORT
4106 else if PLF_COLONY_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)
4108 colony temp(std::move(source));
4109 source = std::move(*
this);
4110 *
this = std::move(temp);
4116 const iterator swap_end_iterator = end_iterator, swap_begin_iterator = begin_iterator;
4117 const group_pointer_type swap_groups_with_erasures_list_head = groups_with_erasures_list_head;
4118 const size_type swap_total_number_of_elements = total_number_of_elements, swap_total_capacity = total_capacity;
4119 const skipfield_type swap_min_elements_per_group = pointer_allocator_pair.min_elements_per_group, swap_max_elements_per_group = group_allocator_pair.max_elements_per_group;
4121 end_iterator = source.end_iterator;
4122 begin_iterator = source.begin_iterator;
4123 groups_with_erasures_list_head = source.groups_with_erasures_list_head;
4124 total_number_of_elements = source.total_number_of_elements;
4125 total_capacity = source.total_capacity;
4126 pointer_allocator_pair.min_elements_per_group = source.pointer_allocator_pair.min_elements_per_group;
4127 group_allocator_pair.max_elements_per_group = source.group_allocator_pair.max_elements_per_group;
4129 source.end_iterator = swap_end_iterator;
4130 source.begin_iterator = swap_begin_iterator;
4131 source.groups_with_erasures_list_head = swap_groups_with_erasures_list_head;
4132 source.total_number_of_elements = swap_total_number_of_elements;
4133 source.total_capacity = swap_total_capacity;
4134 source.pointer_allocator_pair.min_elements_per_group = swap_min_elements_per_group;
4135 source.group_allocator_pair.max_elements_per_group = swap_max_elements_per_group;