passenger 6.2.1 → 6.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +37 -15
- data/build/cxx_tests.rb +2 -0
- data/build/support/cxx_dependency_map.rb +3 -63
- data/src/agent/Core/Config.h +1 -1
- data/src/agent/Core/Controller/Config.h +1 -1
- data/src/agent/Shared/ApiServerUtils.h +1 -1
- data/src/agent/Watchdog/Config.h +1 -1
- data/src/apache2_module/Hooks.cpp +13 -0
- data/src/apache2_module/Utils.h +14 -0
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/FileTools/FileManip.cpp +27 -3
- data/src/cxx_supportlib/InstanceDirectory.h +30 -3
- data/src/cxx_supportlib/ServerKit/Errors.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpHeaderParserState.h +1 -1
- data/src/cxx_supportlib/ServerKit/HttpRequest.h +1 -1
- data/src/cxx_supportlib/ServerKit/llerrors.h +3 -3
- data/src/cxx_supportlib/ServerKit/llversion.h +1 -1
- data/src/cxx_supportlib/{ServerKit/llhttp_api.c → vendor-copy/llhttp/api.c} +30 -23
- data/src/cxx_supportlib/{ServerKit → vendor-copy/llhttp}/llhttp.c +1756 -1645
- data/src/cxx_supportlib/{ServerKit → vendor-copy/llhttp}/llhttp.h +35 -13
- data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/classification.hpp +19 -0
- data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/formatter.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/trim_all.hpp +0 -2
- data/src/cxx_supportlib/vendor-modified/boost/assert.hpp +20 -13
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/core_arch_ops_gcc_x86.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/atomic/thread_pause.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/bind/mem_fn.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/circular_buffer/debug.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx03.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx11.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx14.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx17.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx20.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/assert_cxx23.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/auto_link.hpp +6 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/clang_version.hpp +10 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/visualc.hpp +5 -3
- data/src/cxx_supportlib/vendor-modified/boost/config/detail/cxx_composite.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/workaround.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/adaptive_pool.hpp +57 -53
- data/src/cxx_supportlib/vendor-modified/boost/container/allocator.hpp +10 -10
- data/src/cxx_supportlib/vendor-modified/boost/container/allocator_traits.hpp +34 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/container_fwd.hpp +14 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/deque.hpp +176 -2287
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/adaptive_node_pool.hpp +13 -9
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/adaptive_node_pool_impl.hpp +186 -70
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/algorithm.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/aligned_allocation.hpp +149 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/alloc_helpers.hpp +35 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/alloc_lib.h +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/bit_utilities.hpp +133 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/compare_functors.hpp +18 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/config_begin.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/config_end.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/container_rebind.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/copy_move_algo.hpp +20 -10
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/deque_impl.hpp +2744 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/dispatch_uses_allocator.hpp +202 -104
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/dlmalloc.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/flat_tree.hpp +161 -85
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/is_constructible.hpp +180 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/iterators.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/math_functions.hpp +12 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/mpl.hpp +16 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/mutex.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/next_capacity.hpp +9 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/node_pool.hpp +18 -14
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/node_pool_impl.hpp +256 -41
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/operator_new_helpers.hpp +75 -24
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/pair.hpp +1 -56
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/placement_new.hpp +16 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/pool_common_alloc.hpp +1 -7
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/range_utils.hpp +196 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/std_fwd.hpp +33 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/tree.hpp +124 -69
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/workaround.hpp +109 -7
- data/src/cxx_supportlib/vendor-modified/boost/container/devector.hpp +168 -162
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/nest.hpp +2978 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/pmr/nest.hpp +45 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_all_of.hpp +43 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_any_of.hpp +42 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_copy.hpp +229 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_copy_if.hpp +270 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_copy_n.hpp +308 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_count.hpp +101 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_count_if.hpp +100 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_equal.hpp +268 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_fill.hpp +101 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_fill_n.hpp +171 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find.hpp +110 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find_if.hpp +110 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find_if_not.hpp +43 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find_last.hpp +179 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find_last_if.hpp +179 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_find_last_if_not.hpp +43 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_for_each.hpp +92 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_generate.hpp +90 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_generate_n.hpp +162 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_is_partitioned.hpp +46 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_is_sorted.hpp +49 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_is_sorted_until.hpp +169 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_iterator_traits.hpp +382 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_merge.hpp +428 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_mismatch.hpp +350 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_none_of.hpp +98 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_partition.hpp +296 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_partition_copy.hpp +105 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_partition_point.hpp +116 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_remove.hpp +57 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_remove_copy.hpp +207 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_remove_copy_if.hpp +223 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_remove_if.hpp +57 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_replace.hpp +90 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_replace_if.hpp +90 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_reverse.hpp +245 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_reverse_copy.hpp +229 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_search.hpp +211 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_search_n.hpp +476 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_set_difference.hpp +300 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_set_intersection.hpp +287 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_set_symmetric_difference.hpp +306 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_set_union.hpp +294 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_stable_partition.hpp +153 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_swap_ranges.hpp +92 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/segmented_transform.hpp +93 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/experimental/wrapped_iterator.hpp +142 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/flat_map.hpp +642 -417
- data/src/cxx_supportlib/vendor-modified/boost/container/flat_set.hpp +141 -30
- data/src/cxx_supportlib/vendor-modified/boost/container/hub.hpp +2426 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/list.hpp +65 -57
- data/src/cxx_supportlib/vendor-modified/boost/container/map.hpp +247 -68
- data/src/cxx_supportlib/vendor-modified/boost/container/new_allocator.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/node_allocator.hpp +39 -33
- data/src/cxx_supportlib/vendor-modified/boost/container/options.hpp +156 -23
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/global_resource.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/hub.hpp +43 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/memory_resource.hpp +5 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/monotonic_buffer_resource.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/polymorphic_allocator.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/resource_adaptor.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/segtor.hpp +45 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/scoped_allocator.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/segtor.hpp +905 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/set.hpp +148 -35
- data/src/cxx_supportlib/vendor-modified/boost/container/slist.hpp +59 -52
- data/src/cxx_supportlib/vendor-modified/boost/container/small_vector.hpp +632 -5
- data/src/cxx_supportlib/vendor-modified/boost/container/stable_vector.hpp +66 -60
- data/src/cxx_supportlib/vendor-modified/boost/container/static_vector.hpp +46 -1
- data/src/cxx_supportlib/vendor-modified/boost/container/string.hpp +612 -317
- data/src/cxx_supportlib/vendor-modified/boost/container/uses_allocator.hpp +54 -111
- data/src/cxx_supportlib/vendor-modified/boost/container/uses_allocator_construction.hpp +100 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/uses_allocator_fwd.hpp +1 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/vector.hpp +233 -116
- data/src/cxx_supportlib/vendor-modified/boost/container_hash/hash.hpp +5 -1
- data/src/cxx_supportlib/vendor-modified/boost/core/lightweight_test.hpp +17 -10
- data/src/cxx_supportlib/vendor-modified/boost/date_time/period.hpp +1 -3
- data/src/cxx_supportlib/vendor-modified/boost/describe/detail/config.hpp +16 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/encoder.hpp +114 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/error_info_impl.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/requires_cxx11.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/type_info.hpp +211 -1
- data/src/cxx_supportlib/vendor-modified/boost/exception/diagnostic_information.hpp +59 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/exception.hpp +6 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/info.hpp +34 -0
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree.hpp +0 -1
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree.hpp +12 -3
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/derivation_value_traits.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/ebo_functor_holder.hpp +29 -174
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/generic_hook.hpp +18 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/key_nodeptr_comp.hpp +0 -1
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/workaround.hpp +4 -5
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/hashtable.hpp +20 -11
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/list.hpp +42 -14
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist.hpp +58 -22
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/iterator/advance.hpp +5 -1
- data/src/cxx_supportlib/vendor-modified/boost/iterator/distance.hpp +8 -2
- data/src/cxx_supportlib/vendor-modified/boost/iterator/is_iterator.hpp +9 -0
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/bad_lexical_cast.hpp +11 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/buffer_view.hpp +9 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/config.hpp +22 -0
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical.hpp +15 -7
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical_streams.hpp +23 -11
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_numeric.hpp +11 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/inf_nan.hpp +9 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/is_character.hpp +11 -2
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp +10 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/lcast_char_constants.hpp +8 -1
- data/src/cxx_supportlib/vendor-modified/boost/{detail → lexical_cast/detail}/lcast_precision.hpp +13 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/lcast_unsigned_converters.hpp +11 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/widest_char.hpp +10 -2
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/try_lexical_convert.hpp +15 -2
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast.hpp +11 -1
- data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/once_atomic.cpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/thread.cpp +48 -46
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils.hpp +23 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/move_helpers.hpp +24 -24
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/nsec_clock.hpp +12 -4
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/type_traits.hpp +76 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/workaround.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/move/traits.hpp +11 -0
- data/src/cxx_supportlib/vendor-modified/boost/mp11/algorithm.hpp +58 -37
- data/src/cxx_supportlib/vendor-modified/boost/mp11/detail/mp_copy_if.hpp +1 -2
- data/src/cxx_supportlib/vendor-modified/boost/mp11/detail/mp_map_find.hpp +17 -9
- data/src/cxx_supportlib/vendor-modified/boost/mp11/detail/mp_remove_if.hpp +1 -2
- data/src/cxx_supportlib/vendor-modified/boost/mp11/integer_sequence.hpp +6 -0
- data/src/cxx_supportlib/vendor-modified/boost/mp11/version.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/none_t.hpp +6 -1
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_common_defs.hpp +188 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_factory_support.hpp +0 -6
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_hash.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_nonmember_interface.hpp +117 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_reference_spec.hpp +108 -83
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_relops.hpp +39 -39
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_select_implementation.hpp +37 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_swap.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_trivially_copyable_base.hpp +8 -8
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/union_optional.hpp +724 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/optional.hpp +93 -220
- data/src/cxx_supportlib/vendor-modified/boost/optional/optional_fwd.hpp +14 -4
- data/src/cxx_supportlib/vendor-modified/boost/optional/optional_io.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/random/binomial_distribution.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/random/uniform_int_distribution.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/rational.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/static_assert.hpp +4 -6
- data/src/cxx_supportlib/vendor-modified/boost/system/api_config.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/system/detail/config.hpp +16 -0
- data/src/cxx_supportlib/vendor-modified/boost/system/detail/error_category.hpp +13 -13
- data/src/cxx_supportlib/vendor-modified/boost/system/detail/error_category_impl.hpp +5 -5
- data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/detail/sync_deque_base.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/detail/sync_queue_base.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/thread/detail/thread.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/experimental/parallel/v2/task_region.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/future.hpp +30 -28
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/once.hpp +6 -3
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/once_atomic.hpp +5 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/pthread_helpers.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/shared_mutex.hpp +16 -16
- data/src/cxx_supportlib/vendor-modified/boost/thread/v2/shared_mutex.hpp +26 -26
- data/src/cxx_supportlib/vendor-modified/boost/unordered/concurrent_flat_map.hpp +196 -6
- data/src/cxx_supportlib/vendor-modified/boost/unordered/concurrent_flat_set.hpp +191 -6
- data/src/cxx_supportlib/vendor-modified/boost/unordered/concurrent_node_map.hpp +196 -5
- data/src/cxx_supportlib/vendor-modified/boost/unordered/concurrent_node_set.hpp +192 -5
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/foa/concurrent_table.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/foa/core.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/foa/table.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/implementation.hpp +52 -16
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/ranges_support.hpp +104 -0
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/type_traits.hpp +1 -14
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/unordered_printers.hpp +10 -4
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_flat_map.hpp +121 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_flat_set.hpp +118 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_map.hpp +338 -1
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_node_map.hpp +121 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_node_set.hpp +118 -3
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_set.hpp +333 -1
- data/src/cxx_supportlib/vendor-modified/boost/version.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +276 -143
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +1262 -771
- data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +1704 -1586
- data/src/nginx_module/ContentHandler.c +35 -0
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +6 -6
- data/src/ruby_supportlib/phusion_passenger/utils/json.rb +25 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +12 -1
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- metadata +73 -8
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_utility.hpp +0 -41
- /data/src/cxx_supportlib/{ServerKit/llhttp_http.c → vendor-copy/llhttp/http.c} +0 -0
|
@@ -0,0 +1,2426 @@
|
|
|
1
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// (C) Copyright Joaquin M Lopez Munoz 2025-2026.
|
|
4
|
+
// (C) Copyright Ion Gaztanaga 2026. Distributed under the Boost
|
|
5
|
+
// Software License, Version 1.0. (See accompanying file
|
|
6
|
+
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
7
|
+
//
|
|
8
|
+
// See http://www.boost.org/libs/container for documentation.
|
|
9
|
+
//
|
|
10
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
|
|
12
|
+
#ifndef BOOST_CONTAINER_HUB_HPP
|
|
13
|
+
#define BOOST_CONTAINER_HUB_HPP
|
|
14
|
+
|
|
15
|
+
#ifndef BOOST_CONFIG_HPP
|
|
16
|
+
# include <boost/config.hpp>
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
|
20
|
+
# pragma once
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#include <boost/container/detail/config_begin.hpp>
|
|
24
|
+
#include <boost/container/detail/workaround.hpp>
|
|
25
|
+
|
|
26
|
+
//container
|
|
27
|
+
#include <boost/container/container_fwd.hpp>
|
|
28
|
+
#include <boost/container/detail/bit_utilities.hpp>
|
|
29
|
+
#include <boost/container/detail/range_utils.hpp> //from_range_t / from_range
|
|
30
|
+
|
|
31
|
+
#include <algorithm>
|
|
32
|
+
#include <boost/assert.hpp>
|
|
33
|
+
#include <boost/config.hpp>
|
|
34
|
+
#include <boost/config/workaround.hpp>
|
|
35
|
+
#include <boost/container/allocator_traits.hpp>
|
|
36
|
+
#include <boost/container/new_allocator.hpp> //default allocator when Allocator = void
|
|
37
|
+
#include <boost/container/throw_exception.hpp>
|
|
38
|
+
#include <boost/container/detail/addressof.hpp> //dtl::addressof (avoids <memory>)
|
|
39
|
+
#include <boost/container/detail/aligned_allocation.hpp> //portable (over)aligned nothrow alloc
|
|
40
|
+
#include <boost/container/detail/std_fwd.hpp> //forward declares std::allocator
|
|
41
|
+
#include <boost/intrusive/pointer_traits.hpp>
|
|
42
|
+
#include <boost/move/detail/to_raw_pointer.hpp>
|
|
43
|
+
#include <boost/move/unique_ptr.hpp> //movelib::unique_ptr (avoids <memory>)
|
|
44
|
+
#include <cstddef>
|
|
45
|
+
#include <cstdint>
|
|
46
|
+
#include <functional>
|
|
47
|
+
#include <initializer_list>
|
|
48
|
+
#include <iterator>
|
|
49
|
+
#include <new>
|
|
50
|
+
#include <type_traits>
|
|
51
|
+
#include <utility>
|
|
52
|
+
|
|
53
|
+
#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE
|
|
54
|
+
#include <memory_resource>
|
|
55
|
+
#endif
|
|
56
|
+
|
|
57
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
58
|
+
|
|
59
|
+
#if defined(BOOST_NO_CXX20_HDR_CONCEPTS) || defined(BOOST_NO_CXX20_HDR_RANGES)
|
|
60
|
+
#define BOOST_CONTAINER_HUB_NO_RANGES
|
|
61
|
+
#elif BOOST_WORKAROUND(BOOST_CLANG_VERSION, < 170100) && \
|
|
62
|
+
defined(BOOST_LIBSTDCXX_VERSION)
|
|
63
|
+
//https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109647
|
|
64
|
+
//https://github.com/llvm/llvm-project/issues/49620
|
|
65
|
+
#define BOOST_CONTAINER_HUB_NO_RANGES
|
|
66
|
+
#endif
|
|
67
|
+
|
|
68
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
69
|
+
//<iterator> (std::input_iterator, std::iter_value_t/iter_reference_t) is already
|
|
70
|
+
//included unconditionally below; only <concepts> (std::convertible_to) is extra.
|
|
71
|
+
#include <concepts>
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
//Software prefetch hint accepting a (possibly fancy) pointer: convert to a raw
|
|
75
|
+
//pointer and delegate to BOOST_CONTAINER_PREFETCH (workaround.hpp), which holds
|
|
76
|
+
//the per-compiler/-arch implementation (and is a macro, not a function, because
|
|
77
|
+
//of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109985).
|
|
78
|
+
#define BOOST_CONTAINER_HUB_PREFETCH(p) \
|
|
79
|
+
BOOST_CONTAINER_PREFETCH(boost::movelib::to_raw_pointer(p))
|
|
80
|
+
|
|
81
|
+
#define BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb, Block) \
|
|
82
|
+
do{ \
|
|
83
|
+
auto p0 = &static_cast<Block&>(*(pbb)); \
|
|
84
|
+
BOOST_CONTAINER_HUB_PREFETCH(p0->data()); \
|
|
85
|
+
} while(0)
|
|
86
|
+
|
|
87
|
+
#if defined(BOOST_MSVC)
|
|
88
|
+
#pragma warning(push)
|
|
89
|
+
#pragma warning(disable:4714) //marked as __forceinline not inlined
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
93
|
+
|
|
94
|
+
namespace boost {
|
|
95
|
+
|
|
96
|
+
namespace container {
|
|
97
|
+
|
|
98
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
99
|
+
|
|
100
|
+
//Default argument for Allocator is provided by container_fwd.hpp
|
|
101
|
+
template<typename T, typename Allocator>
|
|
102
|
+
class hub;
|
|
103
|
+
|
|
104
|
+
template<typename T, typename Allocator, typename Predicate>
|
|
105
|
+
typename hub<T, Allocator>::size_type erase_if(hub<T, Allocator>&, Predicate);
|
|
106
|
+
|
|
107
|
+
namespace hub_detail {
|
|
108
|
+
|
|
109
|
+
template<typename ValuePointer> class iterator;
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
template<typename T, typename Allocator, typename F>
|
|
114
|
+
F for_each(hub<T, Allocator>&, F);
|
|
115
|
+
|
|
116
|
+
template<typename T, typename Allocator, typename F>
|
|
117
|
+
std::pair<typename hub<T, Allocator>::iterator, F> for_each_while(
|
|
118
|
+
hub<T, Allocator>&, F);
|
|
119
|
+
|
|
120
|
+
template<typename T, typename Allocator, typename F>
|
|
121
|
+
std::pair<typename hub<T, Allocator>::const_iterator, F> for_each_while(
|
|
122
|
+
const hub<T, Allocator>&, F);
|
|
123
|
+
|
|
124
|
+
template<typename ValuePtr, typename F>
|
|
125
|
+
std::pair<hub_detail::iterator<ValuePtr>, F> for_each_while(
|
|
126
|
+
hub_detail::iterator<ValuePtr>, hub_detail::iterator<ValuePtr>, F);
|
|
127
|
+
|
|
128
|
+
namespace hub_detail {
|
|
129
|
+
|
|
130
|
+
//Shared bit helpers live in boost::container::dtl (detail/bit_utilities.hpp).
|
|
131
|
+
|
|
132
|
+
//Use Boost.Intrusive's pointer_traits (modeled on std::pointer_traits) so the
|
|
133
|
+
//header does not depend on Boost.Core.
|
|
134
|
+
using boost::intrusive::pointer_traits;
|
|
135
|
+
|
|
136
|
+
//Thin alias templates over boost::container::allocator_traits replacing the
|
|
137
|
+
//former boost::core::allocator_access helpers. The propagate_on_* / is_always_equal
|
|
138
|
+
//members of boost::container::allocator_traits are Boost integral constants; wrap
|
|
139
|
+
//their value in std::integral_constant so the std::true_type/std::false_type-based
|
|
140
|
+
//tag-dispatch helpers (swap_if, if_constexpr, copy_assign_if, ...) keep matching.
|
|
141
|
+
template<class A>
|
|
142
|
+
using pocca_t = std::integral_constant<bool,
|
|
143
|
+
allocator_traits<A>::propagate_on_container_copy_assignment::value>;
|
|
144
|
+
template<class A>
|
|
145
|
+
using pocma_t = std::integral_constant<bool,
|
|
146
|
+
allocator_traits<A>::propagate_on_container_move_assignment::value>;
|
|
147
|
+
template<class A>
|
|
148
|
+
using pocs_t = std::integral_constant<bool,
|
|
149
|
+
allocator_traits<A>::propagate_on_container_swap::value>;
|
|
150
|
+
template<class A>
|
|
151
|
+
using is_always_equal_t = std::integral_constant<bool,
|
|
152
|
+
allocator_traits<A>::is_always_equal::value>;
|
|
153
|
+
template<class A, class U>
|
|
154
|
+
using rebind_alloc_t = typename allocator_traits<A>::template portable_rebind_alloc<U>::type;
|
|
155
|
+
|
|
156
|
+
template<typename Pointer, typename T>
|
|
157
|
+
using pointer_rebind_t =
|
|
158
|
+
typename pointer_traits<Pointer>::template rebind<T>;
|
|
159
|
+
|
|
160
|
+
template<typename VoidPointer>
|
|
161
|
+
struct block_base
|
|
162
|
+
{
|
|
163
|
+
using pointer = pointer_rebind_t<VoidPointer, block_base>;
|
|
164
|
+
using const_pointer = pointer_rebind_t<VoidPointer, const block_base>;
|
|
165
|
+
using mask_type = std::uint64_t;
|
|
166
|
+
|
|
167
|
+
static constexpr int N = 64;
|
|
168
|
+
static constexpr mask_type full = (mask_type)(-1);
|
|
169
|
+
|
|
170
|
+
static pointer pointer_to(block_base& x) noexcept
|
|
171
|
+
{
|
|
172
|
+
return pointer_traits<pointer>::pointer_to(x);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
static const_pointer pointer_to(const block_base& x) noexcept
|
|
176
|
+
{
|
|
177
|
+
return pointer_traits<const_pointer>::pointer_to(x);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_before(pointer p) noexcept
|
|
181
|
+
{
|
|
182
|
+
next_available = p;
|
|
183
|
+
prev_available = p->prev_available;
|
|
184
|
+
next_available->prev_available = pointer_to(*this);
|
|
185
|
+
prev_available->next_available = pointer_to(*this);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_after(pointer p) noexcept
|
|
189
|
+
{
|
|
190
|
+
prev_available = p;
|
|
191
|
+
next_available = p->next_available;
|
|
192
|
+
next_available->prev_available = pointer_to(*this);
|
|
193
|
+
prev_available->next_available = pointer_to(*this);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
BOOST_CONTAINER_FORCEINLINE void unlink_available() noexcept
|
|
197
|
+
{
|
|
198
|
+
prev_available->next_available = next_available;
|
|
199
|
+
next_available->prev_available = prev_available;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
BOOST_CONTAINER_FORCEINLINE void link_before(pointer p) noexcept
|
|
203
|
+
{
|
|
204
|
+
next = p;
|
|
205
|
+
prev = p->prev;
|
|
206
|
+
next->prev = pointer_to(*this);
|
|
207
|
+
prev->next = pointer_to(*this);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
BOOST_CONTAINER_FORCEINLINE void unlink() noexcept
|
|
211
|
+
{
|
|
212
|
+
prev->next = next;
|
|
213
|
+
next->prev = prev;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
pointer prev_available,
|
|
217
|
+
next_available,
|
|
218
|
+
prev,
|
|
219
|
+
next;
|
|
220
|
+
mask_type mask;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
template<typename ValuePointer>
|
|
224
|
+
struct block: block_base<pointer_rebind_t<ValuePointer, void>>
|
|
225
|
+
{
|
|
226
|
+
using super = block_base<pointer_rebind_t<ValuePointer, void>>;
|
|
227
|
+
using pointer = pointer_rebind_t<ValuePointer, block>;
|
|
228
|
+
|
|
229
|
+
ValuePointer data() noexcept { return data_; }
|
|
230
|
+
ValuePointer data_;
|
|
231
|
+
|
|
232
|
+
static pointer
|
|
233
|
+
static_cast_block_pointer(typename super::pointer pbb) noexcept
|
|
234
|
+
{
|
|
235
|
+
return pointer_traits<pointer>::pointer_to(static_cast<block&>(*pbb));
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
template<typename ValuePointer>
|
|
240
|
+
void swap_payload(block<ValuePointer>& x, block<ValuePointer>& y) noexcept
|
|
241
|
+
{
|
|
242
|
+
std::swap(x.mask, y.mask);
|
|
243
|
+
std::swap(x.data_, y.data_);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
template<typename ValuePointer>
|
|
247
|
+
struct block_list: block<ValuePointer>
|
|
248
|
+
{
|
|
249
|
+
using block = hub_detail::block<ValuePointer>;
|
|
250
|
+
using block_base = typename block::super;
|
|
251
|
+
using block_base_pointer = typename block_base::pointer;
|
|
252
|
+
using const_block_base_pointer = typename block_base::const_pointer;
|
|
253
|
+
using block_pointer = typename block::pointer;
|
|
254
|
+
using block_base::full;
|
|
255
|
+
using block_base::pointer_to;
|
|
256
|
+
using block_base::prev_available;
|
|
257
|
+
using block_base::next_available;
|
|
258
|
+
using block_base::prev;
|
|
259
|
+
using block_base::next;
|
|
260
|
+
using block_base::mask;
|
|
261
|
+
using block::data_;
|
|
262
|
+
|
|
263
|
+
block_list()
|
|
264
|
+
{
|
|
265
|
+
reset();
|
|
266
|
+
mask = 1; //sentinel
|
|
267
|
+
data_ = nullptr;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
block_list(block_list&& x) noexcept: block_list{}
|
|
271
|
+
{
|
|
272
|
+
if(x.next_available != x.header()) {
|
|
273
|
+
prev_available = x.prev_available;
|
|
274
|
+
next_available = x.next_available;
|
|
275
|
+
next_available->prev_available = header();
|
|
276
|
+
prev_available->next_available = header();
|
|
277
|
+
}
|
|
278
|
+
if(x.prev != x.header()) {
|
|
279
|
+
prev = x.prev;
|
|
280
|
+
next = x.next;
|
|
281
|
+
next->prev = header();
|
|
282
|
+
prev->next = header();
|
|
283
|
+
}
|
|
284
|
+
x.reset();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
block_list& operator=(block_list&& x) noexcept
|
|
288
|
+
{
|
|
289
|
+
reset();
|
|
290
|
+
if(x.next_available != x.header()) {
|
|
291
|
+
prev_available = x.prev_available;
|
|
292
|
+
next_available = x.next_available;
|
|
293
|
+
next_available->prev_available = header();
|
|
294
|
+
prev_available->next_available = header();
|
|
295
|
+
}
|
|
296
|
+
if(x.prev != x.header()) {
|
|
297
|
+
prev = x.prev;
|
|
298
|
+
next = x.next;
|
|
299
|
+
next->prev = header();
|
|
300
|
+
prev->next = header();
|
|
301
|
+
}
|
|
302
|
+
x.reset();
|
|
303
|
+
return *this;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
void reset() noexcept
|
|
307
|
+
{
|
|
308
|
+
prev_available = header();
|
|
309
|
+
next_available = header();
|
|
310
|
+
prev = header();
|
|
311
|
+
next = header();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
block_base_pointer header() noexcept
|
|
315
|
+
{
|
|
316
|
+
return pointer_to(static_cast<block_base&>(*this));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const_block_base_pointer header() const noexcept
|
|
320
|
+
{
|
|
321
|
+
return pointer_to(static_cast<const block_base&>(*this));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
BOOST_CONTAINER_FORCEINLINE void link_at_back(block_pointer pb) noexcept
|
|
325
|
+
{
|
|
326
|
+
pb->link_before(header());
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
BOOST_CONTAINER_FORCEINLINE void link_before(
|
|
330
|
+
block_pointer pbx, block_pointer pby) noexcept
|
|
331
|
+
{
|
|
332
|
+
pbx->link_before(pby);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
BOOST_CONTAINER_FORCEINLINE static void unlink(block_pointer pb) noexcept
|
|
336
|
+
{
|
|
337
|
+
pb->unlink();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_at_back(block_pointer pb) noexcept
|
|
341
|
+
{
|
|
342
|
+
pb->link_available_before(header());
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_at_front(block_pointer pb) noexcept
|
|
346
|
+
{
|
|
347
|
+
pb->link_available_after(header());
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
BOOST_CONTAINER_FORCEINLINE void unlink_available(block_pointer pb) noexcept
|
|
351
|
+
{
|
|
352
|
+
pb->unlink_available();
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
template<typename ValuePointer>
|
|
357
|
+
class iterator
|
|
358
|
+
{
|
|
359
|
+
using element_type = typename pointer_traits<ValuePointer>::element_type;
|
|
360
|
+
template<typename Value2Pointer>
|
|
361
|
+
using enable_if_consts_to_element_type_t =typename std::enable_if<
|
|
362
|
+
std::is_same<
|
|
363
|
+
const typename pointer_traits<Value2Pointer>::element_type,
|
|
364
|
+
element_type>::value
|
|
365
|
+
>::type;
|
|
366
|
+
|
|
367
|
+
public:
|
|
368
|
+
using value_type = typename std::remove_const<element_type>::type;
|
|
369
|
+
using difference_type =
|
|
370
|
+
typename pointer_traits<ValuePointer>::difference_type;
|
|
371
|
+
using pointer = ValuePointer;
|
|
372
|
+
using reference = element_type&;
|
|
373
|
+
using iterator_category = std::bidirectional_iterator_tag;
|
|
374
|
+
|
|
375
|
+
BOOST_CONTAINER_FORCEINLINE iterator() = default;
|
|
376
|
+
BOOST_CONTAINER_FORCEINLINE iterator(const iterator& x) noexcept: pbb{x.pbb}, n{x.n} {}
|
|
377
|
+
|
|
378
|
+
template<
|
|
379
|
+
typename Value2Pointer,
|
|
380
|
+
typename = enable_if_consts_to_element_type_t<Value2Pointer>
|
|
381
|
+
>
|
|
382
|
+
BOOST_CONTAINER_FORCEINLINE iterator(const iterator<Value2Pointer>& x) noexcept:
|
|
383
|
+
pbb{x.pbb}, n{x.n} {}
|
|
384
|
+
|
|
385
|
+
BOOST_CONTAINER_FORCEINLINE iterator& operator=(const iterator& x) noexcept
|
|
386
|
+
{
|
|
387
|
+
pbb = x.pbb;
|
|
388
|
+
n = x.n;
|
|
389
|
+
return *this;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
template<
|
|
393
|
+
typename Value2Pointer,
|
|
394
|
+
typename = enable_if_consts_to_element_type_t<Value2Pointer>
|
|
395
|
+
>
|
|
396
|
+
BOOST_CONTAINER_FORCEINLINE iterator& operator=(
|
|
397
|
+
const iterator<Value2Pointer>& x) noexcept
|
|
398
|
+
{
|
|
399
|
+
pbb = x.pbb;
|
|
400
|
+
n = x.n;
|
|
401
|
+
return *this;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
BOOST_CONTAINER_FORCEINLINE pointer operator->() const noexcept
|
|
405
|
+
{
|
|
406
|
+
return static_cast<block&>(*pbb).data() + n;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
BOOST_CONTAINER_FORCEINLINE reference operator*() const noexcept
|
|
410
|
+
{
|
|
411
|
+
return *operator->();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
BOOST_CONTAINER_FORCEINLINE iterator& operator++() noexcept
|
|
415
|
+
{
|
|
416
|
+
auto mask = pbb->mask & (full << 1 << n);
|
|
417
|
+
if(BOOST_UNLIKELY(mask == 0)) {
|
|
418
|
+
pbb = pbb->next;
|
|
419
|
+
BOOST_CONTAINER_HUB_PREFETCH(pbb->next->next);
|
|
420
|
+
BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb->next, block);
|
|
421
|
+
mask = pbb->mask;
|
|
422
|
+
}
|
|
423
|
+
n = dtl::unchecked_countr_zero(mask);
|
|
424
|
+
return *this;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
BOOST_CONTAINER_FORCEINLINE iterator operator++(int) noexcept
|
|
428
|
+
{
|
|
429
|
+
iterator tmp(*this);
|
|
430
|
+
this->operator++();
|
|
431
|
+
return tmp;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
BOOST_CONTAINER_FORCEINLINE iterator& operator--() noexcept
|
|
435
|
+
{
|
|
436
|
+
auto mask = pbb->mask & (full >> 1 >> (N - 1 - n));
|
|
437
|
+
if(BOOST_UNLIKELY(mask == 0)) {
|
|
438
|
+
pbb = pbb->prev;
|
|
439
|
+
BOOST_CONTAINER_HUB_PREFETCH(pbb->prev->prev);
|
|
440
|
+
BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb->prev, block);
|
|
441
|
+
mask = pbb->mask;
|
|
442
|
+
}
|
|
443
|
+
n = N - 1 - dtl::unchecked_countl_zero(mask);
|
|
444
|
+
return *this;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
BOOST_CONTAINER_FORCEINLINE iterator operator--(int) noexcept
|
|
448
|
+
{
|
|
449
|
+
iterator tmp(*this);
|
|
450
|
+
this->operator--();
|
|
451
|
+
return tmp;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
BOOST_CONTAINER_FORCEINLINE friend bool operator==(
|
|
455
|
+
const iterator& x, const iterator& y) noexcept
|
|
456
|
+
{
|
|
457
|
+
return x.pbb == y.pbb && x.n == y.n;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(
|
|
461
|
+
const iterator& x, const iterator& y) noexcept
|
|
462
|
+
{
|
|
463
|
+
return !(x == y);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
private:
|
|
467
|
+
template<typename> friend class iterator;
|
|
468
|
+
template<typename, typename> friend class container::hub;
|
|
469
|
+
template<typename VP, typename F>
|
|
470
|
+
friend std::pair<hub_detail::iterator<VP>, F> container::for_each_while(
|
|
471
|
+
hub_detail::iterator<VP>, hub_detail::iterator<VP>, F);
|
|
472
|
+
template<typename T, typename A, typename F>
|
|
473
|
+
friend std::pair<typename hub<T, A>::iterator, F> container::for_each_while(
|
|
474
|
+
hub<T, A>&, F);
|
|
475
|
+
|
|
476
|
+
template<typename T>
|
|
477
|
+
using pointer_rebind_t = hub_detail::pointer_rebind_t<ValuePointer, T>;
|
|
478
|
+
using block_base = hub_detail::block_base<pointer_rebind_t<void>>;
|
|
479
|
+
using block_base_pointer = pointer_rebind_t<block_base>;
|
|
480
|
+
using const_block_base_pointer = pointer_rebind_t<const block_base>;
|
|
481
|
+
using nonconst_pointer = pointer_rebind_t<value_type>; //used by Natvis
|
|
482
|
+
using block = hub_detail::block<nonconst_pointer>;
|
|
483
|
+
using mask_type = typename block_base::mask_type;
|
|
484
|
+
|
|
485
|
+
static constexpr int N = block_base::N;
|
|
486
|
+
static constexpr mask_type full = block_base::full;
|
|
487
|
+
|
|
488
|
+
BOOST_CONTAINER_FORCEINLINE iterator(const_block_base_pointer pbb_, int n_) noexcept:
|
|
489
|
+
pbb{const_cast_block_base_pointer(pbb_)}, n{n_} {}
|
|
490
|
+
|
|
491
|
+
BOOST_CONTAINER_FORCEINLINE iterator(const_block_base_pointer pbb_) noexcept:
|
|
492
|
+
pbb{const_cast_block_base_pointer(pbb_)},
|
|
493
|
+
n{dtl::unchecked_countr_zero(pbb->mask)}
|
|
494
|
+
{}
|
|
495
|
+
|
|
496
|
+
static block_base_pointer
|
|
497
|
+
const_cast_block_base_pointer(const_block_base_pointer pbb_) noexcept
|
|
498
|
+
{
|
|
499
|
+
return block_base::pointer_to(const_cast<block_base&>(*pbb_));
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
block_base_pointer pbb = nullptr;
|
|
503
|
+
int n = 0;
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
template<class F>
|
|
507
|
+
struct inline_ref_caller
|
|
508
|
+
{
|
|
509
|
+
F& f;
|
|
510
|
+
|
|
511
|
+
template<typename T>
|
|
512
|
+
BOOST_CONTAINER_FORCEINLINE auto operator()(T&& x) ->
|
|
513
|
+
decltype(std::declval<F>()(std::declval<T&&>()))
|
|
514
|
+
{
|
|
515
|
+
return f(std::forward<T>(x));
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
template<class F>
|
|
520
|
+
struct inline_ref_const_caller
|
|
521
|
+
{
|
|
522
|
+
F& f;
|
|
523
|
+
|
|
524
|
+
template<typename T>
|
|
525
|
+
BOOST_CONTAINER_FORCEINLINE auto operator()(const T& x) ->
|
|
526
|
+
decltype(std::declval<F>()(std::declval<const T&>()))
|
|
527
|
+
{
|
|
528
|
+
return f(x);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
template<class F>
|
|
533
|
+
struct inline_return_true_ref_caller
|
|
534
|
+
{
|
|
535
|
+
F& f;
|
|
536
|
+
|
|
537
|
+
template<typename T>
|
|
538
|
+
BOOST_CONTAINER_FORCEINLINE bool operator()(T&& x)
|
|
539
|
+
{
|
|
540
|
+
f(std::forward<T>(x));
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
template<class F>
|
|
546
|
+
struct inline_return_true_ref_const_caller
|
|
547
|
+
{
|
|
548
|
+
F& f;
|
|
549
|
+
|
|
550
|
+
template<typename T>
|
|
551
|
+
BOOST_CONTAINER_FORCEINLINE bool operator()(const T& x)
|
|
552
|
+
{
|
|
553
|
+
f(x);
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
template<typename T, std::size_t N>
|
|
559
|
+
struct sort_iterator
|
|
560
|
+
{
|
|
561
|
+
using value_type = T;
|
|
562
|
+
using difference_type = std::ptrdiff_t;
|
|
563
|
+
using pointer = T*;
|
|
564
|
+
using reference = T&;
|
|
565
|
+
using iterator_category = std::random_access_iterator_tag;
|
|
566
|
+
|
|
567
|
+
sort_iterator(T** pp_, difference_type index_): pp{pp_}, index{index_} {}
|
|
568
|
+
|
|
569
|
+
pointer operator->() const noexcept
|
|
570
|
+
{
|
|
571
|
+
return pp[(std::size_t)index / N] + ((std::size_t)index % N);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
reference operator*() const noexcept
|
|
575
|
+
{
|
|
576
|
+
return *operator->();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
sort_iterator& operator++() noexcept
|
|
580
|
+
{
|
|
581
|
+
++index;
|
|
582
|
+
return *this;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
sort_iterator operator++(int) noexcept
|
|
586
|
+
{
|
|
587
|
+
sort_iterator tmp(*this);
|
|
588
|
+
++index;
|
|
589
|
+
return tmp;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
sort_iterator& operator--() noexcept
|
|
593
|
+
{
|
|
594
|
+
--index;
|
|
595
|
+
return *this;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
sort_iterator operator--(int) noexcept
|
|
599
|
+
{
|
|
600
|
+
sort_iterator tmp(*this);
|
|
601
|
+
--index;
|
|
602
|
+
return tmp;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
friend difference_type
|
|
606
|
+
operator-(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
607
|
+
{
|
|
608
|
+
return x.index - y.index;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
sort_iterator& operator+=(difference_type n) noexcept
|
|
612
|
+
{
|
|
613
|
+
index += n;
|
|
614
|
+
return *this;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
friend sort_iterator
|
|
618
|
+
operator+(const sort_iterator& x, difference_type n) noexcept
|
|
619
|
+
{
|
|
620
|
+
return {x.pp, x.index + n};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
friend sort_iterator
|
|
624
|
+
operator+(difference_type n, const sort_iterator& x) noexcept
|
|
625
|
+
{
|
|
626
|
+
return {x.pp, n + x.index};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
sort_iterator& operator-=(difference_type n) noexcept
|
|
630
|
+
{
|
|
631
|
+
index -= n;
|
|
632
|
+
return *this;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
friend sort_iterator
|
|
636
|
+
operator-(const sort_iterator& x, difference_type n) noexcept
|
|
637
|
+
{
|
|
638
|
+
return {x.pp, x.index - n};
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
reference operator[](difference_type n) const noexcept
|
|
642
|
+
{
|
|
643
|
+
return *(*this + n);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
friend bool
|
|
647
|
+
operator==(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
648
|
+
{
|
|
649
|
+
return x.index == y.index;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
friend bool
|
|
653
|
+
operator!=(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
654
|
+
{
|
|
655
|
+
return x.index != y.index;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
friend bool
|
|
659
|
+
operator<(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
660
|
+
{
|
|
661
|
+
return x.index < y.index;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
friend bool
|
|
665
|
+
operator>(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
666
|
+
{
|
|
667
|
+
return x.index > y.index;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
friend bool
|
|
671
|
+
operator<=(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
672
|
+
{
|
|
673
|
+
return x.index <= y.index;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
friend bool
|
|
677
|
+
operator>=(const sort_iterator& x, const sort_iterator& y) noexcept
|
|
678
|
+
{
|
|
679
|
+
return x.index >= y.index;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
T** pp;
|
|
683
|
+
difference_type index;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
template<typename T, typename Allocator>
|
|
687
|
+
struct buffer
|
|
688
|
+
{
|
|
689
|
+
buffer(std::size_t n, Allocator al_) noexcept: al{al_}
|
|
690
|
+
{
|
|
691
|
+
allocate_data(n);
|
|
692
|
+
if(data) capacity = n;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
~buffer()
|
|
696
|
+
{
|
|
697
|
+
if(data) {
|
|
698
|
+
for(; begin_ != end_; ++begin_) allocator_traits<Allocator>::destroy(al, begin());
|
|
699
|
+
deallocate_data();
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
T* begin() const noexcept { return data + begin_; }
|
|
704
|
+
T* end() const noexcept { return data + end_; }
|
|
705
|
+
|
|
706
|
+
template<typename... Args>
|
|
707
|
+
void emplace_back(Args&&... args)
|
|
708
|
+
{
|
|
709
|
+
BOOST_ASSERT(data && end_ != capacity);
|
|
710
|
+
allocator_traits<Allocator>::construct(al, end(), std::forward<Args>(args)...);
|
|
711
|
+
++end_;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
void erase_front() noexcept
|
|
715
|
+
{
|
|
716
|
+
BOOST_ASSERT(data && begin_ != end_);
|
|
717
|
+
allocator_traits<Allocator>::destroy(al, begin());
|
|
718
|
+
++begin_;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
Allocator al;
|
|
722
|
+
std::size_t begin_ = 0, end_ = 0;
|
|
723
|
+
std::size_t capacity = 0;
|
|
724
|
+
T* data = nullptr;
|
|
725
|
+
|
|
726
|
+
private:
|
|
727
|
+
//Portable, nothrow, (over)aligned allocation: this is the same primitive
|
|
728
|
+
//boost::container::new_allocator relies on for overalignment, so there is no
|
|
729
|
+
//need to special-case __cpp_aligned_new here. The nothrow null return lets
|
|
730
|
+
//sort() fall back to a leaner algorithm when this (possibly large) scratch
|
|
731
|
+
//buffer cannot be allocated.
|
|
732
|
+
void allocate_data(std::size_t n)
|
|
733
|
+
{
|
|
734
|
+
data = static_cast<T*>(dtl::aligned_allocate(alignof(T), n * sizeof(T)));
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
void deallocate_data() { dtl::aligned_deallocate(data); }
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
template<typename T>
|
|
741
|
+
struct nodtor_deleter
|
|
742
|
+
{
|
|
743
|
+
using pointer = T*;
|
|
744
|
+
void operator()(pointer p) noexcept { ::operator delete(p); }
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
template<typename T>
|
|
748
|
+
struct nodtor_deleter<T[]>
|
|
749
|
+
{
|
|
750
|
+
using pointer = T*;
|
|
751
|
+
void operator()(pointer p) noexcept { ::operator delete[](p); }
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
template<typename T>
|
|
755
|
+
using nodtor_unique_ptr = boost::movelib::unique_ptr<T, nodtor_deleter<T>>;
|
|
756
|
+
|
|
757
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
758
|
+
//begin()/end() access (without <ranges> or std::begin/std::end) lives in
|
|
759
|
+
//boost::container::dtl::adl_range (range_utils.hpp); reuse it here.
|
|
760
|
+
template<class R>
|
|
761
|
+
using range_iterator_t = decltype(dtl::adl_range::adl_begin(std::declval<R&>()));
|
|
762
|
+
|
|
763
|
+
template<class R>
|
|
764
|
+
using range_reference_t = std::iter_reference_t<range_iterator_t<R> >;
|
|
765
|
+
|
|
766
|
+
template<class R>
|
|
767
|
+
using range_value_t = std::iter_value_t<range_iterator_t<R> >;
|
|
768
|
+
|
|
769
|
+
template<class R>
|
|
770
|
+
concept input_range_like =
|
|
771
|
+
requires(R& r) {
|
|
772
|
+
dtl::adl_range::adl_begin(r);
|
|
773
|
+
dtl::adl_range::adl_end(r);
|
|
774
|
+
} &&
|
|
775
|
+
std::input_iterator<range_iterator_t<R> >;
|
|
776
|
+
|
|
777
|
+
template<class R, class T>
|
|
778
|
+
concept container_compatible_range =
|
|
779
|
+
input_range_like<R> &&
|
|
780
|
+
std::convertible_to<range_reference_t<R>, T>;
|
|
781
|
+
|
|
782
|
+
#endif
|
|
783
|
+
|
|
784
|
+
template<typename InputIterator>
|
|
785
|
+
using enable_if_is_input_iterator_t =
|
|
786
|
+
typename std::enable_if<
|
|
787
|
+
std::is_convertible<
|
|
788
|
+
typename std::iterator_traits<InputIterator>::iterator_category,
|
|
789
|
+
std::input_iterator_tag
|
|
790
|
+
>::value
|
|
791
|
+
>::type;
|
|
792
|
+
|
|
793
|
+
//std::pmr::polymorphic_allocator::destroy may be marked as deprecated.
|
|
794
|
+
//C&P from boost/core/allocator_access.hpp.
|
|
795
|
+
#if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH)
|
|
796
|
+
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
|
|
797
|
+
#endif
|
|
798
|
+
#if defined(_STL_DISABLE_DEPRECATED_WARNING)
|
|
799
|
+
_STL_DISABLE_DEPRECATED_WARNING
|
|
800
|
+
#endif
|
|
801
|
+
#if defined(__clang__) && defined(__has_warning)
|
|
802
|
+
# if __has_warning("-Wdeprecated-declarations")
|
|
803
|
+
# pragma clang diagnostic push
|
|
804
|
+
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
805
|
+
# endif
|
|
806
|
+
#elif defined(_MSC_VER)
|
|
807
|
+
# pragma warning(push)
|
|
808
|
+
# pragma warning(disable: 4996)
|
|
809
|
+
#elif defined(BOOST_GCC) && BOOST_GCC >= 40600
|
|
810
|
+
# pragma GCC diagnostic push
|
|
811
|
+
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
812
|
+
#endif
|
|
813
|
+
|
|
814
|
+
template<typename Allocator, typename Ptr, typename = void>
|
|
815
|
+
struct allocator_has_destroy: std::false_type {};
|
|
816
|
+
|
|
817
|
+
template<typename Allocator, typename Ptr>
|
|
818
|
+
struct allocator_has_destroy<
|
|
819
|
+
Allocator, Ptr,
|
|
820
|
+
decltype((void)std::declval<Allocator&>().destroy(std::declval<Ptr>()))
|
|
821
|
+
>: std::true_type {};
|
|
822
|
+
|
|
823
|
+
#if defined(__clang__) && defined(__has_warning)
|
|
824
|
+
# if __has_warning("-Wdeprecated-declarations")
|
|
825
|
+
# pragma clang diagnostic pop
|
|
826
|
+
# endif
|
|
827
|
+
#elif defined(_MSC_VER)
|
|
828
|
+
# pragma warning(pop)
|
|
829
|
+
#elif defined(BOOST_GCC) && BOOST_GCC >= 40600
|
|
830
|
+
# pragma GCC diagnostic pop
|
|
831
|
+
#endif
|
|
832
|
+
#if defined(_STL_RESTORE_DEPRECATED_WARNING)
|
|
833
|
+
_STL_RESTORE_DEPRECATED_WARNING
|
|
834
|
+
#endif
|
|
835
|
+
#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP)
|
|
836
|
+
_LIBCPP_SUPPRESS_DEPRECATED_POP
|
|
837
|
+
#endif
|
|
838
|
+
|
|
839
|
+
template<typename Allocator>
|
|
840
|
+
struct is_std_allocator: std::false_type {};
|
|
841
|
+
|
|
842
|
+
template<typename T>
|
|
843
|
+
struct is_std_allocator<std::allocator<T>>: std::true_type {};
|
|
844
|
+
|
|
845
|
+
template<typename Allocator>
|
|
846
|
+
struct is_std_pmr_polymorphic_allocator: std::false_type {};
|
|
847
|
+
|
|
848
|
+
#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE
|
|
849
|
+
template<typename T>
|
|
850
|
+
struct is_std_pmr_polymorphic_allocator<std::pmr::polymorphic_allocator<T>>:
|
|
851
|
+
std::true_type {};
|
|
852
|
+
#endif
|
|
853
|
+
|
|
854
|
+
struct if_constexpr_void_else{ void operator()() const {} };
|
|
855
|
+
|
|
856
|
+
template<typename F, typename G = if_constexpr_void_else>
|
|
857
|
+
void if_constexpr(std::true_type, F f, G = G{}) { f(); }
|
|
858
|
+
|
|
859
|
+
template<typename F, typename G = if_constexpr_void_else>
|
|
860
|
+
void if_constexpr(std::false_type, F, G g = G{}) { g(); }
|
|
861
|
+
|
|
862
|
+
template<typename T>
|
|
863
|
+
void copy_assign_if(std::true_type, T& x, const T& y) { x = y; }
|
|
864
|
+
|
|
865
|
+
template<typename T>
|
|
866
|
+
void copy_assign_if(std::false_type, T&, const T&) {}
|
|
867
|
+
|
|
868
|
+
template<typename T>
|
|
869
|
+
void move_assign_if(std::true_type, T& x, T& y) { x = std::move(y); }
|
|
870
|
+
|
|
871
|
+
template<typename T>
|
|
872
|
+
void move_assign_if(std::false_type, T&, T&) {}
|
|
873
|
+
|
|
874
|
+
template<typename T>
|
|
875
|
+
void swap_if(std::true_type, T& x, T& y) { using std::swap; swap(x, y); }
|
|
876
|
+
|
|
877
|
+
template<typename T>
|
|
878
|
+
void swap_if(std::false_type, T&, T&) {}
|
|
879
|
+
|
|
880
|
+
template<typename Allocator>
|
|
881
|
+
struct block_typedefs
|
|
882
|
+
{
|
|
883
|
+
using pointer = typename allocator_traits<Allocator>::pointer;
|
|
884
|
+
template<typename Q>
|
|
885
|
+
using pointer_rebind_t = hub_detail::pointer_rebind_t<pointer, Q>;
|
|
886
|
+
|
|
887
|
+
using block_base = hub_detail::block_base<pointer_rebind_t<void>>;
|
|
888
|
+
using block_base_pointer = pointer_rebind_t<block_base>;
|
|
889
|
+
using const_block_base_pointer = pointer_rebind_t<const block_base>;
|
|
890
|
+
using block = hub_detail::block<pointer>;
|
|
891
|
+
using block_pointer = pointer_rebind_t<block>;
|
|
892
|
+
using block_allocator =
|
|
893
|
+
typename allocator_traits<Allocator>::template portable_rebind_alloc<block>::type;
|
|
894
|
+
using block_list = hub_detail::block_list<pointer>;
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
} //namespace container::hub_detail
|
|
898
|
+
|
|
899
|
+
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
900
|
+
|
|
901
|
+
//! A hub is a container with constant-time insertion and erasure and element
|
|
902
|
+
//! stability: pointers and iterators to an element remain valid until the
|
|
903
|
+
//! element is erased. It is a nearly drop-in, more compact alternative to the
|
|
904
|
+
//! C++26 \c std::hive.
|
|
905
|
+
//!
|
|
906
|
+
//! Elements of a hub are stored in \e blocks of contiguous memory, each with a fixed
|
|
907
|
+
//! element capacity. The insertion position is chosen by the container,
|
|
908
|
+
//! which may reuse the memory of previously erased elements. A block with at
|
|
909
|
+
//! least one element is called \e active; an empty block kept internally for
|
|
910
|
+
//! future reuse is called \e reserved. Reserved blocks are not used until all
|
|
911
|
+
//! active blocks are full, and are only deallocated by \c shrink_to_fit,
|
|
912
|
+
//! \c trim_capacity or on container destruction. New blocks are allocated only
|
|
913
|
+
//! when every block is full or when the user issues a \c reserve operation.
|
|
914
|
+
//!
|
|
915
|
+
//! \c hub<T, Allocator> is a model of \c Container, \c ReversibleContainer,
|
|
916
|
+
//! \c AllocatorAwareContainer and \c SequenceContainer, with the following
|
|
917
|
+
//! exceptions: operators \c == and \c != are not provided, and positional
|
|
918
|
+
//! insertion of the form \c insert(position,\ ...) or \c emplace(position,\ ...)
|
|
919
|
+
//! is not provided or ignores the position argument. Its iterators model
|
|
920
|
+
//! \c LegacyBidirectionalIterator.
|
|
921
|
+
//!
|
|
922
|
+
//! \tparam T The cv-unqualified object type of the elements stored in the hub.
|
|
923
|
+
//! \tparam Allocator An allocator whose value type is \c T. If \c void (the
|
|
924
|
+
//! default), \c boost::container::new_allocator<T> is used.
|
|
925
|
+
//!
|
|
926
|
+
//! <b>Exception safety</b>: Except when explicitly noted, all non-const member
|
|
927
|
+
//! functions (and free functions taking \c hub by non-const reference) provide
|
|
928
|
+
//! the basic exception guarantee, whereas all const member functions (and free
|
|
929
|
+
//! functions taking \c hub by const reference) provide the strong guarantee.
|
|
930
|
+
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
931
|
+
template<typename T, typename Allocator = void>
|
|
932
|
+
class hub
|
|
933
|
+
#else
|
|
934
|
+
template<typename T, typename AllocatorOrVoid>
|
|
935
|
+
class hub
|
|
936
|
+
: hub_detail::block_typedefs<typename real_allocator<T, AllocatorOrVoid>::type>::block_allocator
|
|
937
|
+
#endif
|
|
938
|
+
{
|
|
939
|
+
public:
|
|
940
|
+
//! new_allocator<T> is if Allocator is void, an alias for Allocator otherwise.
|
|
941
|
+
typedef BOOST_CONTAINER_IMPDEF
|
|
942
|
+
(typename real_allocator<T BOOST_MOVE_I AllocatorOrVoid>::type) allocator_type;
|
|
943
|
+
|
|
944
|
+
private:
|
|
945
|
+
static_assert(
|
|
946
|
+
!std::is_const<T>::value && !std::is_volatile<T>::value &&
|
|
947
|
+
!std::is_function<T>::value && !std::is_reference<T>::value &&
|
|
948
|
+
!std::is_void<T>::value,
|
|
949
|
+
"T must be a cv-unqualified object type");
|
|
950
|
+
static_assert(
|
|
951
|
+
std::is_same<T, typename allocator_traits<allocator_type>::value_type>::value,
|
|
952
|
+
"Allocator's value_type must be the same type as T");
|
|
953
|
+
|
|
954
|
+
public:
|
|
955
|
+
using value_type = T;
|
|
956
|
+
using pointer = typename allocator_traits<allocator_type>::pointer;
|
|
957
|
+
using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
|
|
958
|
+
using reference = T&;
|
|
959
|
+
using const_reference = const T&;
|
|
960
|
+
using size_type = typename allocator_traits<allocator_type>::size_type;
|
|
961
|
+
using difference_type = typename allocator_traits<allocator_type>::difference_type;
|
|
962
|
+
using iterator = hub_detail::iterator<pointer>;
|
|
963
|
+
using const_iterator = hub_detail::iterator<const_pointer>;
|
|
964
|
+
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
965
|
+
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
966
|
+
|
|
967
|
+
//! <b>Effects</b>: Constructs an empty hub, using \c allocator_type() as the allocator.
|
|
968
|
+
//!
|
|
969
|
+
//! <b>Requires</b>: \c allocator_type is DefaultConstructible.
|
|
970
|
+
//!
|
|
971
|
+
//! <b>Complexity</b>: Constant.
|
|
972
|
+
hub() noexcept(noexcept(allocator_type())): hub{allocator_type()} {}
|
|
973
|
+
|
|
974
|
+
//! <b>Effects</b>: Constructs an empty hub, using the specified allocator.
|
|
975
|
+
//!
|
|
976
|
+
//! <b>Complexity</b>: Constant.
|
|
977
|
+
explicit hub(const allocator_type& al_) noexcept:
|
|
978
|
+
allocator_base(al_) {}
|
|
979
|
+
|
|
980
|
+
//! <b>Effects</b>: Constructs a hub with n default-inserted elements, using
|
|
981
|
+
//! the specified allocator.
|
|
982
|
+
//!
|
|
983
|
+
//! <b>Requires</b>: T is DefaultInsertable into the hub.
|
|
984
|
+
//!
|
|
985
|
+
//! <b>Complexity</b>: Linear in n.
|
|
986
|
+
explicit hub(size_type n, const allocator_type& al_ = allocator_type()): hub{al_}
|
|
987
|
+
{
|
|
988
|
+
range_insert_impl(size_type(0), n, [&, this] (T* p, size_type) {
|
|
989
|
+
block_alloc_traits::construct(al(), p);
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
//! <b>Effects</b>: Constructs a hub with n copies of value, using the
|
|
994
|
+
//! specified allocator.
|
|
995
|
+
//!
|
|
996
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub.
|
|
997
|
+
//!
|
|
998
|
+
//! <b>Complexity</b>: Linear in n.
|
|
999
|
+
hub(size_type n, const T& x, const allocator_type& al_ = allocator_type()): hub{al_}
|
|
1000
|
+
{
|
|
1001
|
+
insert(n, x);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
//! <b>Effects</b>: Constructs a hub equal to the range [first, last), using
|
|
1005
|
+
//! the specified allocator.
|
|
1006
|
+
//!
|
|
1007
|
+
//! <b>Complexity</b>: Linear in std::distance(first, last).
|
|
1008
|
+
template<
|
|
1009
|
+
typename InputIterator
|
|
1010
|
+
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename = hub_detail::enable_if_is_input_iterator_t<InputIterator>)
|
|
1011
|
+
>
|
|
1012
|
+
hub(
|
|
1013
|
+
InputIterator first, InputIterator last,
|
|
1014
|
+
const allocator_type& al_ = allocator_type()): hub{al_}
|
|
1015
|
+
{
|
|
1016
|
+
insert(first, last);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
1020
|
+
//! <b>Effects</b>: Constructs a hub equal to the range rg, using the
|
|
1021
|
+
//! specified allocator.
|
|
1022
|
+
//!
|
|
1023
|
+
//! <b>Complexity</b>: Linear in std::ranges::distance(rg).
|
|
1024
|
+
template< BOOST_CONTAINER_DOC1ST(std::ranges::input_range<T>, hub_detail::container_compatible_range<T>) R >
|
|
1025
|
+
hub(from_range_t, R&& rg, const allocator_type& al_ = allocator_type()): hub{al_}
|
|
1026
|
+
{
|
|
1027
|
+
insert_range(std::forward<R>(rg));
|
|
1028
|
+
}
|
|
1029
|
+
#endif
|
|
1030
|
+
|
|
1031
|
+
//! <b>Effects</b>: Constructs a hub equal to x. The second overload uses the
|
|
1032
|
+
//! given allocator.
|
|
1033
|
+
//!
|
|
1034
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub.
|
|
1035
|
+
//!
|
|
1036
|
+
//! <b>Complexity</b>: Linear in x.size().
|
|
1037
|
+
hub(const hub& x):
|
|
1038
|
+
hub{x, block_alloc_traits::select_on_container_copy_construction(x.al())} {}
|
|
1039
|
+
|
|
1040
|
+
//! <b>Effects</b>: Constructs a hub equal to x, using the given allocator.
|
|
1041
|
+
//!
|
|
1042
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub.
|
|
1043
|
+
//!
|
|
1044
|
+
//! <b>Complexity</b>: Linear in x.size().
|
|
1045
|
+
hub( const hub& x
|
|
1046
|
+
, const BOOST_CONTAINER_DOC1ST(allocator_type, dtl::type_identity_t<allocator_type>) &al_):
|
|
1047
|
+
hub(x.begin(), x.end(), al_) {}
|
|
1048
|
+
|
|
1049
|
+
//! <b>Effects</b>: Move constructor. Element blocks are moved from x into
|
|
1050
|
+
//! *this; pointers, references and iterators to elements of x remain valid
|
|
1051
|
+
//! but now refer to *this.
|
|
1052
|
+
//!
|
|
1053
|
+
//! <b>Postcondition</b>: x.empty() is true.
|
|
1054
|
+
//!
|
|
1055
|
+
//! <b>Complexity</b>: Constant.
|
|
1056
|
+
hub(hub&& x) noexcept:
|
|
1057
|
+
hub{std::move(x), allocator_type(std::move(x.al())), std::true_type{}} {}
|
|
1058
|
+
|
|
1059
|
+
//! <b>Effects</b>: allocator_type-extended move constructor. If alloc equals
|
|
1060
|
+
//! x.get_allocator() the element blocks are moved (iterators/pointers to x
|
|
1061
|
+
//! remain valid as members of *this); otherwise each element is moved into
|
|
1062
|
+
//! *this and references, pointers and iterators to x are invalidated.
|
|
1063
|
+
//!
|
|
1064
|
+
//! <b>Requires</b>: T is MoveInsertable when the allocators may be unequal.
|
|
1065
|
+
//!
|
|
1066
|
+
//! <b>Postcondition</b>: x.empty() is true.
|
|
1067
|
+
//!
|
|
1068
|
+
//! <b>Complexity</b>: Constant, or linear in x.size() if elements are moved
|
|
1069
|
+
//! one by one.
|
|
1070
|
+
hub( hub&& x
|
|
1071
|
+
, const BOOST_CONTAINER_DOC1ST(allocator_type, dtl::type_identity_t<allocator_type>) &al_):
|
|
1072
|
+
hub{std::move(x), al_, hub_detail::is_always_equal_t<allocator_type>{}} {}
|
|
1073
|
+
|
|
1074
|
+
//! <b>Effects</b>: Constructs a hub equal to il, using the specified allocator.
|
|
1075
|
+
//!
|
|
1076
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub.
|
|
1077
|
+
//!
|
|
1078
|
+
//! <b>Complexity</b>: Linear in il.size().
|
|
1079
|
+
hub(std::initializer_list<T> il, const allocator_type& al_ = allocator_type()):
|
|
1080
|
+
hub{il.begin(), il.end(), al_} {}
|
|
1081
|
+
|
|
1082
|
+
//! <b>Effects</b>: Destroys all elements and deallocates all blocks.
|
|
1083
|
+
//!
|
|
1084
|
+
//! <b>Complexity</b>: Linear in size() plus the number of blocks.
|
|
1085
|
+
~hub() { reset(); }
|
|
1086
|
+
|
|
1087
|
+
//! <b>Effects</b>: Copy assignment. Existing elements are copy-assigned or
|
|
1088
|
+
//! destroyed and the elements of x are copied into *this, keeping their
|
|
1089
|
+
//! relative order.
|
|
1090
|
+
//!
|
|
1091
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub and CopyAssignable.
|
|
1092
|
+
//!
|
|
1093
|
+
//! <b>Complexity</b>: Linear in size() + x.size().
|
|
1094
|
+
hub& operator=(const hub& x)
|
|
1095
|
+
{
|
|
1096
|
+
using pocca = hub_detail::pocca_t<allocator_type>;
|
|
1097
|
+
|
|
1098
|
+
if(this != &x) {
|
|
1099
|
+
if(al() != x.al() && pocca::value) {
|
|
1100
|
+
reset();
|
|
1101
|
+
hub_detail::copy_assign_if(pocca{}, al(), x.al());
|
|
1102
|
+
insert(x.begin(), x.end());
|
|
1103
|
+
}
|
|
1104
|
+
else{
|
|
1105
|
+
hub_detail::copy_assign_if(pocca{}, al(), x.al());
|
|
1106
|
+
assign(x.begin(), x.end());
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
return *this;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
//! <b>Effects</b>: Move assignment. Existing elements are move-assigned or
|
|
1113
|
+
//! destroyed. If the allocator propagates on move assignment or both
|
|
1114
|
+
//! allocators are equal, element blocks are moved from x (iterators/pointers
|
|
1115
|
+
//! to x remain valid as members of *this); otherwise each element of x is
|
|
1116
|
+
//! moved into *this and references, pointers and iterators to x are
|
|
1117
|
+
//! invalidated.
|
|
1118
|
+
//!
|
|
1119
|
+
//! <b>Requires</b>: T is MoveInsertable and MoveAssignable when elements are
|
|
1120
|
+
//! moved one by one.
|
|
1121
|
+
//!
|
|
1122
|
+
//! <b>Postcondition</b>: x.empty() is true.
|
|
1123
|
+
//!
|
|
1124
|
+
//! <b>Complexity</b>: Linear in size(), plus linear in x.size() when elements
|
|
1125
|
+
//! are moved one by one.
|
|
1126
|
+
hub& operator=(hub&& x)
|
|
1127
|
+
noexcept(
|
|
1128
|
+
hub_detail::pocma_t<allocator_type>::value ||
|
|
1129
|
+
hub_detail::is_always_equal_t<allocator_type>::value)
|
|
1130
|
+
{
|
|
1131
|
+
if(this != &x) {
|
|
1132
|
+
move_assign(
|
|
1133
|
+
x,
|
|
1134
|
+
std::integral_constant<
|
|
1135
|
+
bool,
|
|
1136
|
+
hub_detail::pocma_t<allocator_type>::
|
|
1137
|
+
value ||
|
|
1138
|
+
hub_detail::is_always_equal_t<allocator_type>::value>{});
|
|
1139
|
+
}
|
|
1140
|
+
return *this;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
//! <b>Effects</b>: Replaces the contents of *this with a copy of il.
|
|
1144
|
+
//!
|
|
1145
|
+
//! <b>Complexity</b>: Linear in size() + il.size().
|
|
1146
|
+
hub& operator=(std::initializer_list<T> il)
|
|
1147
|
+
{
|
|
1148
|
+
assign(il);
|
|
1149
|
+
return *this;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
//! <b>Effects</b>: Replaces the contents of *this with a copy of the range
|
|
1153
|
+
//! [first, last).
|
|
1154
|
+
//!
|
|
1155
|
+
//! <b>Complexity</b>: Linear in size() + std::distance(first, last).
|
|
1156
|
+
template<
|
|
1157
|
+
typename InputIterator
|
|
1158
|
+
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename = hub_detail::enable_if_is_input_iterator_t<InputIterator>)
|
|
1159
|
+
>
|
|
1160
|
+
void assign(InputIterator first, InputIterator last)
|
|
1161
|
+
{
|
|
1162
|
+
range_assign_impl(
|
|
1163
|
+
first, last,
|
|
1164
|
+
[this] (T* p, InputIterator it) { block_alloc_traits::construct(al(), p, *it); },
|
|
1165
|
+
[] (T* p, InputIterator it) { *p = *it; });
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
1169
|
+
//! <b>Effects</b>: Replaces the contents of *this with a copy of the elements
|
|
1170
|
+
//! in the range rg.
|
|
1171
|
+
//!
|
|
1172
|
+
//! <b>Complexity</b>: Linear in size() + std::ranges::distance(rg).
|
|
1173
|
+
template< BOOST_CONTAINER_DOC1ST(std::ranges::input_range<T>, hub_detail::container_compatible_range<T>) R >
|
|
1174
|
+
void assign_range(R&& rg)
|
|
1175
|
+
{
|
|
1176
|
+
range_assign_impl(
|
|
1177
|
+
dtl::adl_range::adl_begin(rg), dtl::adl_range::adl_end(rg),
|
|
1178
|
+
[this] (T* p, auto it) { block_alloc_traits::construct(al(), p, *it); },
|
|
1179
|
+
[] (T* p, auto it) { *p = *it; });
|
|
1180
|
+
}
|
|
1181
|
+
#endif
|
|
1182
|
+
|
|
1183
|
+
//! <b>Effects</b>: Replaces the contents of *this with n copies of x.
|
|
1184
|
+
//!
|
|
1185
|
+
//! <b>Complexity</b>: Linear in size() + n.
|
|
1186
|
+
void assign(size_type n, const T& x)
|
|
1187
|
+
{
|
|
1188
|
+
range_assign_impl(
|
|
1189
|
+
size_type(0), n,
|
|
1190
|
+
[&, this] (T* p, size_type) { block_alloc_traits::construct(al(), p, x); },
|
|
1191
|
+
[&] (T* p, size_type) { *p = x; });
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
//! <b>Effects</b>: Replaces the contents of *this with a copy of il.
|
|
1195
|
+
//!
|
|
1196
|
+
//! <b>Complexity</b>: Linear in size() + il.size().
|
|
1197
|
+
void assign(std::initializer_list<T> il) { assign(il.begin(), il.end()); }
|
|
1198
|
+
|
|
1199
|
+
//! <b>Effects</b>: Returns a copy of the allocator associated with *this.
|
|
1200
|
+
//!
|
|
1201
|
+
//! <b>Complexity</b>: Constant.
|
|
1202
|
+
allocator_type get_allocator() const noexcept { return al(); }
|
|
1203
|
+
|
|
1204
|
+
//! <b>Effects</b>: Returns an iterator to the first element, or end() if empty.
|
|
1205
|
+
//! The const overloads return a const_iterator. <b>Complexity</b>: Constant.
|
|
1206
|
+
iterator begin() noexcept { return ++end(); }
|
|
1207
|
+
const_iterator begin() const noexcept { return ++end(); }
|
|
1208
|
+
//! <b>Effects</b>: Returns the past-the-end iterator. The end iterator is
|
|
1209
|
+
//! stable: it is not invalidated by insertion or erasure. The const overloads
|
|
1210
|
+
//! return a const_iterator. <b>Complexity</b>: Constant.
|
|
1211
|
+
iterator end() noexcept { return {blist.header(), 0}; }
|
|
1212
|
+
const_iterator end() const noexcept { return {blist.header(), 0}; }
|
|
1213
|
+
//! <b>Effects</b>: Reverse and const iterator accessors, with the usual
|
|
1214
|
+
//! semantics. <b>Complexity</b>: Constant.
|
|
1215
|
+
reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
|
|
1216
|
+
const_reverse_iterator rbegin() const noexcept
|
|
1217
|
+
{ return const_reverse_iterator{end()}; }
|
|
1218
|
+
reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
|
|
1219
|
+
const_reverse_iterator rend() const noexcept
|
|
1220
|
+
{ return const_reverse_iterator{begin()}; }
|
|
1221
|
+
const_iterator cbegin() const noexcept { return begin(); }
|
|
1222
|
+
const_iterator cend() const noexcept { return end(); }
|
|
1223
|
+
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
|
1224
|
+
const_reverse_iterator crend() const noexcept { return rend(); }
|
|
1225
|
+
|
|
1226
|
+
//! <b>Effects</b>: Returns true if the hub contains no elements.
|
|
1227
|
+
//!
|
|
1228
|
+
//! <b>Complexity</b>: Constant.
|
|
1229
|
+
bool empty() const noexcept { return size_ == 0; }
|
|
1230
|
+
|
|
1231
|
+
//! <b>Effects</b>: Returns the number of elements in the hub.
|
|
1232
|
+
//!
|
|
1233
|
+
//! <b>Complexity</b>: Constant.
|
|
1234
|
+
size_type size() const noexcept { return size_; }
|
|
1235
|
+
|
|
1236
|
+
//! <b>Effects</b>: Returns the largest possible size of the hub.
|
|
1237
|
+
//!
|
|
1238
|
+
//! <b>Complexity</b>: Constant.
|
|
1239
|
+
size_type max_size() const noexcept
|
|
1240
|
+
{
|
|
1241
|
+
std::size_t
|
|
1242
|
+
bs = (std::size_t)block_alloc_traits::max_size(al()) * sizeof(block),
|
|
1243
|
+
vs = (std::size_t)value_alloc_traits::max_size(value_allocator(al())) * sizeof(T);
|
|
1244
|
+
return
|
|
1245
|
+
(size_type)((std::min)(bs, vs) / (sizeof(block) + sizeof(T) * N) * N);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
//! <b>Effects</b>: Returns the total number of elements that *this can hold
|
|
1249
|
+
//! without requiring allocation of more element blocks.
|
|
1250
|
+
//!
|
|
1251
|
+
//! <b>Complexity</b>: Constant.
|
|
1252
|
+
size_type capacity() const noexcept { return num_blocks * N; }
|
|
1253
|
+
|
|
1254
|
+
//! <b>Effects</b>: If n <= capacity() there are no effects; otherwise
|
|
1255
|
+
//! increases capacity() by allocating reserved blocks.
|
|
1256
|
+
//!
|
|
1257
|
+
//! <b>Postcondition</b>: capacity() >= n.
|
|
1258
|
+
//!
|
|
1259
|
+
//! <b>Throws</b>: if n > max_size(), plus any exception
|
|
1260
|
+
//! thrown by the allocator.
|
|
1261
|
+
//!
|
|
1262
|
+
//! <b>Complexity</b>: Linear in the number of reserved blocks allocated.
|
|
1263
|
+
//!
|
|
1264
|
+
//! <b>Note</b>: All references, pointers and iterators (including the
|
|
1265
|
+
//! past-the-end iterator) remain valid.
|
|
1266
|
+
void reserve(size_type n)
|
|
1267
|
+
{
|
|
1268
|
+
if(n > max_size()) {
|
|
1269
|
+
throw_length_error("Requested capacity greater than max_size()");
|
|
1270
|
+
}
|
|
1271
|
+
while(capacity() < n) (void)create_new_available_block();
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
//! <b>Effects</b>: Reallocates elements if needed so that the number of active
|
|
1275
|
+
//! blocks is minimized and deallocates the ensuing reserved blocks. If
|
|
1276
|
+
//! capacity() already equals size() there are no effects. If T throws during
|
|
1277
|
+
//! reallocation, the effects are unspecified.
|
|
1278
|
+
//!
|
|
1279
|
+
//! <b>Requires</b>: T is MoveInsertable into the hub.
|
|
1280
|
+
//!
|
|
1281
|
+
//! <b>Complexity</b>: Linear in size() if reallocation happens, plus linear in
|
|
1282
|
+
//! the number of reserved blocks.
|
|
1283
|
+
//!
|
|
1284
|
+
//! <b>Note</b>: If reallocation happens, the order of the elements may change
|
|
1285
|
+
//! and all references, pointers and iterators to elements are invalidated.
|
|
1286
|
+
void shrink_to_fit()
|
|
1287
|
+
{
|
|
1288
|
+
compact();
|
|
1289
|
+
trim_capacity();
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
//! <b>Effects</b>: Deallocates all reserved blocks, reducing capacity()
|
|
1293
|
+
//! accordingly.
|
|
1294
|
+
//!
|
|
1295
|
+
//! <b>Complexity</b>: Linear in the number of reserved blocks deallocated.
|
|
1296
|
+
//!
|
|
1297
|
+
//! <b>Note</b>: All references, pointers and iterators (including the
|
|
1298
|
+
//! past-the-end iterator) remain valid.
|
|
1299
|
+
void trim_capacity() noexcept { trim_capacity(0); }
|
|
1300
|
+
|
|
1301
|
+
//! <b>Effects</b>: If n >= capacity() there are no effects; otherwise reduces
|
|
1302
|
+
//! capacity() to no less than n by deallocating reserved blocks.
|
|
1303
|
+
//!
|
|
1304
|
+
//! <b>Complexity</b>: Linear in the number of reserved blocks deallocated.
|
|
1305
|
+
//!
|
|
1306
|
+
//! <b>Note</b>: All references, pointers and iterators (including the
|
|
1307
|
+
//! past-the-end iterator) remain valid.
|
|
1308
|
+
void trim_capacity(size_type n) noexcept
|
|
1309
|
+
{
|
|
1310
|
+
if(capacity() <= n) return;
|
|
1311
|
+
for(auto pbb = blist.header()->prev_available;
|
|
1312
|
+
capacity() - n >= N && pbb != blist.header() && pbb->mask == 0; ) {
|
|
1313
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1314
|
+
pbb = pbb-> prev_available;
|
|
1315
|
+
blist.unlink_available(pb);
|
|
1316
|
+
delete_block(pb);
|
|
1317
|
+
--num_blocks;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
//! <b>Effects</b>: Inserts an object of type T constructed with
|
|
1322
|
+
//! std::forward<Args>(args)... at a position chosen by the container. If an
|
|
1323
|
+
//! exception is thrown there are no effects. args may directly or indirectly
|
|
1324
|
+
//! refer to a value in *this.
|
|
1325
|
+
//!
|
|
1326
|
+
//! <b>Requires</b>: T is EmplaceConstructible into the hub from args.
|
|
1327
|
+
//!
|
|
1328
|
+
//! <b>Returns</b>: An iterator pointing to the new element.
|
|
1329
|
+
//!
|
|
1330
|
+
//! <b>Complexity</b>: Constant. Exactly one object of type T is constructed.
|
|
1331
|
+
template<typename... Args>
|
|
1332
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace(Args&&... args)
|
|
1333
|
+
{
|
|
1334
|
+
auto pbb = blist.next_available; //for construct_or_restore_capacity
|
|
1335
|
+
int n;
|
|
1336
|
+
auto pb = retrieve_available_block(n);
|
|
1337
|
+
auto mask = pb->mask;
|
|
1338
|
+
construct_or_restore_capacity(
|
|
1339
|
+
boost::movelib::to_raw_pointer(pb->data() + n), pbb, std::forward<Args>(args)...);
|
|
1340
|
+
mask |= mask + 1;
|
|
1341
|
+
pb->mask = mask;
|
|
1342
|
+
auto mask_plus_one = mask + 1;
|
|
1343
|
+
if(BOOST_UNLIKELY(mask_plus_one <= 2)) {
|
|
1344
|
+
//pb->mask == 0 (impossible), 1 or full
|
|
1345
|
+
if(mask_plus_one == 0) blist.unlink_available(pb);
|
|
1346
|
+
else /* pb->mask == 1 */ blist.link_at_back(pb);
|
|
1347
|
+
}
|
|
1348
|
+
++size_;
|
|
1349
|
+
return {pb, n};
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
//! <b>Effects</b>: Equivalent to emplace(std::forward<Args>(args)...); the
|
|
1353
|
+
//! hint is ignored.
|
|
1354
|
+
//!
|
|
1355
|
+
//! <b>Returns</b>: An iterator pointing to the new element.
|
|
1356
|
+
//!
|
|
1357
|
+
//! <b>Complexity</b>: Constant.
|
|
1358
|
+
template<typename... Args>
|
|
1359
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
|
|
1360
|
+
{
|
|
1361
|
+
return emplace(std::forward<Args>(args)...);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
//! <b>Effects</b>: Inserts a copy of x (or moves x) at a position chosen by
|
|
1365
|
+
//! the container; overloads taking a hint ignore it. Equivalent to
|
|
1366
|
+
//! emplace(std::forward<decltype(x)>(x)).
|
|
1367
|
+
//!
|
|
1368
|
+
//! <b>Returns</b>: An iterator pointing to the new element.
|
|
1369
|
+
//!
|
|
1370
|
+
//! <b>Complexity</b>: Constant.
|
|
1371
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const T& x) { return emplace(x); }
|
|
1372
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator, const T& x)
|
|
1373
|
+
{ return emplace(x); }
|
|
1374
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(T&& x) { return emplace(std::move(x)); }
|
|
1375
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator, T&& x)
|
|
1376
|
+
{ return emplace(std::move(x)); }
|
|
1377
|
+
|
|
1378
|
+
//! <b>Effects</b>: Inserts copies of the elements in il. Equivalent to
|
|
1379
|
+
//! insert(il.begin(), il.end()).
|
|
1380
|
+
//!
|
|
1381
|
+
//! <b>Complexity</b>: Linear in il.size().
|
|
1382
|
+
void insert(std::initializer_list<T> il) { insert(il.begin(), il.end()); }
|
|
1383
|
+
|
|
1384
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
1385
|
+
//! <b>Effects</b>: Inserts copies of the elements in rg. Each iterator in rg
|
|
1386
|
+
//! is dereferenced exactly once.
|
|
1387
|
+
//!
|
|
1388
|
+
//! <b>Requires</b>: T is EmplaceConstructible into the hub from
|
|
1389
|
+
//! *ranges::begin(rg) and rg does not overlap with *this.
|
|
1390
|
+
//!
|
|
1391
|
+
//! <b>Complexity</b>: Linear in the number of elements inserted; one object of
|
|
1392
|
+
//! type T is constructed per element.
|
|
1393
|
+
template< BOOST_CONTAINER_DOC1ST(std::ranges::input_range<T>, hub_detail::container_compatible_range<T>) R >
|
|
1394
|
+
void insert_range(R&& rg)
|
|
1395
|
+
{
|
|
1396
|
+
range_insert_impl(
|
|
1397
|
+
dtl::adl_range::adl_begin(rg), dtl::adl_range::adl_end(rg),
|
|
1398
|
+
[this] (T* p, auto it) { block_alloc_traits::construct(al(), p, *it); });
|
|
1399
|
+
}
|
|
1400
|
+
#endif
|
|
1401
|
+
|
|
1402
|
+
//! <b>Effects</b>: Inserts copies of the elements in [first, last). Each
|
|
1403
|
+
//! iterator in the range is dereferenced exactly once.
|
|
1404
|
+
//!
|
|
1405
|
+
//! <b>Requires</b>: T is EmplaceConstructible into the hub from *first and
|
|
1406
|
+
//! [first, last) does not overlap with *this.
|
|
1407
|
+
//!
|
|
1408
|
+
//! <b>Complexity</b>: Linear in the number of elements inserted; one object of
|
|
1409
|
+
//! type T is constructed per element.
|
|
1410
|
+
template<
|
|
1411
|
+
typename InputIterator
|
|
1412
|
+
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename = hub_detail::enable_if_is_input_iterator_t<InputIterator>)
|
|
1413
|
+
>
|
|
1414
|
+
void insert(InputIterator first, InputIterator last)
|
|
1415
|
+
{
|
|
1416
|
+
range_insert_impl(first, last, [this] (T* p, InputIterator it) {
|
|
1417
|
+
block_alloc_traits::construct(al(), p, *it);
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
//! <b>Effects</b>: Inserts n copies of x.
|
|
1422
|
+
//!
|
|
1423
|
+
//! <b>Requires</b>: T is CopyInsertable into the hub.
|
|
1424
|
+
//!
|
|
1425
|
+
//! <b>Complexity</b>: Linear in n; one object of type T is constructed per
|
|
1426
|
+
//! element.
|
|
1427
|
+
void insert(size_type n, const T& x)
|
|
1428
|
+
{
|
|
1429
|
+
range_insert_impl(size_type(0), n, [&, this] (T* p, size_type) {
|
|
1430
|
+
block_alloc_traits::construct(al(), p, x);
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
//! <b>Effects</b>: Erases the element pointed to by pos.
|
|
1435
|
+
//!
|
|
1436
|
+
//! <b>Returns</b>: An iterator pointing to the element that followed the
|
|
1437
|
+
//! erased one.
|
|
1438
|
+
//!
|
|
1439
|
+
//! <b>Complexity</b>: Constant.
|
|
1440
|
+
//!
|
|
1441
|
+
//! <b>Note</b>: Invalidates references, pointers and iterators referring to
|
|
1442
|
+
//! the erased element.
|
|
1443
|
+
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator pos)
|
|
1444
|
+
{
|
|
1445
|
+
auto pbb = pos.pbb;
|
|
1446
|
+
auto n = pos.n;
|
|
1447
|
+
++pos;
|
|
1448
|
+
erase_impl(pbb, n);
|
|
1449
|
+
return {pos.pbb, pos.n};
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
//! <b>Effects</b>: Erases the element pointed to by pos. Equivalent to
|
|
1453
|
+
//! erase(pos) but returns nothing.
|
|
1454
|
+
//!
|
|
1455
|
+
//! <b>Complexity</b>: Constant.
|
|
1456
|
+
//!
|
|
1457
|
+
//! <b>Note</b>: Potentially faster than erase(pos) as no return iterator needs
|
|
1458
|
+
//! to be computed. Invalidates references, pointers and iterators referring
|
|
1459
|
+
//! to the erased element.
|
|
1460
|
+
BOOST_CONTAINER_FORCEINLINE void erase_void(const_iterator pos)
|
|
1461
|
+
{
|
|
1462
|
+
erase_impl(pos.pbb, pos.n);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
//! <b>Effects</b>: Erases the elements in the range [first, last).
|
|
1466
|
+
//!
|
|
1467
|
+
//! <b>Returns</b>: An iterator pointing to the element that followed the last
|
|
1468
|
+
//! erased element.
|
|
1469
|
+
//!
|
|
1470
|
+
//! <b>Complexity</b>: Linear in the number of elements erased.
|
|
1471
|
+
//!
|
|
1472
|
+
//! <b>Note</b>: Invalidates references, pointers and iterators referring to
|
|
1473
|
+
//! the erased elements.
|
|
1474
|
+
iterator erase(const_iterator first, const_iterator last)
|
|
1475
|
+
{
|
|
1476
|
+
for(auto pbb = first.pbb; first != last; ) {
|
|
1477
|
+
first = erase(first);
|
|
1478
|
+
if(first.pbb != pbb) break;
|
|
1479
|
+
}
|
|
1480
|
+
auto pbb = first.pbb;
|
|
1481
|
+
if(pbb != last.pbb) {
|
|
1482
|
+
do {
|
|
1483
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1484
|
+
pbb = pb->next;
|
|
1485
|
+
BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb, block);
|
|
1486
|
+
size_ -= destroy_all_in_nonempty_block(pb);
|
|
1487
|
+
blist.unlink(pb);
|
|
1488
|
+
if(BOOST_LIKELY(pb->mask != full)) blist.unlink_available(pb);
|
|
1489
|
+
blist.link_available_at_back(pb);
|
|
1490
|
+
pb->mask = 0;
|
|
1491
|
+
} while(pbb != last.pbb);
|
|
1492
|
+
first = {pbb};
|
|
1493
|
+
}
|
|
1494
|
+
while(first != last) first = erase(first);
|
|
1495
|
+
return {last.pbb, last.n};
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
//! <b>Effects</b>: Exchanges the contents and capacity() of *this with those
|
|
1499
|
+
//! of x.
|
|
1500
|
+
//!
|
|
1501
|
+
//! <b>Complexity</b>: Constant.
|
|
1502
|
+
void swap(hub& x)
|
|
1503
|
+
noexcept(
|
|
1504
|
+
hub_detail::pocs_t<allocator_type>::value ||
|
|
1505
|
+
hub_detail::is_always_equal_t<allocator_type>::value)
|
|
1506
|
+
{
|
|
1507
|
+
using pocs = hub_detail::pocs_t<allocator_type>;
|
|
1508
|
+
|
|
1509
|
+
hub_detail::if_constexpr(pocs{}, [&, this]{
|
|
1510
|
+
hub_detail::swap_if(pocs{}, al(), x.al());
|
|
1511
|
+
},
|
|
1512
|
+
[&, this]{ //else
|
|
1513
|
+
BOOST_ASSERT(al() == x.al());
|
|
1514
|
+
(void)this;
|
|
1515
|
+
});
|
|
1516
|
+
std::swap(blist, x.blist);
|
|
1517
|
+
std::swap(num_blocks, x.num_blocks);
|
|
1518
|
+
std::swap(size_, x.size_);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
//! <b>Effects</b>: Erases all elements. Reserved blocks are kept.
|
|
1522
|
+
//!
|
|
1523
|
+
//! <b>Complexity</b>: Linear in size().
|
|
1524
|
+
void clear() noexcept { erase(begin(), end()); }
|
|
1525
|
+
|
|
1526
|
+
//! <b>Effects</b>: Inserts the contents of x into *this, leaving x empty.
|
|
1527
|
+
//! Pointers and references to the moved elements of x now refer to *this;
|
|
1528
|
+
//! iterators continue to refer to their elements but behave as iterators
|
|
1529
|
+
//! into *this. Reserved blocks of x are not transferred.
|
|
1530
|
+
//!
|
|
1531
|
+
//! <b>Requires</b>: get_allocator() == x.get_allocator() and
|
|
1532
|
+
//! std::addressof(x) != this.
|
|
1533
|
+
//!
|
|
1534
|
+
//! <b>Complexity</b>: Linear in the number of blocks of x plus the number of
|
|
1535
|
+
//! blocks of *this.
|
|
1536
|
+
void splice(hub& x)
|
|
1537
|
+
{
|
|
1538
|
+
BOOST_ASSERT(this != &x);
|
|
1539
|
+
BOOST_ASSERT(al() == x.al());
|
|
1540
|
+
for(auto pbb = x.blist.header()->next; pbb != x.blist.header(); ) {
|
|
1541
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1542
|
+
pbb = pbb->next;
|
|
1543
|
+
if(pb->mask != full) {
|
|
1544
|
+
x.blist.unlink_available(pb);
|
|
1545
|
+
blist.link_available_at_front(pb);
|
|
1546
|
+
}
|
|
1547
|
+
x.blist.unlink(pb);
|
|
1548
|
+
blist.link_at_back(pb);
|
|
1549
|
+
--x.num_blocks;
|
|
1550
|
+
++num_blocks;
|
|
1551
|
+
auto s = dtl::popcount(pb->mask);
|
|
1552
|
+
x.size_ -= (size_type)s;
|
|
1553
|
+
size_ += (size_type)s;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
//! <b>Effects</b>: Equivalent to splice(x).
|
|
1558
|
+
void splice(hub&& x) { splice(x); }
|
|
1559
|
+
|
|
1560
|
+
//! <b>Effects</b>: Erases all but the first element from every consecutive
|
|
1561
|
+
//! group of equivalent elements, i.e. erases each element i in
|
|
1562
|
+
//! [begin() + 1, end()) for which pred(*i, *(i - 1)) is true.
|
|
1563
|
+
//!
|
|
1564
|
+
//! <b>Requires</b>: pred is an equivalence relation.
|
|
1565
|
+
//!
|
|
1566
|
+
//! <b>Returns</b>: The number of elements erased.
|
|
1567
|
+
//!
|
|
1568
|
+
//! <b>Throws</b>: Nothing unless pred throws.
|
|
1569
|
+
//!
|
|
1570
|
+
//! <b>Complexity</b>: Exactly size() - 1 applications of pred for a non-empty
|
|
1571
|
+
//! hub, otherwise none.
|
|
1572
|
+
//!
|
|
1573
|
+
//! <b>Note</b>: Invalidates references, pointers and iterators referring to
|
|
1574
|
+
//! the erased elements.
|
|
1575
|
+
template<typename BinaryPredicate = std::equal_to<T>>
|
|
1576
|
+
size_type unique(BinaryPredicate pred = BinaryPredicate())
|
|
1577
|
+
{
|
|
1578
|
+
auto s = size_;
|
|
1579
|
+
for(auto first = cbegin(), last = cend(); first != last; ) {
|
|
1580
|
+
auto next = std::next(first);
|
|
1581
|
+
first = erase(
|
|
1582
|
+
next,
|
|
1583
|
+
std::find_if_not(next, last, [&] (const T& x) {
|
|
1584
|
+
return pred(x, *first);
|
|
1585
|
+
}));
|
|
1586
|
+
}
|
|
1587
|
+
return (size_type)(s - size_);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
#if defined(BOOST_MSVC)
|
|
1591
|
+
#pragma warning(push)
|
|
1592
|
+
#pragma warning(disable:4127) //conditional expression is constant
|
|
1593
|
+
#endif
|
|
1594
|
+
|
|
1595
|
+
//! <b>Effects</b>: Sorts *this according to comp. If comp or any operation on
|
|
1596
|
+
//! T throws, *this is left in a valid but unspecified state; if an exception
|
|
1597
|
+
//! is thrown while allocating internal memory there are no effects.
|
|
1598
|
+
//!
|
|
1599
|
+
//! <b>Requires</b>: T is MoveInsertable into the hub, MoveConstructible,
|
|
1600
|
+
//! MoveAssignable and Swappable.
|
|
1601
|
+
//!
|
|
1602
|
+
//! <b>Complexity</b>: O(N*log(N)) comparisons, where N is size().
|
|
1603
|
+
//!
|
|
1604
|
+
//! <b>Note</b>: May allocate. References, pointers and iterators to elements
|
|
1605
|
+
//! may be invalidated. The sort is not stable.
|
|
1606
|
+
template<typename Compare = std::less<T>>
|
|
1607
|
+
void sort(Compare comp = Compare())
|
|
1608
|
+
{
|
|
1609
|
+
//transfer_sort is usually the fastest, but it consumes the most
|
|
1610
|
+
//auxiliary memory when sizeof(T) > sizeof(sort_proxy), so we restrict
|
|
1611
|
+
//its usage to the case sizeof(T) <= sizeof(sort_proxy).
|
|
1612
|
+
//compact_sort uses the least amount of auxiliary memory (by far), and
|
|
1613
|
+
//it's also faster than proxy_sort when the auxiliary memory of the latter
|
|
1614
|
+
//exceeds some threshold seemingly related to the size of the L2 cache;
|
|
1615
|
+
//we conventionally set the threshold to 2MB for lack of a more precise
|
|
1616
|
+
//estimation mechanism.
|
|
1617
|
+
//TODO: In 32-bit mode, the threshold policy is not so clear-cut and the
|
|
1618
|
+
//cost of moving elements around seems to play a role.
|
|
1619
|
+
BOOST_IF_CONSTEXPR(sizeof(T) <= sizeof(sort_proxy)) {
|
|
1620
|
+
if(transfer_sort(comp)) return;
|
|
1621
|
+
}
|
|
1622
|
+
else{
|
|
1623
|
+
static constexpr std::size_t memory_threshold = 2 * 1024 * 1024;
|
|
1624
|
+
if((std::size_t)size_ * sizeof(sort_proxy) <= memory_threshold) {
|
|
1625
|
+
if(proxy_sort(comp)) return;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
compact_sort(comp);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
#if defined(BOOST_MSVC)
|
|
1632
|
+
#pragma warning(pop) //C4127
|
|
1633
|
+
#endif
|
|
1634
|
+
|
|
1635
|
+
//! <b>Effects</b>: Returns an iterator referring to the
|
|
1636
|
+
//! same element as p.
|
|
1637
|
+
//!
|
|
1638
|
+
//! <b>Requires</b>: p points to an element in *this.
|
|
1639
|
+
//!
|
|
1640
|
+
//! <b>Throws</b>: Nothing.
|
|
1641
|
+
//!
|
|
1642
|
+
//! <b>Complexity</b>: Linear in the number of active blocks in *this.
|
|
1643
|
+
iterator get_iterator(const_pointer p)
|
|
1644
|
+
{
|
|
1645
|
+
std::less<const T*> less;
|
|
1646
|
+
for(auto pbb = blist.next; pbb != blist.header(); pbb = pbb-> next) {
|
|
1647
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1648
|
+
if(!less(boost::movelib::to_raw_pointer(p), boost::movelib::to_raw_pointer(pb->data())) &&
|
|
1649
|
+
less(boost::movelib::to_raw_pointer(p), boost::movelib::to_raw_pointer(pb->data() + N))) {
|
|
1650
|
+
int n = (int)(p - pb->data());
|
|
1651
|
+
BOOST_ASSERT_MSG(
|
|
1652
|
+
(pb->mask & ((mask_type)(1) << n)) != 0,
|
|
1653
|
+
"p points to an invalid element");
|
|
1654
|
+
return {pb, n};
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
BOOST_ASSERT_MSG(false, "p does not point into the extents of *this");
|
|
1658
|
+
#if defined(BOOST_ASSERT_HANDLER_IS_NORETURN)
|
|
1659
|
+
BOOST_UNREACHABLE_RETURN(end());
|
|
1660
|
+
#else
|
|
1661
|
+
return end();
|
|
1662
|
+
#endif
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
//! <b>Effects</b>: Returns a const_iterator referring to the
|
|
1666
|
+
//! same element as p.
|
|
1667
|
+
//!
|
|
1668
|
+
//! <b>Requires</b>: p points to an element in *this.
|
|
1669
|
+
//!
|
|
1670
|
+
//! <b>Throws</b>: Nothing.
|
|
1671
|
+
//!
|
|
1672
|
+
//! <b>Complexity</b>: Linear in the number of active blocks in *this.
|
|
1673
|
+
const_iterator get_iterator(const_pointer p) const
|
|
1674
|
+
{
|
|
1675
|
+
return const_cast<hub*>(this)->get_iterator(p);
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1679
|
+
private:
|
|
1680
|
+
template<typename U, typename A, typename F>
|
|
1681
|
+
friend std::pair<typename hub<U, A>::iterator, F> for_each_while(
|
|
1682
|
+
hub<U, A>&, F);
|
|
1683
|
+
template<typename U, typename A, typename P>
|
|
1684
|
+
friend typename hub<U, A>::size_type erase_if(hub<U, A>&, P);
|
|
1685
|
+
|
|
1686
|
+
using block_typedefs = hub_detail::block_typedefs<allocator_type>;
|
|
1687
|
+
using block_base = typename block_typedefs::block_base;
|
|
1688
|
+
using block_base_pointer = typename block_typedefs::block_base_pointer;
|
|
1689
|
+
using const_block_base_pointer =
|
|
1690
|
+
typename block_typedefs::const_block_base_pointer;
|
|
1691
|
+
using block = typename block_typedefs::block;
|
|
1692
|
+
using block_pointer = typename block_typedefs::block_pointer;
|
|
1693
|
+
using block_allocator = typename block_typedefs::block_allocator;
|
|
1694
|
+
using block_list = typename block_typedefs::block_list;
|
|
1695
|
+
//EBO: hub derives directly from block_allocator (like dtl::vector_alloc_holder).
|
|
1696
|
+
using allocator_base = block_allocator;
|
|
1697
|
+
using block_alloc_traits = allocator_traits<block_allocator>;
|
|
1698
|
+
using value_allocator = hub_detail::rebind_alloc_t<allocator_type, value_type>;
|
|
1699
|
+
using value_alloc_traits = allocator_traits<value_allocator>;
|
|
1700
|
+
using mask_type = typename block_base::mask_type;
|
|
1701
|
+
|
|
1702
|
+
static constexpr int N = block_base::N;
|
|
1703
|
+
static constexpr mask_type full = block_base::full;
|
|
1704
|
+
|
|
1705
|
+
block_allocator& al() noexcept
|
|
1706
|
+
{ return static_cast<block_allocator&>(*this); }
|
|
1707
|
+
const block_allocator& al() const noexcept
|
|
1708
|
+
{ return static_cast<const block_allocator&>(*this); }
|
|
1709
|
+
|
|
1710
|
+
struct reset_on_exit
|
|
1711
|
+
{
|
|
1712
|
+
~reset_on_exit() { x.reset(); }
|
|
1713
|
+
|
|
1714
|
+
hub& x;
|
|
1715
|
+
};
|
|
1716
|
+
|
|
1717
|
+
hub(
|
|
1718
|
+
hub&& x, const allocator_type& al_, std::true_type /* equal allocs */) noexcept:
|
|
1719
|
+
allocator_base(al_), blist{std::move(x.blist)},
|
|
1720
|
+
num_blocks{x.num_blocks}, size_{x.size_}
|
|
1721
|
+
{
|
|
1722
|
+
x.num_blocks = 0;
|
|
1723
|
+
x.size_ = 0;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
hub(
|
|
1727
|
+
hub&& x, const allocator_type& al_, std::false_type /* maybe unequal allocs */):
|
|
1728
|
+
hub{al_}
|
|
1729
|
+
{
|
|
1730
|
+
if(al() == x.al()) {
|
|
1731
|
+
blist = std::move(x.blist);
|
|
1732
|
+
num_blocks = x.num_blocks;
|
|
1733
|
+
size_ = x.size_;
|
|
1734
|
+
x.num_blocks = 0;
|
|
1735
|
+
x.size_ = 0;
|
|
1736
|
+
}
|
|
1737
|
+
else {
|
|
1738
|
+
reset_on_exit on_exit{x}; (void)on_exit;
|
|
1739
|
+
range_insert_impl(x.begin(), x.end(), [this] (T* p, iterator it) {
|
|
1740
|
+
block_alloc_traits::construct(al(), p, std::move(*it));
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
void move_assign(hub& x, std::true_type /* transfer structure */)
|
|
1746
|
+
{
|
|
1747
|
+
using pocma =
|
|
1748
|
+
hub_detail::pocma_t<allocator_type>;
|
|
1749
|
+
|
|
1750
|
+
reset();
|
|
1751
|
+
hub_detail::move_assign_if(pocma{}, al(), x.al());
|
|
1752
|
+
blist = std::move(x.blist);
|
|
1753
|
+
num_blocks = x.num_blocks;
|
|
1754
|
+
size_ = x.size_;
|
|
1755
|
+
x.num_blocks = 0;
|
|
1756
|
+
x.size_ = 0;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
void move_assign(hub& x, std::false_type /* maybe move data */)
|
|
1760
|
+
{
|
|
1761
|
+
if(al() == x.al()) {
|
|
1762
|
+
move_assign(x, std::true_type{});
|
|
1763
|
+
}
|
|
1764
|
+
else {
|
|
1765
|
+
reset_on_exit on_exit{x}; (void)on_exit;
|
|
1766
|
+
range_assign_impl(
|
|
1767
|
+
x.begin(), x.end(),
|
|
1768
|
+
[this] (T* p, iterator it)
|
|
1769
|
+
{ block_alloc_traits::construct(al(), p, std::move(*it)); },
|
|
1770
|
+
[] (T* p, iterator it)
|
|
1771
|
+
{ *p = std::move(*it); });
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
static block_pointer
|
|
1776
|
+
static_cast_block_pointer(block_base_pointer pbb) noexcept
|
|
1777
|
+
{
|
|
1778
|
+
return block::static_cast_block_pointer(pbb);
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
block_pointer create_new_available_block()
|
|
1782
|
+
{
|
|
1783
|
+
auto pb = block_alloc_traits::allocate(al(), 1);
|
|
1784
|
+
pb->mask = 0;
|
|
1785
|
+
BOOST_CONTAINER_TRY {
|
|
1786
|
+
value_allocator val(al());
|
|
1787
|
+
pb->data_ = value_alloc_traits::allocate(val, N);
|
|
1788
|
+
}
|
|
1789
|
+
BOOST_CONTAINER_CATCH(...) {
|
|
1790
|
+
block_alloc_traits::deallocate(al(), pb, 1);
|
|
1791
|
+
BOOST_CONTAINER_RETHROW;
|
|
1792
|
+
}
|
|
1793
|
+
BOOST_CONTAINER_CATCH_END
|
|
1794
|
+
blist.link_available_at_back(pb);
|
|
1795
|
+
++num_blocks;
|
|
1796
|
+
return pb;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
void delete_block(block_pointer pb) noexcept
|
|
1800
|
+
{
|
|
1801
|
+
value_allocator val(al());
|
|
1802
|
+
value_alloc_traits::deallocate(val, pb->data(), N);
|
|
1803
|
+
block_alloc_traits::deallocate(al(), pb, 1);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
BOOST_CONTAINER_FORCEINLINE block_pointer retrieve_available_block(int& n)
|
|
1807
|
+
{
|
|
1808
|
+
if(BOOST_LIKELY(blist.next_available != blist.header())) {
|
|
1809
|
+
auto pb = static_cast_block_pointer(blist.next_available);
|
|
1810
|
+
n = dtl::unchecked_countr_one(pb->mask);
|
|
1811
|
+
return pb;
|
|
1812
|
+
}
|
|
1813
|
+
else {
|
|
1814
|
+
n = 0;
|
|
1815
|
+
return create_new_available_block();
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
BOOST_CONTAINER_FORCEINLINE size_type destroy_all_in_nonempty_block(
|
|
1820
|
+
block_pointer pb) noexcept
|
|
1821
|
+
{
|
|
1822
|
+
BOOST_ASSERT(pb->mask != 0);
|
|
1823
|
+
return destroy_all_in_nonempty_block(pb, std::integral_constant<bool,
|
|
1824
|
+
std::is_trivially_destructible<T>::value &&
|
|
1825
|
+
( hub_detail::is_std_allocator<block_allocator>::value ||
|
|
1826
|
+
hub_detail::is_std_pmr_polymorphic_allocator<block_allocator>::value ||
|
|
1827
|
+
!hub_detail::allocator_has_destroy<block_allocator, T*>::value )>{});
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
BOOST_CONTAINER_FORCEINLINE size_type destroy_all_in_nonempty_block(
|
|
1831
|
+
block_pointer pb, std::true_type /* trivial destruction */) noexcept
|
|
1832
|
+
{
|
|
1833
|
+
return (size_type)dtl::popcount(pb->mask);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
BOOST_CONTAINER_FORCEINLINE size_type destroy_all_in_nonempty_block(
|
|
1837
|
+
block_pointer pb, std::false_type /* use allocator destroy */) noexcept
|
|
1838
|
+
{
|
|
1839
|
+
size_type s = (size_type)dtl::popcount(pb->mask);
|
|
1840
|
+
auto mask = pb->mask;
|
|
1841
|
+
auto pd = boost::movelib::to_raw_pointer(pb->data());
|
|
1842
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
1843
|
+
do {
|
|
1844
|
+
auto n = dtl::unchecked_countr_zero(mask);
|
|
1845
|
+
block_alloc_traits::destroy(al(), pd + n);
|
|
1846
|
+
mask &= mask - 1;
|
|
1847
|
+
} while(mask);
|
|
1848
|
+
return s;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
BOOST_CONTAINER_FORCEINLINE size_type destroy_all_in_full_block(
|
|
1852
|
+
block_pointer pb) noexcept
|
|
1853
|
+
{
|
|
1854
|
+
BOOST_ASSERT(pb->mask == full);
|
|
1855
|
+
auto pd = boost::movelib::to_raw_pointer(pb->data());
|
|
1856
|
+
int n = 0;
|
|
1857
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
1858
|
+
for(; n < N; ++n) {
|
|
1859
|
+
block_alloc_traits::destroy(al(), pd + n);
|
|
1860
|
+
}
|
|
1861
|
+
return (size_type)N;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
void reset() noexcept
|
|
1865
|
+
{
|
|
1866
|
+
//empty blocks
|
|
1867
|
+
auto pbb = blist.prev_available;
|
|
1868
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
1869
|
+
while(pbb != blist.header() && pbb->mask == 0) {
|
|
1870
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1871
|
+
pbb = pb->prev_available;
|
|
1872
|
+
BOOST_CONTAINER_HUB_PREFETCH(pbb);
|
|
1873
|
+
delete_block(pb);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
//non-empty blocks
|
|
1877
|
+
pbb = blist.next;
|
|
1878
|
+
while(pbb != blist.header()) {
|
|
1879
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1880
|
+
pbb = pb->next;
|
|
1881
|
+
BOOST_IF_CONSTEXPR(!std::is_trivially_destructible<T>::value) {
|
|
1882
|
+
BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb, block);
|
|
1883
|
+
}
|
|
1884
|
+
if(pb->mask == full) destroy_all_in_full_block(pb);
|
|
1885
|
+
else destroy_all_in_nonempty_block(pb);
|
|
1886
|
+
delete_block(pb);
|
|
1887
|
+
}
|
|
1888
|
+
blist.reset();
|
|
1889
|
+
num_blocks = 0;
|
|
1890
|
+
size_ = 0;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
template<typename... Args>
|
|
1894
|
+
inline void construct_or_restore_capacity(
|
|
1895
|
+
value_type* p, block_base_pointer pbb, Args&&... args)
|
|
1896
|
+
{
|
|
1897
|
+
BOOST_CONTAINER_TRY {
|
|
1898
|
+
block_alloc_traits::construct(al(), p, std::forward<Args>(args)...);
|
|
1899
|
+
}
|
|
1900
|
+
BOOST_CONTAINER_CATCH(...) {
|
|
1901
|
+
restore_capacity_on_throw(pbb);
|
|
1902
|
+
BOOST_CONTAINER_RETHROW
|
|
1903
|
+
}
|
|
1904
|
+
BOOST_CONTAINER_CATCH_END
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
BOOST_NOINLINE void restore_capacity_on_throw(
|
|
1908
|
+
block_base_pointer pbb) noexcept
|
|
1909
|
+
{
|
|
1910
|
+
auto pb = static_cast_block_pointer(blist.next_available);
|
|
1911
|
+
if(pb != pbb) { //block freshly allocated -> restore capacity
|
|
1912
|
+
blist.unlink_available(pb);
|
|
1913
|
+
delete_block(pb);
|
|
1914
|
+
--num_blocks;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
BOOST_CONTAINER_FORCEINLINE void erase_impl(block_base_pointer pbb, int n) noexcept
|
|
1919
|
+
{
|
|
1920
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1921
|
+
block_alloc_traits::destroy(al(), boost::movelib::to_raw_pointer(pb->data() + n));
|
|
1922
|
+
if(BOOST_UNLIKELY(pb->mask == full)) blist.link_available_at_front(pb);
|
|
1923
|
+
pb->mask &= ~((mask_type)(1) << n);
|
|
1924
|
+
if(BOOST_UNLIKELY(pb->mask == 0)) {
|
|
1925
|
+
blist.unlink(pb);
|
|
1926
|
+
blist.unlink_available(pb);
|
|
1927
|
+
blist.link_available_at_back(pb);
|
|
1928
|
+
}
|
|
1929
|
+
--size_;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
template<typename Incrementable, typename Sentinel, typename Construct>
|
|
1933
|
+
void range_insert_impl(
|
|
1934
|
+
Incrementable first, Sentinel last, Construct construct_)
|
|
1935
|
+
{
|
|
1936
|
+
while(first != last) {
|
|
1937
|
+
int n;
|
|
1938
|
+
auto pb = retrieve_available_block(n);
|
|
1939
|
+
for(; ; ) {
|
|
1940
|
+
construct_(boost::movelib::to_raw_pointer(pb->data() + n), first++);
|
|
1941
|
+
++size_;
|
|
1942
|
+
if(BOOST_UNLIKELY(pb->mask == 0)) blist.link_at_back(pb);
|
|
1943
|
+
pb->mask |= pb->mask +1;
|
|
1944
|
+
if(pb->mask == full) {
|
|
1945
|
+
blist.unlink_available(pb);
|
|
1946
|
+
break;
|
|
1947
|
+
}
|
|
1948
|
+
else if(first == last) return;
|
|
1949
|
+
n = dtl::unchecked_countr_one(pb->mask);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
template<
|
|
1955
|
+
typename Incrementable, typename Sentinel,
|
|
1956
|
+
typename Construct, typename Insert
|
|
1957
|
+
>
|
|
1958
|
+
void range_assign_impl(
|
|
1959
|
+
Incrementable first, Sentinel last, Construct construct_, Insert insert_)
|
|
1960
|
+
{
|
|
1961
|
+
auto pbb = blist.next;
|
|
1962
|
+
int n = -1;
|
|
1963
|
+
if(first != last) {
|
|
1964
|
+
//consume active blocks
|
|
1965
|
+
for(; pbb != blist.header(); pbb = pbb->next) {
|
|
1966
|
+
auto pb = static_cast_block_pointer(pbb);
|
|
1967
|
+
n = 0;
|
|
1968
|
+
for(mask_type bit = 1; bit; bit <<= 1, ++n) {
|
|
1969
|
+
if(pb->mask & bit) { //full slot
|
|
1970
|
+
insert_(boost::movelib::to_raw_pointer(pb->data() + n), first++);
|
|
1971
|
+
}
|
|
1972
|
+
else { //empty slot
|
|
1973
|
+
construct_(boost::movelib::to_raw_pointer(pb->data() + n), first++);
|
|
1974
|
+
++size_;
|
|
1975
|
+
pb->mask |= bit;
|
|
1976
|
+
if(pb->mask == full) blist.unlink_available(pb);
|
|
1977
|
+
}
|
|
1978
|
+
if(first == last) goto exit;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
exit: ;
|
|
1982
|
+
}
|
|
1983
|
+
if(first != last) {
|
|
1984
|
+
//all active blocks consumed, keep inserting
|
|
1985
|
+
range_insert_impl(first, last, construct_);
|
|
1986
|
+
}
|
|
1987
|
+
else{
|
|
1988
|
+
//erase remaining original elements
|
|
1989
|
+
auto it = (n == -1)? const_iterator{pbb}: ++const_iterator{pbb, n};
|
|
1990
|
+
erase(it, cend());
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
template<typename Compare>
|
|
1995
|
+
bool transfer_sort(Compare comp)
|
|
1996
|
+
{
|
|
1997
|
+
//transfer to a buffer, sort and transfer back
|
|
1998
|
+
if(size_ > 1) {
|
|
1999
|
+
hub_detail::buffer<T,allocator_type> buf(size_, al());
|
|
2000
|
+
if(!buf.data) return false;
|
|
2001
|
+
|
|
2002
|
+
container::for_each(*this, [&] (value_type& x) {
|
|
2003
|
+
buf.emplace_back(std::move(x));
|
|
2004
|
+
});
|
|
2005
|
+
std::sort(buf.begin(), buf.end(), comp);
|
|
2006
|
+
container::for_each(*this, [&] (value_type& x) {
|
|
2007
|
+
x = std::move(*buf.begin());
|
|
2008
|
+
buf.erase_front();
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
return true;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
struct sort_proxy
|
|
2015
|
+
{
|
|
2016
|
+
T* p;
|
|
2017
|
+
size_type n;
|
|
2018
|
+
};
|
|
2019
|
+
|
|
2020
|
+
template<typename Compare>
|
|
2021
|
+
bool proxy_sort(Compare comp)
|
|
2022
|
+
{
|
|
2023
|
+
//sort an array of (pointer, index) pairs and relocate according to it
|
|
2024
|
+
if(size_ > 1) {
|
|
2025
|
+
hub_detail::nodtor_unique_ptr<sort_proxy[]> p
|
|
2026
|
+
{static_cast<sort_proxy*>(
|
|
2027
|
+
::operator new[](size_ * sizeof(sort_proxy), std::nothrow))};
|
|
2028
|
+
if(!p) return false;
|
|
2029
|
+
|
|
2030
|
+
size_type i = 0;
|
|
2031
|
+
container::for_each(*this, [&] (value_type& x) {
|
|
2032
|
+
p[i] = {dtl::addressof(x), i};
|
|
2033
|
+
++i;
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
std::sort(
|
|
2037
|
+
p.get(), p.get() + size_,
|
|
2038
|
+
[&] (const sort_proxy& x, const sort_proxy& y) {
|
|
2039
|
+
return comp(const_cast<const T&>(*x.p), const_cast<const T&>(*y.p));
|
|
2040
|
+
});
|
|
2041
|
+
|
|
2042
|
+
i = 0;
|
|
2043
|
+
for(; i < size_; ++i) {
|
|
2044
|
+
if(p[i].n != i) {
|
|
2045
|
+
T x = std::move(*(p[i].p));
|
|
2046
|
+
auto j = i;
|
|
2047
|
+
do {
|
|
2048
|
+
auto k = p[j].n;
|
|
2049
|
+
*(p[j].p) = std::move(*p[k].p);
|
|
2050
|
+
p[j].n = j;
|
|
2051
|
+
j = k;
|
|
2052
|
+
} while(p[j].n != i);
|
|
2053
|
+
*(p[j].p) = std::move(x);
|
|
2054
|
+
p[j].n = j;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
return true;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
template<typename Compare>
|
|
2062
|
+
void compact_sort(Compare comp)
|
|
2063
|
+
{
|
|
2064
|
+
//compact elements and build an array of pointers to data chunks of N
|
|
2065
|
+
using sort_iterator = hub_detail::sort_iterator<T, (std::size_t)N>;
|
|
2066
|
+
|
|
2067
|
+
if(size_ > 1) {
|
|
2068
|
+
std::size_t n = (std::size_t)((size_ + N - 1) / N);
|
|
2069
|
+
hub_detail::nodtor_unique_ptr<T*[]> p
|
|
2070
|
+
{static_cast<T**>(::operator new[](n * sizeof(T*)))};
|
|
2071
|
+
std::size_t i = 0;
|
|
2072
|
+
compact([&] (block_pointer pb) {
|
|
2073
|
+
p[i++] = boost::movelib::to_raw_pointer(pb->data());
|
|
2074
|
+
});
|
|
2075
|
+
BOOST_ASSERT(i == n);
|
|
2076
|
+
|
|
2077
|
+
std::sort(
|
|
2078
|
+
sort_iterator{p.get(), 0},
|
|
2079
|
+
sort_iterator{p.get(), (std::ptrdiff_t)size_}, comp);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
void compact() { compact([] (block_pointer) {}); }
|
|
2084
|
+
|
|
2085
|
+
template<typename Track>
|
|
2086
|
+
void compact(Track track)
|
|
2087
|
+
{
|
|
2088
|
+
for(auto pbbx = blist.next; pbbx != blist.header(); ) {
|
|
2089
|
+
auto pbx = static_cast_block_pointer(pbbx);
|
|
2090
|
+
auto pbby = pbbx->next;
|
|
2091
|
+
if(pbx->mask != full) {
|
|
2092
|
+
do{
|
|
2093
|
+
if(pbby->mask == full) {
|
|
2094
|
+
do {
|
|
2095
|
+
track(static_cast_block_pointer(pbby));
|
|
2096
|
+
pbby = pbby->next;
|
|
2097
|
+
} while(pbby->mask == full);
|
|
2098
|
+
blist.unlink(pbx);
|
|
2099
|
+
blist.link_before(pbx, static_cast_block_pointer(pbby));
|
|
2100
|
+
}
|
|
2101
|
+
if(pbby == blist.header()) {
|
|
2102
|
+
compact(pbx);
|
|
2103
|
+
track(pbx);
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
else{
|
|
2107
|
+
auto pby = static_cast_block_pointer(pbby);
|
|
2108
|
+
compact(pbx,pby);
|
|
2109
|
+
if(pby->mask == 0) {
|
|
2110
|
+
pbby = pby->next;
|
|
2111
|
+
blist.unlink(pby);
|
|
2112
|
+
blist.unlink_available(pby);
|
|
2113
|
+
blist.link_available_at_back(pby);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
}while(pbx->mask != full);
|
|
2117
|
+
blist.unlink_available(pbx);
|
|
2118
|
+
}
|
|
2119
|
+
track(pbx);
|
|
2120
|
+
pbbx = pbby;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
void compact(block_pointer pbx, block_pointer pby)
|
|
2125
|
+
{
|
|
2126
|
+
auto cx = dtl::popcount(pbx->mask),
|
|
2127
|
+
cy = dtl::popcount(pby->mask);
|
|
2128
|
+
if(cx < cy) {
|
|
2129
|
+
std::swap(cx, cy);
|
|
2130
|
+
swap_payload(*pbx, *pby);
|
|
2131
|
+
}
|
|
2132
|
+
auto c = (std::min)(N - cx, cy);
|
|
2133
|
+
while(c--) {
|
|
2134
|
+
auto n = dtl::unchecked_countr_one(pbx->mask);
|
|
2135
|
+
auto m = N - 1 - dtl::unchecked_countl_zero(pby->mask);
|
|
2136
|
+
block_alloc_traits::construct(
|
|
2137
|
+
al(), boost::movelib::to_raw_pointer(pbx->data() + n), std::move(pby->data()[m]));
|
|
2138
|
+
block_alloc_traits::destroy(al(), boost::movelib::to_raw_pointer(pby->data() + m));
|
|
2139
|
+
pbx->mask |= pbx->mask + 1;
|
|
2140
|
+
pby->mask &= ~((mask_type)(1) << m);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
void compact(block_pointer pb)
|
|
2145
|
+
{
|
|
2146
|
+
for(; ; ) {
|
|
2147
|
+
auto n = dtl::unchecked_countr_one(pb->mask);
|
|
2148
|
+
auto m = N - 1 - dtl::unchecked_countl_zero(pb->mask);
|
|
2149
|
+
if(n > m) return;
|
|
2150
|
+
block_alloc_traits::construct(
|
|
2151
|
+
al(), boost::movelib::to_raw_pointer(pb->data() + n), std::move(pb->data()[m]));
|
|
2152
|
+
block_alloc_traits::destroy(al(), boost::movelib::to_raw_pointer(pb->data() + m));
|
|
2153
|
+
pb->mask |= pb->mask + 1;
|
|
2154
|
+
pb->mask &= ~((mask_type)(1) << m);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
block_list blist;
|
|
2159
|
+
size_type num_blocks = 0;
|
|
2160
|
+
size_type size_ = 0;
|
|
2161
|
+
|
|
2162
|
+
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
2166
|
+
|
|
2167
|
+
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
|
|
2168
|
+
|
|
2169
|
+
template<typename InputIterator>
|
|
2170
|
+
hub(InputIterator, InputIterator)
|
|
2171
|
+
-> hub<typename std::iterator_traits<InputIterator>::value_type>;
|
|
2172
|
+
|
|
2173
|
+
template<typename InputIterator, typename Allocator>
|
|
2174
|
+
hub(InputIterator, InputIterator, Allocator)
|
|
2175
|
+
-> hub<typename std::iterator_traits<InputIterator>::value_type, Allocator>;
|
|
2176
|
+
|
|
2177
|
+
//The (initializer_list) case is covered by the implicit guide of the
|
|
2178
|
+
//initializer_list constructor (the allocator defaults to void); an explicit
|
|
2179
|
+
//guide is only needed to deduce a user-supplied allocator, since the resolved
|
|
2180
|
+
//in-class allocator type is a non-deduced context.
|
|
2181
|
+
template<typename T, typename Allocator>
|
|
2182
|
+
hub(std::initializer_list<T>, Allocator) -> hub<T, Allocator>;
|
|
2183
|
+
|
|
2184
|
+
#if !defined(BOOST_CONTAINER_HUB_NO_RANGES)
|
|
2185
|
+
template<hub_detail::input_range_like R>
|
|
2186
|
+
hub(from_range_t, R&&) -> hub<hub_detail::range_value_t<R> >;
|
|
2187
|
+
|
|
2188
|
+
template<hub_detail::input_range_like R, typename Allocator>
|
|
2189
|
+
hub(from_range_t, R&&, Allocator) -> hub<hub_detail::range_value_t<R>, Allocator>;
|
|
2190
|
+
|
|
2191
|
+
#endif //BOOST_CONTAINER_HUB_NO_RANGES
|
|
2192
|
+
|
|
2193
|
+
#endif //BOOST_NO_CXX17_DEDUCTION_GUIDES
|
|
2194
|
+
|
|
2195
|
+
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
2196
|
+
|
|
2197
|
+
//! <b>Effects</b>: Equivalent to x.swap(y).
|
|
2198
|
+
//!
|
|
2199
|
+
//! <b>Complexity</b>: Constant.
|
|
2200
|
+
template<typename T, typename Allocator>
|
|
2201
|
+
void swap(hub<T, Allocator>& x, hub<T, Allocator>& y)
|
|
2202
|
+
noexcept(noexcept(x.swap(y)))
|
|
2203
|
+
{
|
|
2204
|
+
x.swap(y);
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
//! <b>Effects</b>: Erases all elements of x equal to value. Equivalent to
|
|
2208
|
+
//! erase_if(x, [&](const auto& e){ return e == value; }).
|
|
2209
|
+
//!
|
|
2210
|
+
//! <b>Returns</b>: The number of erased elements.
|
|
2211
|
+
//!
|
|
2212
|
+
//! <b>Complexity</b>: Linear in x.size().
|
|
2213
|
+
template<typename T, typename Allocator, typename U = T>
|
|
2214
|
+
typename hub<T, Allocator>::size_type
|
|
2215
|
+
erase(hub<T, Allocator>& x, const U& value)
|
|
2216
|
+
{
|
|
2217
|
+
return container::erase_if(
|
|
2218
|
+
x, [&](const T& v) -> bool { return v == value; });
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
//! <b>Effects</b>: Erases all elements of x for which pred returns true.
|
|
2222
|
+
//!
|
|
2223
|
+
//! <b>Returns</b>: The number of erased elements.
|
|
2224
|
+
//!
|
|
2225
|
+
//! <b>Complexity</b>: Linear in x.size().
|
|
2226
|
+
//!
|
|
2227
|
+
//! <b>Note</b>: Potentially faster than the naive erase loop due to internal
|
|
2228
|
+
//! optimizations.
|
|
2229
|
+
template<typename T, typename Allocator, typename Predicate>
|
|
2230
|
+
typename hub<T, Allocator>::size_type
|
|
2231
|
+
erase_if(hub<T, Allocator>& x, Predicate pred)
|
|
2232
|
+
{
|
|
2233
|
+
using hub_container = hub<T, Allocator>;
|
|
2234
|
+
using size_type = typename hub_container::size_type;
|
|
2235
|
+
using block = typename hub_container::block;
|
|
2236
|
+
|
|
2237
|
+
auto s = x.size_;
|
|
2238
|
+
for(auto pbb = x.blist.next; pbb != x.blist.header(); ) {
|
|
2239
|
+
auto pb = x.static_cast_block_pointer(pbb);
|
|
2240
|
+
pbb = pb->next;
|
|
2241
|
+
BOOST_CONTAINER_HUB_PREFETCH_BLOCK(pbb, block);
|
|
2242
|
+
auto mask = pb->mask;
|
|
2243
|
+
do {
|
|
2244
|
+
auto n = dtl::unchecked_countr_zero(mask);
|
|
2245
|
+
if(pred(pb->data()[n])) x.erase_impl(pb, n);
|
|
2246
|
+
mask &= mask - 1;
|
|
2247
|
+
} while(mask);
|
|
2248
|
+
}
|
|
2249
|
+
return (size_type)(s - x.size_);
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
//! <b>Effects</b>: Applies f to every element in [first, last), in order.
|
|
2253
|
+
//! Equivalent to: while(first != last) f(*first++); return f;
|
|
2254
|
+
//!
|
|
2255
|
+
//! <b>Requires</b>: decltype(first) is the `iterator` or `const_iterator` of an
|
|
2256
|
+
//! instantiation of hub and [first, last) is a valid range.
|
|
2257
|
+
//!
|
|
2258
|
+
//! <b>Returns</b>: std::move(f).
|
|
2259
|
+
//!
|
|
2260
|
+
//! <b>Note</b>: Potentially faster than the equivalent loop thanks to internal
|
|
2261
|
+
//! unrolling and prefetching.
|
|
2262
|
+
template< BOOST_CONTAINER_DOC1ST(class ImplDefinedHubIterator, typename ValuePtr), typename F>
|
|
2263
|
+
BOOST_CONTAINER_FORCEINLINE F for_each
|
|
2264
|
+
( BOOST_CONTAINER_DOC1ST(ImplDefinedHubIterator, hub_detail::iterator<ValuePtr>) first
|
|
2265
|
+
, BOOST_CONTAINER_DOC1ST(ImplDefinedHubIterator, hub_detail::iterator<ValuePtr>) last
|
|
2266
|
+
, F f)
|
|
2267
|
+
{
|
|
2268
|
+
container::for_each_while(
|
|
2269
|
+
first, last, hub_detail::inline_return_true_ref_caller<F>{f});
|
|
2270
|
+
return f;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
//! <b>Effects</b>: Applies f to every element of x. Equivalent to
|
|
2274
|
+
//! for_each(x.begin(), x.end(), std::ref(f)).
|
|
2275
|
+
//!
|
|
2276
|
+
//! <b>Returns</b>: std::move(f).
|
|
2277
|
+
//!
|
|
2278
|
+
//! <b>Note</b>: Potentially faster than range iteration thanks to internal
|
|
2279
|
+
//! unrolling and prefetching.
|
|
2280
|
+
template<typename T, typename Allocator, typename F>
|
|
2281
|
+
BOOST_CONTAINER_FORCEINLINE F for_each(hub<T, Allocator>& x, F f)
|
|
2282
|
+
{
|
|
2283
|
+
container::for_each_while(
|
|
2284
|
+
x, hub_detail::inline_return_true_ref_caller<F>{f});
|
|
2285
|
+
return f;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
//! <b>Effects</b>: Applies f to every element of x. Equivalent to
|
|
2289
|
+
//! for_each(x.cbegin(), x.cend(), std::ref(f)).
|
|
2290
|
+
//!
|
|
2291
|
+
//! <b>Returns</b>: std::move(f).
|
|
2292
|
+
//!
|
|
2293
|
+
//! <b>Note</b>: Potentially faster than range iteration thanks to internal
|
|
2294
|
+
//! unrolling and prefetching.
|
|
2295
|
+
template<typename T, typename Allocator, typename F>
|
|
2296
|
+
BOOST_CONTAINER_FORCEINLINE F for_each(const hub<T, Allocator>& x, F f)
|
|
2297
|
+
{
|
|
2298
|
+
container::for_each_while(
|
|
2299
|
+
const_cast<hub<T, Allocator>&>(x),
|
|
2300
|
+
hub_detail::inline_return_true_ref_const_caller<F>{f});
|
|
2301
|
+
return f;
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
//! <b>Effects</b>: Applies f to the elements of [first, last) in order while f
|
|
2305
|
+
//! returns true. Equivalent to:
|
|
2306
|
+
//! while(first != last && f(*first)) ++first; return {first, std::move(f)};
|
|
2307
|
+
//!
|
|
2308
|
+
//! <b>Requires</b>: decltype(first) is the `iterator` or `const_iterator` of an
|
|
2309
|
+
//! instantiation of hub and [first, last) is a valid range.
|
|
2310
|
+
//!
|
|
2311
|
+
//! <b>Returns</b>: A pair with the iterator past the last visited element and
|
|
2312
|
+
//! std::move(f).
|
|
2313
|
+
//!
|
|
2314
|
+
//! <b>Note</b>: Potentially faster than the equivalent loop thanks to internal
|
|
2315
|
+
//! unrolling and prefetching.
|
|
2316
|
+
template< BOOST_CONTAINER_DOC1ST(class ImplDefinedHubIterator, typename ValuePtr), typename F>
|
|
2317
|
+
std::pair<BOOST_CONTAINER_DOC1ST(ImplDefinedHubIterator, hub_detail::iterator<ValuePtr>), F>
|
|
2318
|
+
for_each_while
|
|
2319
|
+
( BOOST_CONTAINER_DOC1ST(ImplDefinedHubIterator, hub_detail::iterator<ValuePtr>) first
|
|
2320
|
+
, BOOST_CONTAINER_DOC1ST(ImplDefinedHubIterator, hub_detail::iterator<ValuePtr>) last
|
|
2321
|
+
, F f)
|
|
2322
|
+
{
|
|
2323
|
+
using iterator = hub_detail::iterator<ValuePtr>;
|
|
2324
|
+
using block = typename iterator::block;
|
|
2325
|
+
using mask_type = typename iterator::mask_type;
|
|
2326
|
+
static constexpr auto full = iterator::full;
|
|
2327
|
+
|
|
2328
|
+
if(BOOST_UNLIKELY(first == last)) return {last, std::move(f)};
|
|
2329
|
+
|
|
2330
|
+
auto pbb = first.pbb,
|
|
2331
|
+
last_pbb = last.pbb;
|
|
2332
|
+
auto last_n = last.n;
|
|
2333
|
+
auto mask = pbb->mask & (full << first.n);
|
|
2334
|
+
|
|
2335
|
+
for(; ;) {
|
|
2336
|
+
BOOST_CONTAINER_HUB_PREFETCH(&pbb->next->mask);
|
|
2337
|
+
auto is_last = mask_type(pbb == last_pbb);
|
|
2338
|
+
mask &= (is_last << last_n) - mask_type(1);
|
|
2339
|
+
BOOST_CONTAINER_HUB_PREFETCH(
|
|
2340
|
+
block::static_cast_block_pointer(pbb->next)->data());
|
|
2341
|
+
auto next_n = dtl::unchecked_countr_zero(pbb->next->mask);
|
|
2342
|
+
BOOST_CONTAINER_HUB_PREFETCH(
|
|
2343
|
+
block::static_cast_block_pointer(pbb->next)->data() + next_n);
|
|
2344
|
+
auto pd = block::static_cast_block_pointer(pbb)->data();
|
|
2345
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2346
|
+
while(mask) {
|
|
2347
|
+
auto n = dtl::unchecked_countr_zero(mask);
|
|
2348
|
+
if (!f(pd[n])) return {{pbb, n}, std::move(f)};
|
|
2349
|
+
mask &= mask - 1;
|
|
2350
|
+
}
|
|
2351
|
+
if(BOOST_UNLIKELY(is_last != 0)) return {last, std::move(f)};
|
|
2352
|
+
pbb = pbb->next;
|
|
2353
|
+
mask = pbb->mask;
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
//! <b>Effects</b>: Applies f to the elements of x while f returns true.
|
|
2358
|
+
//! Equivalent to for_each_while(x.begin(), x.end(), std::ref(f)) with f moved
|
|
2359
|
+
//! into the returned pair.
|
|
2360
|
+
//!
|
|
2361
|
+
//! <b>Returns</b>: A pair with the iterator past the last visited element and
|
|
2362
|
+
//! std::move(f).
|
|
2363
|
+
//!
|
|
2364
|
+
//! <b>Note</b>: Potentially faster than range iteration thanks to internal
|
|
2365
|
+
//! unrolling and prefetching.
|
|
2366
|
+
template<typename T, typename Allocator, typename F>
|
|
2367
|
+
std::pair<typename hub<T, Allocator>::iterator, F>
|
|
2368
|
+
for_each_while(hub<T, Allocator>& x, F f)
|
|
2369
|
+
{
|
|
2370
|
+
using iterator = typename hub<T, Allocator>::iterator;
|
|
2371
|
+
using block = typename iterator::block;
|
|
2372
|
+
|
|
2373
|
+
auto last_pbb = x.blist.header();
|
|
2374
|
+
for(auto pbb = x.blist.next; pbb != last_pbb; ) {
|
|
2375
|
+
BOOST_CONTAINER_HUB_PREFETCH(&pbb->next->mask);
|
|
2376
|
+
BOOST_CONTAINER_HUB_PREFETCH(
|
|
2377
|
+
block::static_cast_block_pointer(pbb->next)->data());
|
|
2378
|
+
auto next_n = dtl::unchecked_countr_zero(pbb->next->mask);
|
|
2379
|
+
BOOST_CONTAINER_HUB_PREFETCH(
|
|
2380
|
+
block::static_cast_block_pointer(pbb->next)->data() + next_n);
|
|
2381
|
+
auto pd = block::static_cast_block_pointer(pbb)->data();
|
|
2382
|
+
auto mask = pbb->mask;
|
|
2383
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2384
|
+
while(mask) {
|
|
2385
|
+
auto n = dtl::unchecked_countr_zero(mask);
|
|
2386
|
+
if (!f(pd[n])) return {{pbb, n}, std::move(f)};
|
|
2387
|
+
mask &= mask - 1;
|
|
2388
|
+
}
|
|
2389
|
+
pbb = pbb->next;
|
|
2390
|
+
mask = pbb->mask;
|
|
2391
|
+
}
|
|
2392
|
+
return {{last_pbb}, std::move(f)};
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
//! <b>Effects</b>: Applies f to the elements of x while f returns true.
|
|
2396
|
+
//! Equivalent to for_each_while(x.cbegin(), x.cend(), std::ref(f)) with f moved
|
|
2397
|
+
//! into the returned pair.
|
|
2398
|
+
//!
|
|
2399
|
+
//! <b>Returns</b>: A pair with the iterator past the last visited element and
|
|
2400
|
+
//! std::move(f).
|
|
2401
|
+
//!
|
|
2402
|
+
//! <b>Note</b>: Potentially faster than range iteration thanks to internal
|
|
2403
|
+
//! unrolling and prefetching.
|
|
2404
|
+
template<typename T, typename Allocator, typename F>
|
|
2405
|
+
std::pair<typename hub<T, Allocator>::const_iterator, F>
|
|
2406
|
+
BOOST_CONTAINER_FORCEINLINE for_each_while(const hub<T, Allocator>& x, F f)
|
|
2407
|
+
{
|
|
2408
|
+
return {
|
|
2409
|
+
container::for_each_while(
|
|
2410
|
+
const_cast<hub<T, Allocator>&>(x),
|
|
2411
|
+
hub_detail::inline_ref_const_caller<F>{f}).first,
|
|
2412
|
+
std::move(f)};
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
} //namespace container
|
|
2416
|
+
|
|
2417
|
+
} //namespace boost
|
|
2418
|
+
|
|
2419
|
+
#if defined(BOOST_MSVC)
|
|
2420
|
+
#pragma warning(pop) //C4714
|
|
2421
|
+
#endif
|
|
2422
|
+
|
|
2423
|
+
#include <boost/container/detail/config_end.hpp>
|
|
2424
|
+
|
|
2425
|
+
#endif //BOOST_CONTAINER_HUB_HPP
|
|
2426
|
+
|