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,2978 @@
|
|
|
1
|
+
|
|
2
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
3
|
+
//
|
|
4
|
+
// (C) Copyright Joaquin M Lopez Munoz 2025-2026.
|
|
5
|
+
// (C) Copyright Ion Gaztanaga 2025-2026.
|
|
6
|
+
//
|
|
7
|
+
// Distributed under the Boost Software License, Version 1.0.
|
|
8
|
+
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
9
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
|
10
|
+
//
|
|
11
|
+
// See http://www.boost.org/libs/container for documentation.
|
|
12
|
+
//
|
|
13
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
#ifndef BOOST_CONTAINER_EXPERIMENTAL_NEST_HPP
|
|
15
|
+
#define BOOST_CONTAINER_EXPERIMENTAL_NEST_HPP
|
|
16
|
+
|
|
17
|
+
#ifndef BOOST_CONFIG_HPP
|
|
18
|
+
# include <boost/config.hpp>
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
|
22
|
+
# pragma once
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#include <boost/container/detail/config_begin.hpp>
|
|
26
|
+
#include <boost/container/detail/workaround.hpp>
|
|
27
|
+
|
|
28
|
+
// container
|
|
29
|
+
#include <boost/container/container_fwd.hpp>
|
|
30
|
+
#include <boost/container/options.hpp>
|
|
31
|
+
#include <boost/container/new_allocator.hpp>
|
|
32
|
+
#include <boost/container/allocator_traits.hpp>
|
|
33
|
+
// container/detail
|
|
34
|
+
#include <boost/container/detail/aligned_allocation.hpp> //portable (over)aligned nothrow alloc
|
|
35
|
+
#include <boost/container/detail/bit_utilities.hpp>
|
|
36
|
+
#include <boost/container/detail/compare_functors.hpp>
|
|
37
|
+
#include <boost/container/detail/iterator.hpp>
|
|
38
|
+
#include <boost/container/detail/iterators.hpp>
|
|
39
|
+
#include <boost/container/detail/mpl.hpp>
|
|
40
|
+
#include <boost/container/detail/type_traits.hpp>
|
|
41
|
+
// move
|
|
42
|
+
#include <boost/move/utility_core.hpp>
|
|
43
|
+
#include <boost/move/core.hpp>
|
|
44
|
+
#include <boost/move/traits.hpp>
|
|
45
|
+
#include <boost/move/adl_move_swap.hpp>
|
|
46
|
+
#include <boost/move/iterator.hpp>
|
|
47
|
+
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
|
48
|
+
# include <boost/move/detail/fwd_macros.hpp>
|
|
49
|
+
#endif
|
|
50
|
+
#include <boost/move/detail/move_helpers.hpp>
|
|
51
|
+
#include <boost/move/detail/to_raw_pointer.hpp>
|
|
52
|
+
// intrusive
|
|
53
|
+
#include <boost/intrusive/pointer_traits.hpp>
|
|
54
|
+
//
|
|
55
|
+
#include <boost/assert.hpp>
|
|
56
|
+
#include <boost/container/detail/addressof.hpp>
|
|
57
|
+
// std
|
|
58
|
+
#include <algorithm>
|
|
59
|
+
#include <cstddef>
|
|
60
|
+
#include <functional>
|
|
61
|
+
#include <new>
|
|
62
|
+
#include <utility>
|
|
63
|
+
#include <boost/cstdint.hpp>
|
|
64
|
+
#include <climits>
|
|
65
|
+
|
|
66
|
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
67
|
+
#include <initializer_list>
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
#if !defined(BOOST_CONTAINER_NEST_DISABLE_SSE2)
|
|
71
|
+
#if defined(BOOST_CONTAINER_NEST_ENABLE_SSE2)|| \
|
|
72
|
+
defined(__SSE2__) || \
|
|
73
|
+
defined(_M_X64) || (defined(_M_IX86_FP)&&_M_IX86_FP>=2)
|
|
74
|
+
#define BOOST_CONTAINER_NEST_SSE2
|
|
75
|
+
#endif
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
#if defined(BOOST_CONTAINER_NEST_SSE2)
|
|
79
|
+
#include <emmintrin.h>
|
|
80
|
+
#endif
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
// Fancy-pointer-aware wrapper over BOOST_CONTAINER_PREFETCH (defined in
|
|
84
|
+
// workaround.hpp): it converts 'p' to a raw pointer before prefetching.
|
|
85
|
+
#define BOOST_CONTAINER_NEST_PREFETCH(p) \
|
|
86
|
+
BOOST_CONTAINER_PREFETCH(boost::movelib::to_raw_pointer(p))
|
|
87
|
+
|
|
88
|
+
#define BOOST_CONTAINER_NEST_PREFETCH_BLOCK(pbb) \
|
|
89
|
+
do{ \
|
|
90
|
+
BOOST_CONTAINER_NEST_PREFETCH(static_cast<block_type&>(*(pbb)).data());\
|
|
91
|
+
} while(0)\
|
|
92
|
+
//
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
#if defined(BOOST_MSVC)
|
|
96
|
+
#pragma warning(push)
|
|
97
|
+
#pragma warning(disable:4714) // marked as __forceinline not inlined
|
|
98
|
+
#endif
|
|
99
|
+
|
|
100
|
+
namespace boost {
|
|
101
|
+
namespace container {
|
|
102
|
+
|
|
103
|
+
////////////////////////////////////////////////////////////////
|
|
104
|
+
//
|
|
105
|
+
//
|
|
106
|
+
// OPTIONS FOR NEST CONTAINER (EXPERIMENTAL)
|
|
107
|
+
//
|
|
108
|
+
//
|
|
109
|
+
////////////////////////////////////////////////////////////////
|
|
110
|
+
|
|
111
|
+
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
112
|
+
|
|
113
|
+
template<bool StoreDataInBlock, bool Prefetch>
|
|
114
|
+
struct nest_opt
|
|
115
|
+
{
|
|
116
|
+
BOOST_STATIC_CONSTEXPR bool store_data_in_block = StoreDataInBlock;
|
|
117
|
+
BOOST_STATIC_CONSTEXPR bool prefetch = Prefetch;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
typedef nest_opt<false, true> nest_null_opt;
|
|
121
|
+
|
|
122
|
+
#endif // !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
123
|
+
|
|
124
|
+
//! This option specifies whether block data (value storage) is inlined
|
|
125
|
+
//! in each block (true) or allocated separately via the allocator (false).
|
|
126
|
+
//! Inline data can improve locality but increases block size.
|
|
127
|
+
//!
|
|
128
|
+
//!\tparam Enabled A boolean value.
|
|
129
|
+
BOOST_INTRUSIVE_OPTION_CONSTANT(store_data_in_block, bool, Enabled, store_data_in_block)
|
|
130
|
+
|
|
131
|
+
//! This option specifies if hardware prefetch instructions
|
|
132
|
+
//! are emitted during iteration and other traversal operations.
|
|
133
|
+
//! When enabled, prefetching can improve performance by reducing
|
|
134
|
+
//! cache misses. The default value is true.
|
|
135
|
+
//!
|
|
136
|
+
//!\tparam Enabled A boolean value. True to enable prefetching.
|
|
137
|
+
BOOST_INTRUSIVE_OPTION_CONSTANT(prefetch, bool, Enabled, prefetch)
|
|
138
|
+
|
|
139
|
+
//! Helper metafunction to combine options into a single type to be used
|
|
140
|
+
//! by \c boost::container::nest.
|
|
141
|
+
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
|
142
|
+
template<class ...Options>
|
|
143
|
+
#else
|
|
144
|
+
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
|
|
145
|
+
#endif
|
|
146
|
+
struct nest_options
|
|
147
|
+
{
|
|
148
|
+
/// @cond
|
|
149
|
+
typedef typename ::boost::intrusive::pack_options
|
|
150
|
+
< nest_null_opt,
|
|
151
|
+
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
|
152
|
+
O1, O2, O3, O4
|
|
153
|
+
#else
|
|
154
|
+
Options...
|
|
155
|
+
#endif
|
|
156
|
+
>::type packed_options;
|
|
157
|
+
typedef nest_opt<
|
|
158
|
+
packed_options::store_data_in_block,
|
|
159
|
+
packed_options::prefetch> implementation_defined;
|
|
160
|
+
/// @endcond
|
|
161
|
+
typedef implementation_defined type;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
|
165
|
+
|
|
166
|
+
template<class ...Options>
|
|
167
|
+
using nest_options_t = typename boost::container::nest_options<Options...>::type;
|
|
168
|
+
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
#endif // !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
172
|
+
|
|
173
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
174
|
+
|
|
175
|
+
template <class T
|
|
176
|
+
,class Allocator = void
|
|
177
|
+
,class Options = void>
|
|
178
|
+
class nest;
|
|
179
|
+
|
|
180
|
+
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch>
|
|
181
|
+
class nest_iterator;
|
|
182
|
+
|
|
183
|
+
template<class T, class Allocator, class Options, class Predicate>
|
|
184
|
+
typename nest<T, Allocator, Options>::size_type
|
|
185
|
+
erase_if(nest<T, Allocator, Options>&, Predicate);
|
|
186
|
+
|
|
187
|
+
template<class T, class Allocator, class Options, class F>
|
|
188
|
+
F for_each(nest<T, Allocator, Options>&, F);
|
|
189
|
+
|
|
190
|
+
template<class T, class Allocator, class Options, class F>
|
|
191
|
+
F for_each(const nest<T, Allocator, Options>&, F);
|
|
192
|
+
|
|
193
|
+
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch, class F>
|
|
194
|
+
std::pair< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>, F >
|
|
195
|
+
for_each_while
|
|
196
|
+
( nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>
|
|
197
|
+
, nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>
|
|
198
|
+
, F);
|
|
199
|
+
|
|
200
|
+
namespace nest_detail {
|
|
201
|
+
|
|
202
|
+
//////////////////////////////////////////////
|
|
203
|
+
//
|
|
204
|
+
// pointer_rebind helper
|
|
205
|
+
//
|
|
206
|
+
//////////////////////////////////////////////
|
|
207
|
+
|
|
208
|
+
template<class Pointer, class T>
|
|
209
|
+
struct pointer_rebind
|
|
210
|
+
{
|
|
211
|
+
typedef typename boost::intrusive::pointer_traits<Pointer>::
|
|
212
|
+
template rebind_pointer<T>::type type;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
//////////////////////////////////////////////
|
|
216
|
+
//
|
|
217
|
+
// bit manipulation helpers
|
|
218
|
+
//
|
|
219
|
+
//////////////////////////////////////////////
|
|
220
|
+
|
|
221
|
+
//Shared bit helpers live in boost::container::dtl (detail/bit_utilities.hpp).
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
//////////////////////////////////////////////
|
|
225
|
+
//
|
|
226
|
+
// find_if_not (C++03-compatible)
|
|
227
|
+
//
|
|
228
|
+
//////////////////////////////////////////////
|
|
229
|
+
|
|
230
|
+
template<class It, class Pred>
|
|
231
|
+
It find_if_not(It first, It last, Pred pred)
|
|
232
|
+
{
|
|
233
|
+
for (; first != last; ++first)
|
|
234
|
+
if (!pred(*first))
|
|
235
|
+
break;
|
|
236
|
+
return first;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
//////////////////////////////////////////////
|
|
240
|
+
//
|
|
241
|
+
// block_base / block
|
|
242
|
+
//
|
|
243
|
+
//////////////////////////////////////////////
|
|
244
|
+
|
|
245
|
+
template<class VoidPointer>
|
|
246
|
+
struct block_base
|
|
247
|
+
{
|
|
248
|
+
typedef typename pointer_rebind<VoidPointer, block_base>::type pointer;
|
|
249
|
+
typedef typename pointer_rebind<VoidPointer, const block_base>::type const_pointer;
|
|
250
|
+
typedef boost::uint64_t mask_type;
|
|
251
|
+
|
|
252
|
+
BOOST_STATIC_CONSTEXPR std::size_t N = sizeof(mask_type)*CHAR_BIT;
|
|
253
|
+
BOOST_STATIC_CONSTEXPR mask_type full = (mask_type)(-1);
|
|
254
|
+
|
|
255
|
+
BOOST_CONTAINER_FORCEINLINE static pointer pointer_to(block_base& x) BOOST_NOEXCEPT
|
|
256
|
+
{
|
|
257
|
+
return boost::intrusive::pointer_traits<pointer>::pointer_to(x);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
BOOST_CONTAINER_FORCEINLINE static const_pointer pointer_to(const block_base& x) BOOST_NOEXCEPT
|
|
261
|
+
{
|
|
262
|
+
return boost::intrusive::pointer_traits<const_pointer>::pointer_to(x);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
block_base()
|
|
266
|
+
{
|
|
267
|
+
this->reset();
|
|
268
|
+
mask = 1; // sentinel
|
|
269
|
+
//mask = 0; // sentinel
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_before(pointer p) BOOST_NOEXCEPT
|
|
273
|
+
{
|
|
274
|
+
next_available = p;
|
|
275
|
+
prev_available = p->prev_available;
|
|
276
|
+
pointer const pthis = pointer_to(*this);
|
|
277
|
+
next_available->prev_available = pthis;
|
|
278
|
+
prev_available->next_available = pthis;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_after(pointer p) BOOST_NOEXCEPT
|
|
282
|
+
{
|
|
283
|
+
prev_available = p;
|
|
284
|
+
next_available = p->next_available;
|
|
285
|
+
pointer const pthis = pointer_to(*this);
|
|
286
|
+
next_available->prev_available = pthis;
|
|
287
|
+
prev_available->next_available = pthis;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
BOOST_CONTAINER_FORCEINLINE void unlink_available() BOOST_NOEXCEPT
|
|
291
|
+
{
|
|
292
|
+
prev_available->next_available = next_available;
|
|
293
|
+
next_available->prev_available = prev_available;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
BOOST_CONTAINER_FORCEINLINE void link_before(pointer p) BOOST_NOEXCEPT
|
|
297
|
+
{
|
|
298
|
+
next = p;
|
|
299
|
+
prev = p->prev;
|
|
300
|
+
pointer const pthis = pointer_to(*this);
|
|
301
|
+
next->prev = pthis;
|
|
302
|
+
prev->next = pthis;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
BOOST_CONTAINER_FORCEINLINE void unlink() BOOST_NOEXCEPT
|
|
306
|
+
{
|
|
307
|
+
prev->next = next;
|
|
308
|
+
next->prev = prev;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
BOOST_CONTAINER_FORCEINLINE pointer header() BOOST_NOEXCEPT
|
|
312
|
+
{
|
|
313
|
+
return pointer_to(*this);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
BOOST_CONTAINER_FORCEINLINE const_pointer header() const BOOST_NOEXCEPT
|
|
317
|
+
{
|
|
318
|
+
return pointer_to(*this);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
BOOST_CONTAINER_FORCEINLINE void link_at_back(pointer pb) BOOST_NOEXCEPT
|
|
322
|
+
{
|
|
323
|
+
pb->link_before(header());
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
BOOST_CONTAINER_FORCEINLINE void link_before(
|
|
327
|
+
pointer pbx, pointer pby) BOOST_NOEXCEPT
|
|
328
|
+
{
|
|
329
|
+
pbx->link_before(pby);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
BOOST_CONTAINER_FORCEINLINE static void unlink(pointer pb) BOOST_NOEXCEPT
|
|
333
|
+
{
|
|
334
|
+
pb->unlink();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_at_back(pointer pb) BOOST_NOEXCEPT
|
|
338
|
+
{
|
|
339
|
+
pb->link_available_before(header());
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
BOOST_CONTAINER_FORCEINLINE void link_available_at_front(pointer pb) BOOST_NOEXCEPT
|
|
343
|
+
{
|
|
344
|
+
pb->link_available_after(header());
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
BOOST_CONTAINER_FORCEINLINE void unlink_available(pointer pb) BOOST_NOEXCEPT
|
|
348
|
+
{
|
|
349
|
+
pb->unlink_available();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
void reset() BOOST_NOEXCEPT
|
|
353
|
+
{
|
|
354
|
+
pointer const h = header();
|
|
355
|
+
prev_available = h;
|
|
356
|
+
next_available = h;
|
|
357
|
+
prev = h;
|
|
358
|
+
next = h;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
block_base(BOOST_RV_REF(block_base) x) BOOST_NOEXCEPT
|
|
362
|
+
{
|
|
363
|
+
mask = 1; // sentinel
|
|
364
|
+
this->operator=(boost::move(x));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
block_base& operator=(BOOST_RV_REF(block_base) x) BOOST_NOEXCEPT
|
|
368
|
+
{
|
|
369
|
+
pointer const x_header = x.header();
|
|
370
|
+
pointer const t_header = this->header();
|
|
371
|
+
|
|
372
|
+
if (x.next_available != x_header) {
|
|
373
|
+
prev_available = x.prev_available;
|
|
374
|
+
next_available = x.next_available;
|
|
375
|
+
next_available->prev_available = t_header;
|
|
376
|
+
prev_available->next_available = t_header;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
prev_available = t_header;
|
|
380
|
+
next_available = t_header;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (x.prev != x_header) {
|
|
384
|
+
prev = x.prev;
|
|
385
|
+
next = x.next;
|
|
386
|
+
next->prev = t_header;
|
|
387
|
+
prev->next = t_header;
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
prev = t_header;
|
|
391
|
+
next = t_header;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
x.reset();
|
|
395
|
+
return *this;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//////////////////////////////////////////////
|
|
399
|
+
//
|
|
400
|
+
// block_base linked-list memberships
|
|
401
|
+
//
|
|
402
|
+
//////////////////////////////////////////////
|
|
403
|
+
//
|
|
404
|
+
//Each block_base is simultaneously a node in TWO doubly-linked,
|
|
405
|
+
//circular lists. Both lists are anchored at the per-nest `blist`
|
|
406
|
+
//sentinel (itself a block_base, embedded inside `nest` and with no
|
|
407
|
+
//associated data array) returned by `header()`.
|
|
408
|
+
//
|
|
409
|
+
//A given block participates in each list depending on the value of
|
|
410
|
+
//its own `mask`:
|
|
411
|
+
//
|
|
412
|
+
// | main list | available list
|
|
413
|
+
// -----------------+-----------+----------------
|
|
414
|
+
// mask == 0 | no | yes (empty, reusable)
|
|
415
|
+
// 0 < mask < full | yes | yes (partial)
|
|
416
|
+
// mask == full | yes | no (saturated)
|
|
417
|
+
//
|
|
418
|
+
//(1) MAIN LIST -- members `prev` / `next`
|
|
419
|
+
//
|
|
420
|
+
// Spans every block that holds at least one live element
|
|
421
|
+
// (mask != 0). Defines the user-visible block ordering: the
|
|
422
|
+
// nest's `begin()` returns an iterator to the first set bit
|
|
423
|
+
// of `blist.next->mask`; `nest_iterator::operator++` walks
|
|
424
|
+
// to the successor block via `pbb->next`, and
|
|
425
|
+
// `operator--` via `pbb->prev`. Thus iteration order is
|
|
426
|
+
// exactly the order in which blocks first became non-empty
|
|
427
|
+
// (link_at_back appends a freshly-non-empty block at the
|
|
428
|
+
// tail). The sentinel `header()` itself does NOT belong to
|
|
429
|
+
// the user-visible sequence; reaching `next == header()`
|
|
430
|
+
// signals end-of-range.
|
|
431
|
+
//
|
|
432
|
+
// Maintenance points:
|
|
433
|
+
// * link_at_back(pb) on the empty->non-empty transition
|
|
434
|
+
// (priv_insert_range_copy, emplace's "mask was 0" branch).
|
|
435
|
+
// * unlink(pb) on the non-empty->empty transition
|
|
436
|
+
// (priv_erase_impl when mask becomes 0).
|
|
437
|
+
// * priv_reset's second sweep walks `blist.next` to deal
|
|
438
|
+
// with the blocks that the first available-list sweep
|
|
439
|
+
// left behind, which by then must all be saturated.
|
|
440
|
+
//
|
|
441
|
+
//(2) AVAILABLE LIST -- members `prev_available` / `next_available`
|
|
442
|
+
//
|
|
443
|
+
// Spans every block that has at least one free slot
|
|
444
|
+
// (mask != full): empty blocks and partial blocks. This is
|
|
445
|
+
// the freelist consulted on every insertion by
|
|
446
|
+
// `priv_retrieve_available_block`, which returns
|
|
447
|
+
// `blist.next_available` and lands the new element on the
|
|
448
|
+
// lowest 0-bit of that block's mask. As long as the list is
|
|
449
|
+
// non-empty, insertion is O(1) and never reaches the
|
|
450
|
+
// allocator.
|
|
451
|
+
//
|
|
452
|
+
// INVARIANT: the available list is partitioned so that all
|
|
453
|
+
// PARTIAL blocks come first and all EMPTY (reserved) blocks come
|
|
454
|
+
// last: [ partial ... partial | empty ... empty ]. This lets
|
|
455
|
+
// `trim_capacity` walk the list backwards from `prev_available`
|
|
456
|
+
// and stop at the first non-empty block, making it linear on the
|
|
457
|
+
// number of reserved blocks rather than on the whole list.
|
|
458
|
+
//
|
|
459
|
+
// Insertion-order policy that preserves the partition:
|
|
460
|
+
// * empty blocks (freshly allocated, or just drained by an
|
|
461
|
+
// erase/compaction) are linked at the BACK
|
|
462
|
+
// (link_available_at_back). Freshly allocated empties are
|
|
463
|
+
// thus also consumed last, after existing partials.
|
|
464
|
+
// * a saturated block that becomes partial again because an
|
|
465
|
+
// element was erased is linked at the FRONT
|
|
466
|
+
// (link_available_at_front, in priv_erase_impl and
|
|
467
|
+
// priv_erase_range). This favors reuse of cache-hot slots
|
|
468
|
+
// the program just vacated and keeps partials ahead of
|
|
469
|
+
// empties.
|
|
470
|
+
//
|
|
471
|
+
// Maintenance points:
|
|
472
|
+
// * link_available_at_back(pb) on block creation and on every
|
|
473
|
+
// non-empty->empty transition (priv_erase_impl,
|
|
474
|
+
// priv_erase_range, priv_compact_*), preceded by
|
|
475
|
+
// unlink_available(pb) when the block was already partial so
|
|
476
|
+
// it is relocated to the back rather than duplicated.
|
|
477
|
+
// * link_available_at_front(pb) on the full->partial
|
|
478
|
+
// transition (priv_erase_impl, priv_erase_range when a
|
|
479
|
+
// block had been saturated).
|
|
480
|
+
// * unlink_available(pb) on the partial->full transition
|
|
481
|
+
// (emplace / priv_insert_range_copy when `mask + 1 == 0`).
|
|
482
|
+
// * priv_reset's first sweep walks `blist.header()->next_available`
|
|
483
|
+
// to destroy empty and partial blocks and free their data.
|
|
484
|
+
//
|
|
485
|
+
//Note that a partial block is on BOTH lists at once; its four
|
|
486
|
+
//pointers are independent (the available chain may skip past full
|
|
487
|
+
//blocks that the main chain visits, and vice versa).
|
|
488
|
+
pointer prev_available;
|
|
489
|
+
pointer next_available;
|
|
490
|
+
pointer prev;
|
|
491
|
+
pointer next;
|
|
492
|
+
mask_type mask;
|
|
493
|
+
private:
|
|
494
|
+
BOOST_MOVABLE_BUT_NOT_COPYABLE(block_base)
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
template<class ValuePointer, bool StoreDataInBlock>
|
|
498
|
+
struct block
|
|
499
|
+
: block_base<typename pointer_rebind<ValuePointer, void>::type>
|
|
500
|
+
{
|
|
501
|
+
typedef block_base<typename pointer_rebind<ValuePointer, void>::type> block_base_type;
|
|
502
|
+
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type value_type;
|
|
503
|
+
typedef typename pointer_rebind<ValuePointer, block>::type pointer;
|
|
504
|
+
|
|
505
|
+
BOOST_CONTAINER_FORCEINLINE ValuePointer data() BOOST_NOEXCEPT { return data_; }
|
|
506
|
+
BOOST_CONTAINER_FORCEINLINE void set_data_null() BOOST_NOEXCEPT { data_ = ValuePointer(); }
|
|
507
|
+
|
|
508
|
+
block()
|
|
509
|
+
: block_base_type(), data_()
|
|
510
|
+
{}
|
|
511
|
+
|
|
512
|
+
block(BOOST_RV_REF(block) x) BOOST_NOEXCEPT
|
|
513
|
+
: block_base_type(BOOST_MOVE_BASE(block_base_type, x)), data_()
|
|
514
|
+
{}
|
|
515
|
+
|
|
516
|
+
block& operator=(BOOST_RV_REF(block) x) BOOST_NOEXCEPT
|
|
517
|
+
{
|
|
518
|
+
this->block_base_type::operator=(boost::move(x));
|
|
519
|
+
return *this;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
BOOST_CONTAINER_FORCEINLINE static pointer
|
|
523
|
+
static_cast_block_pointer(typename block_base_type::pointer pbb) BOOST_NOEXCEPT
|
|
524
|
+
{
|
|
525
|
+
return boost::intrusive::pointer_traits<pointer>::pointer_to(
|
|
526
|
+
static_cast<block&>(*pbb));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
ValuePointer data_;
|
|
530
|
+
private:
|
|
531
|
+
BOOST_MOVABLE_BUT_NOT_COPYABLE(block)
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
template<class ValuePointer>
|
|
535
|
+
struct block<ValuePointer, true>
|
|
536
|
+
: block_base<typename pointer_rebind<ValuePointer, void>::type>
|
|
537
|
+
{
|
|
538
|
+
typedef block_base<typename pointer_rebind<ValuePointer, void>::type> block_base_type;
|
|
539
|
+
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type value_type;
|
|
540
|
+
typedef typename pointer_rebind<ValuePointer, block>::type pointer;
|
|
541
|
+
|
|
542
|
+
BOOST_CONTAINER_FORCEINLINE ValuePointer data() BOOST_NOEXCEPT { return static_cast<ValuePointer>(static_cast<void*>(&data_stor)); }
|
|
543
|
+
BOOST_CONTAINER_FORCEINLINE void set_data_null() BOOST_NOEXCEPT {}
|
|
544
|
+
|
|
545
|
+
block()
|
|
546
|
+
: block_base_type()
|
|
547
|
+
{}
|
|
548
|
+
|
|
549
|
+
block(BOOST_RV_REF(block) x) BOOST_NOEXCEPT
|
|
550
|
+
: block_base_type(BOOST_MOVE_BASE(block_base_type, x))
|
|
551
|
+
{}
|
|
552
|
+
|
|
553
|
+
block& operator=(BOOST_RV_REF(block) x) BOOST_NOEXCEPT
|
|
554
|
+
{
|
|
555
|
+
this->block_base_type::operator=(boost::move(x));
|
|
556
|
+
return *this;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
BOOST_CONTAINER_FORCEINLINE static pointer
|
|
560
|
+
static_cast_block_pointer(typename block_base_type::pointer pbb) BOOST_NOEXCEPT
|
|
561
|
+
{
|
|
562
|
+
return boost::intrusive::pointer_traits<pointer>::pointer_to(
|
|
563
|
+
static_cast<block&>(*pbb));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
typename dtl::aligned_storage<sizeof(value_type)*64u, dtl::alignment_of<value_type>::value>::type data_stor;
|
|
567
|
+
private:
|
|
568
|
+
BOOST_MOVABLE_BUT_NOT_COPYABLE(block)
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
template<class ValuePointer, bool StoreDataInBlock>
|
|
572
|
+
void swap_payload(block<ValuePointer, StoreDataInBlock>& x, block<ValuePointer, StoreDataInBlock>& y) BOOST_NOEXCEPT;
|
|
573
|
+
|
|
574
|
+
template<class ValuePointer>
|
|
575
|
+
BOOST_CONTAINER_FORCEINLINE void swap_payload(block<ValuePointer, true>& x, block<ValuePointer, true>& y) BOOST_NOEXCEPT
|
|
576
|
+
{
|
|
577
|
+
boost::adl_move_swap(x.mask, y.mask);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
template<class ValuePointer>
|
|
581
|
+
BOOST_CONTAINER_FORCEINLINE void swap_payload(block<ValuePointer, false>& x, block<ValuePointer, false>& y) BOOST_NOEXCEPT
|
|
582
|
+
{
|
|
583
|
+
boost::adl_move_swap(x.mask, y.mask);
|
|
584
|
+
boost::adl_move_swap(x.data_, y.data_);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
BOOST_CONTAINER_FORCEINLINE int first_in_mask(boost::uint64_t m)
|
|
588
|
+
{
|
|
589
|
+
return dtl::unchecked_countr_zero(m);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
BOOST_CONTAINER_FORCEINLINE int last_in_mask(boost::uint64_t m)
|
|
593
|
+
{
|
|
594
|
+
return 63 - dtl::unchecked_countl_zero(m);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
} // namespace nest_detail
|
|
598
|
+
|
|
599
|
+
//////////////////////////////////////////////
|
|
600
|
+
//
|
|
601
|
+
// nest_iterator
|
|
602
|
+
//
|
|
603
|
+
//////////////////////////////////////////////
|
|
604
|
+
|
|
605
|
+
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch>
|
|
606
|
+
class nest_iterator
|
|
607
|
+
{
|
|
608
|
+
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type element_type;
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
public:
|
|
612
|
+
typedef typename dtl::remove_const<element_type>::type value_type;
|
|
613
|
+
typedef typename boost::intrusive::pointer_traits<ValuePointer>::difference_type difference_type;
|
|
614
|
+
typedef ValuePointer pointer;
|
|
615
|
+
typedef element_type& reference;
|
|
616
|
+
typedef std::bidirectional_iterator_tag iterator_category;
|
|
617
|
+
|
|
618
|
+
struct nat
|
|
619
|
+
{
|
|
620
|
+
nat() : pbb(), n() {}
|
|
621
|
+
pointer pbb;
|
|
622
|
+
int n;
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
typedef typename nest_detail::pointer_rebind<pointer, value_type>::type maybe_nonconst_pointer;
|
|
626
|
+
|
|
627
|
+
typedef typename dtl::if_c< boost::move_detail::is_const<element_type>::value
|
|
628
|
+
, nest_iterator< maybe_nonconst_pointer, StoreDataInBlock, Prefetch >
|
|
629
|
+
, nat>::type maybe_nonconst_iterator;
|
|
630
|
+
|
|
631
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator() BOOST_NOEXCEPT
|
|
632
|
+
: pbb(), n(0)
|
|
633
|
+
{}
|
|
634
|
+
|
|
635
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator(const nest_iterator& x) BOOST_NOEXCEPT
|
|
636
|
+
: pbb(x.pbb), n(x.n)
|
|
637
|
+
{}
|
|
638
|
+
|
|
639
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator(const maybe_nonconst_iterator& x) BOOST_NOEXCEPT
|
|
640
|
+
: pbb(x.pbb), n(x.n)
|
|
641
|
+
{}
|
|
642
|
+
|
|
643
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator& operator=(const nest_iterator& x) BOOST_NOEXCEPT
|
|
644
|
+
{
|
|
645
|
+
pbb = x.pbb;
|
|
646
|
+
n = x.n;
|
|
647
|
+
return *this;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator& operator=(const maybe_nonconst_iterator& x) BOOST_NOEXCEPT
|
|
651
|
+
{
|
|
652
|
+
pbb = x.pbb;
|
|
653
|
+
n = x.n;
|
|
654
|
+
return *this;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
|
|
658
|
+
{
|
|
659
|
+
return static_cast<block_type&>(*pbb).data() + n;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
|
|
663
|
+
{
|
|
664
|
+
return static_cast<block_type&>(*pbb).data()[n];
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator& operator++() BOOST_NOEXCEPT
|
|
668
|
+
{
|
|
669
|
+
mask_type mask = pbb->mask & (full << 1 << n);
|
|
670
|
+
if(BOOST_UNLIKELY(mask == 0)) {
|
|
671
|
+
pbb = pbb->next;
|
|
672
|
+
BOOST_IF_CONSTEXPR(Prefetch) {
|
|
673
|
+
//Load next critical metadata
|
|
674
|
+
block_base_type& pbn = static_cast<block_base_type&>(*pbb->next);
|
|
675
|
+
//Prefetch the next block's metadata plus the next metadata
|
|
676
|
+
BOOST_CONTAINER_NEST_PREFETCH(&pbn.next->next);
|
|
677
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(&pbn);
|
|
678
|
+
}
|
|
679
|
+
mask = pbb->mask;
|
|
680
|
+
}
|
|
681
|
+
n = nest_detail::first_in_mask(mask);
|
|
682
|
+
return *this;
|
|
683
|
+
}
|
|
684
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator operator++(int) BOOST_NOEXCEPT
|
|
685
|
+
{
|
|
686
|
+
nest_iterator tmp(*this);
|
|
687
|
+
this->operator++();
|
|
688
|
+
return tmp;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator& operator--() BOOST_NOEXCEPT
|
|
692
|
+
{
|
|
693
|
+
mask_type mask = pbb->mask & (full >> 1 >> (((int)N - 1) - n));
|
|
694
|
+
if (BOOST_UNLIKELY(mask == 0)) {
|
|
695
|
+
pbb = pbb->prev;
|
|
696
|
+
BOOST_IF_CONSTEXPR(Prefetch) {
|
|
697
|
+
//Load previous data
|
|
698
|
+
block_base_type& pbn = static_cast<block_base_type&>(*pbb->prev);
|
|
699
|
+
BOOST_CONTAINER_NEST_PREFETCH(&pbn.prev->prev);
|
|
700
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(&pbn);
|
|
701
|
+
}
|
|
702
|
+
mask = pbb->mask;
|
|
703
|
+
}
|
|
704
|
+
n = nest_detail::last_in_mask(mask);
|
|
705
|
+
return *this;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator operator--(int) BOOST_NOEXCEPT
|
|
709
|
+
{
|
|
710
|
+
nest_iterator tmp(*this);
|
|
711
|
+
this->operator--();
|
|
712
|
+
return tmp;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const nest_iterator& x, const nest_iterator& y) BOOST_NOEXCEPT
|
|
716
|
+
{
|
|
717
|
+
return x.pbb == y.pbb && x.n == y.n;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const nest_iterator& x, const nest_iterator& y) BOOST_NOEXCEPT
|
|
721
|
+
{
|
|
722
|
+
return !(x == y);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
private:
|
|
726
|
+
template<class, bool, bool> friend class nest_iterator;
|
|
727
|
+
template<class, class, class> friend class boost::container::nest;
|
|
728
|
+
template<class VP, bool SDIB, bool Pf, class FF>
|
|
729
|
+
friend std::pair< nest_iterator<VP, SDIB, Pf>, FF >
|
|
730
|
+
for_each_while
|
|
731
|
+
( nest_iterator<VP, SDIB, Pf>
|
|
732
|
+
, nest_iterator<VP, SDIB, Pf>
|
|
733
|
+
, FF);
|
|
734
|
+
|
|
735
|
+
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
|
|
736
|
+
typedef nest_detail::block_base<void_pointer> block_base_type;
|
|
737
|
+
typedef typename nest_detail::pointer_rebind
|
|
738
|
+
<ValuePointer, block_base_type>::type block_base_pointer;
|
|
739
|
+
typedef typename nest_detail::pointer_rebind
|
|
740
|
+
<ValuePointer, const block_base_type>::type const_block_base_pointer;
|
|
741
|
+
typedef typename nest_detail::pointer_rebind
|
|
742
|
+
<ValuePointer, value_type>::type nonconst_pointer;
|
|
743
|
+
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
|
|
744
|
+
typedef typename block_base_type::mask_type mask_type;
|
|
745
|
+
|
|
746
|
+
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
|
|
747
|
+
BOOST_STATIC_CONSTEXPR mask_type full = block_base_type::full;
|
|
748
|
+
BOOST_STATIC_CONSTEXPR bool prefetch_enabled = Prefetch;
|
|
749
|
+
|
|
750
|
+
BOOST_CONTAINER_FORCEINLINE nest_iterator(const_block_base_pointer pbb_, int n_) BOOST_NOEXCEPT
|
|
751
|
+
: pbb(const_cast_block_base_pointer(pbb_)), n(n_)
|
|
752
|
+
{}
|
|
753
|
+
|
|
754
|
+
BOOST_CONTAINER_FORCEINLINE static block_base_pointer
|
|
755
|
+
const_cast_block_base_pointer(const_block_base_pointer pbb_) BOOST_NOEXCEPT
|
|
756
|
+
{
|
|
757
|
+
return block_base_type::pointer_to(const_cast<block_base_type&>(*pbb_));
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
block_base_pointer pbb;
|
|
761
|
+
int n;
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
namespace nest_detail {
|
|
765
|
+
|
|
766
|
+
//////////////////////////////////////////////
|
|
767
|
+
//
|
|
768
|
+
// sort_iterator
|
|
769
|
+
//
|
|
770
|
+
//////////////////////////////////////////////
|
|
771
|
+
|
|
772
|
+
template<class T, std::size_t N>
|
|
773
|
+
struct sort_iterator
|
|
774
|
+
{
|
|
775
|
+
typedef T value_type;
|
|
776
|
+
typedef std::ptrdiff_t difference_type;
|
|
777
|
+
typedef T* pointer;
|
|
778
|
+
typedef T& reference;
|
|
779
|
+
typedef std::random_access_iterator_tag iterator_category;
|
|
780
|
+
|
|
781
|
+
sort_iterator(T** pp_, difference_type index_)
|
|
782
|
+
: pp(pp_), index(index_)
|
|
783
|
+
{}
|
|
784
|
+
|
|
785
|
+
pointer operator->() const BOOST_NOEXCEPT
|
|
786
|
+
{ return pp[(std::size_t)index / N] + ((std::size_t)index % N); }
|
|
787
|
+
|
|
788
|
+
reference operator*() const BOOST_NOEXCEPT
|
|
789
|
+
{ return *operator->(); }
|
|
790
|
+
|
|
791
|
+
sort_iterator& operator++() BOOST_NOEXCEPT { ++index; return *this; }
|
|
792
|
+
sort_iterator operator++(int) BOOST_NOEXCEPT { sort_iterator t(*this); ++index; return t; }
|
|
793
|
+
sort_iterator& operator--() BOOST_NOEXCEPT { --index; return *this; }
|
|
794
|
+
sort_iterator operator--(int) BOOST_NOEXCEPT { sort_iterator t(*this); --index; return t; }
|
|
795
|
+
|
|
796
|
+
friend difference_type
|
|
797
|
+
operator-(const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
798
|
+
{ return x.index - y.index; }
|
|
799
|
+
|
|
800
|
+
sort_iterator& operator+=(difference_type d) BOOST_NOEXCEPT
|
|
801
|
+
{ index += d; return *this; }
|
|
802
|
+
|
|
803
|
+
friend sort_iterator
|
|
804
|
+
operator+(const sort_iterator& x, difference_type d) BOOST_NOEXCEPT
|
|
805
|
+
{ return sort_iterator(x.pp, x.index + d); }
|
|
806
|
+
|
|
807
|
+
friend sort_iterator
|
|
808
|
+
operator+(difference_type d, const sort_iterator& x) BOOST_NOEXCEPT
|
|
809
|
+
{ return sort_iterator(x.pp, d + x.index); }
|
|
810
|
+
|
|
811
|
+
sort_iterator& operator-=(difference_type d) BOOST_NOEXCEPT
|
|
812
|
+
{ index -= d; return *this; }
|
|
813
|
+
|
|
814
|
+
friend sort_iterator
|
|
815
|
+
operator-(const sort_iterator& x, difference_type d) BOOST_NOEXCEPT
|
|
816
|
+
{ return sort_iterator(x.pp, x.index - d); }
|
|
817
|
+
|
|
818
|
+
reference operator[](difference_type d) const BOOST_NOEXCEPT
|
|
819
|
+
{ return *(*this + d); }
|
|
820
|
+
|
|
821
|
+
friend bool operator==(const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
822
|
+
{ return x.index == y.index; }
|
|
823
|
+
friend bool operator!=(const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
824
|
+
{ return x.index != y.index; }
|
|
825
|
+
friend bool operator< (const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
826
|
+
{ return x.index < y.index; }
|
|
827
|
+
friend bool operator> (const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
828
|
+
{ return x.index > y.index; }
|
|
829
|
+
friend bool operator<=(const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
830
|
+
{ return x.index <= y.index; }
|
|
831
|
+
friend bool operator>=(const sort_iterator& x, const sort_iterator& y) BOOST_NOEXCEPT
|
|
832
|
+
{ return x.index >= y.index; }
|
|
833
|
+
|
|
834
|
+
T** pp;
|
|
835
|
+
difference_type index;
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
//////////////////////////////////////////////
|
|
839
|
+
//
|
|
840
|
+
// RAII helpers (replacing unique_ptr)
|
|
841
|
+
//
|
|
842
|
+
//////////////////////////////////////////////
|
|
843
|
+
|
|
844
|
+
template<class T, class Allocator>
|
|
845
|
+
struct buffer
|
|
846
|
+
{
|
|
847
|
+
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
|
848
|
+
|
|
849
|
+
buffer(std::size_t n_, Allocator al_) BOOST_NOEXCEPT
|
|
850
|
+
: al(al_), begin_idx(0), end_idx(0), cap(0), data(0)
|
|
851
|
+
{
|
|
852
|
+
allocate_data(n_);
|
|
853
|
+
if(data) cap = n_;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
~buffer()
|
|
857
|
+
{
|
|
858
|
+
if(data) {
|
|
859
|
+
for(; begin_idx != end_idx; ++begin_idx) {
|
|
860
|
+
alloc_traits::destroy(al, data + begin_idx);
|
|
861
|
+
}
|
|
862
|
+
deallocate_data();
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
T* begin() const BOOST_NOEXCEPT { return data + begin_idx; }
|
|
867
|
+
T* end() const BOOST_NOEXCEPT { return data + end_idx; }
|
|
868
|
+
|
|
869
|
+
void push_back_move(T& v)
|
|
870
|
+
{
|
|
871
|
+
BOOST_ASSERT(data && end_idx != cap);
|
|
872
|
+
alloc_traits::construct(al, data + end_idx, boost::move(v));
|
|
873
|
+
++end_idx;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
void erase_front() BOOST_NOEXCEPT
|
|
877
|
+
{
|
|
878
|
+
BOOST_ASSERT(data && begin_idx != end_idx);
|
|
879
|
+
alloc_traits::destroy(al, data + begin_idx);
|
|
880
|
+
++begin_idx;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
Allocator al;
|
|
884
|
+
std::size_t begin_idx;
|
|
885
|
+
std::size_t end_idx;
|
|
886
|
+
std::size_t cap;
|
|
887
|
+
T* data;
|
|
888
|
+
|
|
889
|
+
private:
|
|
890
|
+
buffer(const buffer&);
|
|
891
|
+
buffer& operator=(const buffer&);
|
|
892
|
+
|
|
893
|
+
//Portable, nothrow, (over)aligned allocation: this is the same primitive
|
|
894
|
+
//boost::container::new_allocator relies on for overalignment, so there is no
|
|
895
|
+
//need to special-case __cpp_aligned_new here. The nothrow null return lets
|
|
896
|
+
//the sort routines fall back to a leaner algorithm when this (possibly large)
|
|
897
|
+
//scratch buffer cannot be allocated.
|
|
898
|
+
void allocate_data(std::size_t m)
|
|
899
|
+
{
|
|
900
|
+
data = static_cast<T*>(dtl::aligned_allocate(dtl::alignment_of<T>::value, m * sizeof(T)));
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
void deallocate_data() { dtl::aligned_deallocate(static_cast<void*>(data)); }
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
// RAII wrapper for raw memory (replaces unique_ptr with nodtor_deleter)
|
|
907
|
+
struct raw_memory_holder
|
|
908
|
+
{
|
|
909
|
+
explicit raw_memory_holder(void* p_) BOOST_NOEXCEPT : p(p_) {}
|
|
910
|
+
~raw_memory_holder() { if(p) ::operator delete(p); }
|
|
911
|
+
void release() BOOST_NOEXCEPT { p = 0; }
|
|
912
|
+
void* get() const BOOST_NOEXCEPT { return p; }
|
|
913
|
+
void* p;
|
|
914
|
+
private:
|
|
915
|
+
raw_memory_holder(const raw_memory_holder&);
|
|
916
|
+
raw_memory_holder& operator=(const raw_memory_holder&);
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
//////////////////////////////////////////////
|
|
920
|
+
//
|
|
921
|
+
// allocator propagation helpers
|
|
922
|
+
//
|
|
923
|
+
//////////////////////////////////////////////
|
|
924
|
+
|
|
925
|
+
template<class T>
|
|
926
|
+
void copy_assign_if(dtl::true_type, T& x, const T& y) { x = y; }
|
|
927
|
+
|
|
928
|
+
template<class T>
|
|
929
|
+
void copy_assign_if(dtl::false_type, T&, const T&) {}
|
|
930
|
+
|
|
931
|
+
template<class T>
|
|
932
|
+
void move_assign_if(dtl::true_type, T& x, T& y) { x = boost::move(y); }
|
|
933
|
+
|
|
934
|
+
template<class T>
|
|
935
|
+
void move_assign_if(dtl::false_type, T&, T&) {}
|
|
936
|
+
|
|
937
|
+
//////////////////////////////////////////////
|
|
938
|
+
//
|
|
939
|
+
// block_typedefs
|
|
940
|
+
//
|
|
941
|
+
//////////////////////////////////////////////
|
|
942
|
+
|
|
943
|
+
template<class ValueAllocator, bool StoreDataInBlock>
|
|
944
|
+
struct block_typedefs
|
|
945
|
+
{
|
|
946
|
+
typedef boost::container::allocator_traits<ValueAllocator> val_alloc_traits;
|
|
947
|
+
typedef typename val_alloc_traits::pointer value_pointer;
|
|
948
|
+
typedef typename pointer_rebind<value_pointer, void>::type void_pointer;
|
|
949
|
+
|
|
950
|
+
typedef nest_detail::block_base<void_pointer> block_base_t;
|
|
951
|
+
typedef typename pointer_rebind<
|
|
952
|
+
value_pointer, block_base_t>::type block_base_pointer;
|
|
953
|
+
typedef typename pointer_rebind<
|
|
954
|
+
value_pointer, const block_base_t>::type const_block_base_pointer;
|
|
955
|
+
|
|
956
|
+
typedef nest_detail::block<value_pointer, StoreDataInBlock> block_type;
|
|
957
|
+
typedef typename pointer_rebind<
|
|
958
|
+
value_pointer, block_type>::type block_pointer;
|
|
959
|
+
|
|
960
|
+
typedef typename val_alloc_traits::
|
|
961
|
+
template portable_rebind_alloc<block_type>::type block_allocator;
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
//////////////////////////////////////////////
|
|
965
|
+
//
|
|
966
|
+
// predicate adaptor for unique()
|
|
967
|
+
//
|
|
968
|
+
//////////////////////////////////////////////
|
|
969
|
+
|
|
970
|
+
template<class T, class BinaryPredicate>
|
|
971
|
+
struct unique_pred_adaptor
|
|
972
|
+
{
|
|
973
|
+
const T* value_ptr;
|
|
974
|
+
BinaryPredicate& pred;
|
|
975
|
+
unique_pred_adaptor(const T* v, BinaryPredicate& p) : value_ptr(v), pred(p) {}
|
|
976
|
+
bool operator()(const T& x) const { return pred(x, *value_ptr); }
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
//////////////////////////////////////////////
|
|
980
|
+
//
|
|
981
|
+
// sort_proxy_comparator
|
|
982
|
+
//
|
|
983
|
+
//////////////////////////////////////////////
|
|
984
|
+
|
|
985
|
+
template<class T, class Compare>
|
|
986
|
+
struct sort_proxy_comparator
|
|
987
|
+
{
|
|
988
|
+
Compare& comp;
|
|
989
|
+
explicit sort_proxy_comparator(Compare& c) : comp(c) {}
|
|
990
|
+
|
|
991
|
+
template<class SortProxy>
|
|
992
|
+
bool operator()(const SortProxy& x, const SortProxy& y) const
|
|
993
|
+
{
|
|
994
|
+
return comp(
|
|
995
|
+
const_cast<const T&>(*x.p),
|
|
996
|
+
const_cast<const T&>(*y.p));
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
//////////////////////////////////////////////
|
|
1001
|
+
//
|
|
1002
|
+
// for_each adaptor: wraps a unary function so it can be used as the
|
|
1003
|
+
// predicate of for_each_while (always returns true).
|
|
1004
|
+
//
|
|
1005
|
+
//////////////////////////////////////////////
|
|
1006
|
+
|
|
1007
|
+
template<class F, class T>
|
|
1008
|
+
struct for_each_adaptor
|
|
1009
|
+
{
|
|
1010
|
+
F& f;
|
|
1011
|
+
BOOST_CONTAINER_FORCEINLINE explicit for_each_adaptor(F& f_) : f(f_) {}
|
|
1012
|
+
BOOST_CONTAINER_FORCEINLINE bool operator()(T& x) const { f(x); return true; }
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
//////////////////////////////////////////////
|
|
1016
|
+
//
|
|
1017
|
+
// ref_predicate_adaptor: holds the wrapped predicate by reference so its
|
|
1018
|
+
// state is preserved when the adaptor is copied around by the visiting
|
|
1019
|
+
// machinery.
|
|
1020
|
+
//
|
|
1021
|
+
//////////////////////////////////////////////
|
|
1022
|
+
|
|
1023
|
+
template<class F, class T>
|
|
1024
|
+
struct ref_predicate_adaptor
|
|
1025
|
+
{
|
|
1026
|
+
F& f;
|
|
1027
|
+
BOOST_CONTAINER_FORCEINLINE explicit ref_predicate_adaptor(F& f_) : f(f_) {}
|
|
1028
|
+
BOOST_CONTAINER_FORCEINLINE bool operator()(T& x) const { return f(x); }
|
|
1029
|
+
};
|
|
1030
|
+
|
|
1031
|
+
} // namespace nest_detail
|
|
1032
|
+
|
|
1033
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1034
|
+
|
|
1035
|
+
template<class Options>
|
|
1036
|
+
struct get_nest_opt
|
|
1037
|
+
{
|
|
1038
|
+
typedef nest_opt<
|
|
1039
|
+
Options::store_data_in_block,
|
|
1040
|
+
Options::prefetch> type;
|
|
1041
|
+
};
|
|
1042
|
+
|
|
1043
|
+
template<>
|
|
1044
|
+
struct get_nest_opt<void>
|
|
1045
|
+
{
|
|
1046
|
+
typedef nest_null_opt type;
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
template<bool B, bool P>
|
|
1050
|
+
struct get_nest_opt<nest_opt<B, P> >
|
|
1051
|
+
{
|
|
1052
|
+
typedef nest_opt<B, P> type;
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1056
|
+
|
|
1057
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
1058
|
+
//
|
|
1059
|
+
// nest
|
|
1060
|
+
//
|
|
1061
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
1062
|
+
|
|
1063
|
+
//! A nest is a node-like container with a fixed block size of 64 elements
|
|
1064
|
+
//! and bitmask-based slot management. It provides stable iterators and
|
|
1065
|
+
//! efficient insertion and erasure operations in constant time.
|
|
1066
|
+
//!
|
|
1067
|
+
//! \tparam T The type of object stored in the nest
|
|
1068
|
+
//! \tparam Allocator The allocator used for all internal memory management, use void
|
|
1069
|
+
//! for the default allocator
|
|
1070
|
+
//! \tparam Options A type produced from \c boost::container::nest_options (e.g. \c store_data_in_block).
|
|
1071
|
+
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1072
|
+
template <class T, class Allocator = void, class Options = void>
|
|
1073
|
+
#else
|
|
1074
|
+
template <class T, class Allocator, class Options>
|
|
1075
|
+
#endif
|
|
1076
|
+
class nest
|
|
1077
|
+
//EBO: nest derives directly from its (block) allocator
|
|
1078
|
+
: private nest_detail::block_typedefs<
|
|
1079
|
+
typename real_allocator<T, Allocator>::type
|
|
1080
|
+
, get_nest_opt<Options>::type::store_data_in_block
|
|
1081
|
+
>::block_allocator
|
|
1082
|
+
{
|
|
1083
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1084
|
+
typedef typename real_allocator<T, Allocator>::type ValueAllocator;
|
|
1085
|
+
typedef typename get_nest_opt<Options>::type options_type;
|
|
1086
|
+
BOOST_STATIC_CONSTEXPR bool store_data_in_block = options_type::store_data_in_block;
|
|
1087
|
+
BOOST_STATIC_CONSTEXPR bool prefetch_enabled = options_type::prefetch;
|
|
1088
|
+
typedef boost::container::allocator_traits<ValueAllocator> allocator_traits_type;
|
|
1089
|
+
typedef nest_detail::block_typedefs<ValueAllocator, store_data_in_block> btd;
|
|
1090
|
+
typedef typename btd::block_base_t block_base;
|
|
1091
|
+
typedef typename btd::block_base_pointer block_base_pointer;
|
|
1092
|
+
typedef typename btd::const_block_base_pointer const_block_base_pointer;
|
|
1093
|
+
typedef typename btd::block_type block_type;
|
|
1094
|
+
typedef typename btd::block_pointer block_pointer;
|
|
1095
|
+
typedef typename btd::block_allocator block_allocator;
|
|
1096
|
+
typedef block_allocator allocator_base;
|
|
1097
|
+
typedef typename block_base::mask_type mask_type;
|
|
1098
|
+
typedef boost::container::allocator_traits<block_allocator> block_alloc_traits;
|
|
1099
|
+
|
|
1100
|
+
BOOST_STATIC_CONSTEXPR std::size_t N = block_base::N;
|
|
1101
|
+
BOOST_STATIC_CONSTEXPR mask_type full = block_base::full;
|
|
1102
|
+
|
|
1103
|
+
BOOST_COPYABLE_AND_MOVABLE(nest)
|
|
1104
|
+
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
1105
|
+
|
|
1106
|
+
public:
|
|
1107
|
+
//////////////////////////////////////////////
|
|
1108
|
+
//
|
|
1109
|
+
// types
|
|
1110
|
+
//
|
|
1111
|
+
//////////////////////////////////////////////
|
|
1112
|
+
|
|
1113
|
+
typedef T value_type;
|
|
1114
|
+
typedef ValueAllocator allocator_type;
|
|
1115
|
+
typedef typename allocator_traits_type::pointer pointer;
|
|
1116
|
+
typedef typename allocator_traits_type::const_pointer const_pointer;
|
|
1117
|
+
typedef T& reference;
|
|
1118
|
+
typedef const T& const_reference;
|
|
1119
|
+
typedef typename allocator_traits_type::size_type size_type;
|
|
1120
|
+
typedef typename allocator_traits_type::difference_type difference_type;
|
|
1121
|
+
typedef BOOST_CONTAINER_IMPDEF(nest_iterator<pointer BOOST_MOVE_I store_data_in_block BOOST_MOVE_I prefetch_enabled>) iterator;
|
|
1122
|
+
typedef BOOST_CONTAINER_IMPDEF(nest_iterator<const_pointer BOOST_MOVE_I store_data_in_block BOOST_MOVE_I prefetch_enabled>) const_iterator;
|
|
1123
|
+
typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
|
|
1124
|
+
typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
|
|
1125
|
+
|
|
1126
|
+
//////////////////////////////////////////////
|
|
1127
|
+
//
|
|
1128
|
+
// construct/copy/destroy
|
|
1129
|
+
//
|
|
1130
|
+
//////////////////////////////////////////////
|
|
1131
|
+
|
|
1132
|
+
//! <b>Effects</b>: Default constructs a nest.
|
|
1133
|
+
//!
|
|
1134
|
+
//! <b>Throws</b>: If allocator_type's default constructor throws.
|
|
1135
|
+
//!
|
|
1136
|
+
//! <b>Complexity</b>: Constant.
|
|
1137
|
+
nest() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<ValueAllocator>::value)
|
|
1138
|
+
: allocator_base()
|
|
1139
|
+
, blist()
|
|
1140
|
+
, num_blocks(0)
|
|
1141
|
+
, size_(0)
|
|
1142
|
+
{}
|
|
1143
|
+
|
|
1144
|
+
//! <b>Effects</b>: Constructs a nest taking the allocator as parameter.
|
|
1145
|
+
//!
|
|
1146
|
+
//! <b>Throws</b>: Nothing.
|
|
1147
|
+
//!
|
|
1148
|
+
//! <b>Complexity</b>: Constant.
|
|
1149
|
+
explicit nest(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
|
|
1150
|
+
: allocator_base(block_allocator(a))
|
|
1151
|
+
, blist()
|
|
1152
|
+
, num_blocks(0)
|
|
1153
|
+
, size_(0)
|
|
1154
|
+
{}
|
|
1155
|
+
|
|
1156
|
+
//! <b>Effects</b>: Constructs a nest and inserts n value-initialized elements.
|
|
1157
|
+
//!
|
|
1158
|
+
//! <b>Throws</b>: If allocator_type's default constructor
|
|
1159
|
+
//! throws or T's default constructor throws.
|
|
1160
|
+
//!
|
|
1161
|
+
//! <b>Complexity</b>: Linear to n.
|
|
1162
|
+
explicit nest(size_type n, const allocator_type& a = allocator_type())
|
|
1163
|
+
: allocator_base(block_allocator(a))
|
|
1164
|
+
, blist()
|
|
1165
|
+
, num_blocks(0)
|
|
1166
|
+
, size_(0)
|
|
1167
|
+
{
|
|
1168
|
+
priv_insert_n_default(n);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
//! <b>Effects</b>: Constructs a nest and inserts n copies of x.
|
|
1172
|
+
//!
|
|
1173
|
+
//! <b>Throws</b>: If allocator_type's default constructor
|
|
1174
|
+
//! throws or T's copy constructor throws.
|
|
1175
|
+
//!
|
|
1176
|
+
//! <b>Complexity</b>: Linear to n.
|
|
1177
|
+
nest(size_type n, const T& x, const allocator_type& a = allocator_type())
|
|
1178
|
+
: allocator_base(block_allocator(a))
|
|
1179
|
+
, blist()
|
|
1180
|
+
, num_blocks(0)
|
|
1181
|
+
, size_(0)
|
|
1182
|
+
{
|
|
1183
|
+
insert(n, x);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
//! <b>Effects</b>: Constructs a nest and inserts a copy of [first, last).
|
|
1187
|
+
//!
|
|
1188
|
+
//! <b>Throws</b>: If allocator_type's default constructor
|
|
1189
|
+
//! throws or T's constructor taking a dereferenced InpIt throws.
|
|
1190
|
+
//!
|
|
1191
|
+
//! <b>Complexity</b>: Linear to the range [first, last).
|
|
1192
|
+
template<class InpIt>
|
|
1193
|
+
nest(InpIt first, InpIt last
|
|
1194
|
+
,const allocator_type& a = allocator_type()
|
|
1195
|
+
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
1196
|
+
, typename dtl::disable_if_convertible<InpIt, size_type>::type* = 0
|
|
1197
|
+
#endif
|
|
1198
|
+
)
|
|
1199
|
+
: allocator_base(block_allocator(a))
|
|
1200
|
+
, blist()
|
|
1201
|
+
, num_blocks(0)
|
|
1202
|
+
, size_(0)
|
|
1203
|
+
{
|
|
1204
|
+
insert(first, last);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
//! <b>Effects</b>: Copy constructs a nest.
|
|
1208
|
+
//!
|
|
1209
|
+
//! <b>Postcondition</b>: x == *this.
|
|
1210
|
+
//!
|
|
1211
|
+
//! <b>Throws</b>: If allocator_type's copy constructor throws.
|
|
1212
|
+
//!
|
|
1213
|
+
//! <b>Complexity</b>: Linear to the elements x contains.
|
|
1214
|
+
nest(const nest& x)
|
|
1215
|
+
: allocator_base(block_allocator(
|
|
1216
|
+
allocator_traits_type::select_on_container_copy_construction(x.priv_alloc())))
|
|
1217
|
+
, blist()
|
|
1218
|
+
, num_blocks(0)
|
|
1219
|
+
, size_(0)
|
|
1220
|
+
{
|
|
1221
|
+
insert(x.begin(), x.end());
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
//! <b>Effects</b>: Move constructor. Moves x's resources to *this.
|
|
1225
|
+
//!
|
|
1226
|
+
//! <b>Throws</b>: Nothing.
|
|
1227
|
+
//!
|
|
1228
|
+
//! <b>Complexity</b>: Constant.
|
|
1229
|
+
nest(BOOST_RV_REF(nest) x) BOOST_NOEXCEPT_OR_NOTHROW
|
|
1230
|
+
: allocator_base(boost::move(x.al()))
|
|
1231
|
+
, blist(boost::move(x.blist))
|
|
1232
|
+
, num_blocks(x.num_blocks)
|
|
1233
|
+
, size_(x.size_)
|
|
1234
|
+
{
|
|
1235
|
+
x.num_blocks = 0;
|
|
1236
|
+
x.size_ = 0;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
//! <b>Effects</b>: Copy constructs a nest using the specified allocator.
|
|
1240
|
+
//!
|
|
1241
|
+
//! <b>Postcondition</b>: x == *this.
|
|
1242
|
+
//!
|
|
1243
|
+
//! <b>Throws</b>: If allocator_type's copy constructor throws.
|
|
1244
|
+
//!
|
|
1245
|
+
//! <b>Complexity</b>: Linear to the elements x contains.
|
|
1246
|
+
nest(const nest& x, const BOOST_CONTAINER_DOC1ST(allocator_type, typename dtl::type_identity<allocator_type>::type)& a)
|
|
1247
|
+
: allocator_base(block_allocator(a))
|
|
1248
|
+
, blist()
|
|
1249
|
+
, num_blocks(0)
|
|
1250
|
+
, size_(0)
|
|
1251
|
+
{
|
|
1252
|
+
insert(x.begin(), x.end());
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
//! <b>Effects</b>: Move constructor using the specified allocator.
|
|
1256
|
+
//! Moves x's resources to *this.
|
|
1257
|
+
//!
|
|
1258
|
+
//! <b>Throws</b>: If allocation or value_type's copy constructor throws.
|
|
1259
|
+
//!
|
|
1260
|
+
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
|
|
1261
|
+
nest(BOOST_RV_REF(nest) x, const BOOST_CONTAINER_DOC1ST(allocator_type, typename dtl::type_identity<allocator_type>::type)& a)
|
|
1262
|
+
: allocator_base(block_allocator(a))
|
|
1263
|
+
, blist()
|
|
1264
|
+
, num_blocks(0)
|
|
1265
|
+
, size_(0)
|
|
1266
|
+
{
|
|
1267
|
+
if(al() == x.al()){
|
|
1268
|
+
blist = boost::move(x.blist);
|
|
1269
|
+
num_blocks = x.num_blocks;
|
|
1270
|
+
size_ = x.size_;
|
|
1271
|
+
x.num_blocks = 0;
|
|
1272
|
+
x.size_ = 0;
|
|
1273
|
+
}
|
|
1274
|
+
else{
|
|
1275
|
+
priv_insert_range_move(x.begin(), x.end());
|
|
1276
|
+
x.priv_reset();
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
1281
|
+
//! <b>Effects</b>: Constructs a nest and inserts elements from il.
|
|
1282
|
+
//!
|
|
1283
|
+
//! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
|
1284
|
+
nest(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
|
|
1285
|
+
: allocator_base(block_allocator(a))
|
|
1286
|
+
, blist()
|
|
1287
|
+
, num_blocks(0)
|
|
1288
|
+
, size_(0)
|
|
1289
|
+
{
|
|
1290
|
+
insert(il.begin(), il.end());
|
|
1291
|
+
}
|
|
1292
|
+
#endif
|
|
1293
|
+
|
|
1294
|
+
//! <b>Effects</b>: Destroys the nest. All stored values are destroyed
|
|
1295
|
+
//! and used memory is deallocated.
|
|
1296
|
+
//!
|
|
1297
|
+
//! <b>Throws</b>: Nothing.
|
|
1298
|
+
//!
|
|
1299
|
+
//! <b>Complexity</b>: Linear to the number of elements.
|
|
1300
|
+
~nest() BOOST_NOEXCEPT_OR_NOTHROW
|
|
1301
|
+
{
|
|
1302
|
+
priv_reset();
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
//! <b>Effects</b>: Makes *this contain the same elements as x.
|
|
1306
|
+
//!
|
|
1307
|
+
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
|
|
1308
|
+
//!
|
|
1309
|
+
//! <b>Complexity</b>: Linear to the number of elements in x.
|
|
1310
|
+
nest& operator=(BOOST_COPY_ASSIGN_REF(nest) x)
|
|
1311
|
+
{
|
|
1312
|
+
if (BOOST_LIKELY(this != &x)) {
|
|
1313
|
+
dtl::bool_<allocator_traits_type::
|
|
1314
|
+
propagate_on_container_copy_assignment::value> pocca;
|
|
1315
|
+
if(priv_alloc() != x.priv_alloc() && pocca.value) {
|
|
1316
|
+
priv_reset();
|
|
1317
|
+
nest_detail::copy_assign_if(pocca, al(), x.al());
|
|
1318
|
+
insert(x.begin(), x.end());
|
|
1319
|
+
}
|
|
1320
|
+
else{
|
|
1321
|
+
nest_detail::copy_assign_if(pocca, al(), x.al());
|
|
1322
|
+
assign(x.begin(), x.end());
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return *this;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
//! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
|
|
1329
|
+
//!
|
|
1330
|
+
//! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
|
|
1331
|
+
//! is false and (allocation throws or value_type's move constructor throws).
|
|
1332
|
+
//!
|
|
1333
|
+
//! <b>Complexity</b>: Constant if allocator_traits_type::
|
|
1334
|
+
//! propagate_on_container_move_assignment is true or
|
|
1335
|
+
//! this->get_allocator() == x.get_allocator(). Linear otherwise.
|
|
1336
|
+
nest& operator=(BOOST_RV_REF(nest) x)
|
|
1337
|
+
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|
|
1338
|
+
|| allocator_traits_type::is_always_equal::value)
|
|
1339
|
+
{
|
|
1340
|
+
if (BOOST_LIKELY(this != &x)) {
|
|
1341
|
+
BOOST_STATIC_CONSTEXPR bool can_steal =
|
|
1342
|
+
allocator_traits_type::propagate_on_container_move_assignment::value ||
|
|
1343
|
+
allocator_traits_type::is_always_equal::value;
|
|
1344
|
+
priv_move_assign(x, dtl::bool_<can_steal>());
|
|
1345
|
+
}
|
|
1346
|
+
return *this;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
1350
|
+
//! <b>Effects</b>: Assigns the elements of il to *this.
|
|
1351
|
+
//!
|
|
1352
|
+
//! <b>Complexity</b>: Linear.
|
|
1353
|
+
nest& operator=(std::initializer_list<value_type> il)
|
|
1354
|
+
{
|
|
1355
|
+
assign(il.begin(), il.end());
|
|
1356
|
+
return *this;
|
|
1357
|
+
}
|
|
1358
|
+
#endif
|
|
1359
|
+
|
|
1360
|
+
//! <b>Effects</b>: Assigns [first, last) to *this.
|
|
1361
|
+
//!
|
|
1362
|
+
//! <b>Complexity</b>: Linear.
|
|
1363
|
+
template<class InpIt>
|
|
1364
|
+
void assign(InpIt first, InpIt last
|
|
1365
|
+
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
1366
|
+
, typename dtl::disable_if_convertible<InpIt, size_type>::type* = 0
|
|
1367
|
+
#endif
|
|
1368
|
+
)
|
|
1369
|
+
{
|
|
1370
|
+
priv_range_assign(first, last);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
//! <b>Effects</b>: Assigns n copies of val to *this.
|
|
1374
|
+
//!
|
|
1375
|
+
//! <b>Complexity</b>: Linear.
|
|
1376
|
+
void assign(size_type n, const T& val)
|
|
1377
|
+
{
|
|
1378
|
+
priv_assign_n(n, val);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
1382
|
+
//! <b>Effects</b>: Assigns the elements of il to *this.
|
|
1383
|
+
//!
|
|
1384
|
+
//! <b>Complexity</b>: Linear.
|
|
1385
|
+
void assign(std::initializer_list<value_type> il)
|
|
1386
|
+
{ assign(il.begin(), il.end()); }
|
|
1387
|
+
#endif
|
|
1388
|
+
|
|
1389
|
+
//! <b>Effects</b>: Returns a copy of the allocator.
|
|
1390
|
+
//!
|
|
1391
|
+
//! <b>Throws</b>: Nothing.
|
|
1392
|
+
//!
|
|
1393
|
+
//! <b>Complexity</b>: Constant.
|
|
1394
|
+
allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
|
1395
|
+
{ return allocator_type(al()); }
|
|
1396
|
+
|
|
1397
|
+
//////////////////////////////////////////////
|
|
1398
|
+
//
|
|
1399
|
+
// iterators
|
|
1400
|
+
//
|
|
1401
|
+
//////////////////////////////////////////////
|
|
1402
|
+
|
|
1403
|
+
//! <b>Effects</b>: Returns an iterator to the first element.
|
|
1404
|
+
//!
|
|
1405
|
+
//! <b>Complexity</b>: Constant.
|
|
1406
|
+
iterator begin() BOOST_NOEXCEPT { return ++end(); }
|
|
1407
|
+
//! <b>Effects</b>: Returns a const_iterator to the first element.
|
|
1408
|
+
const_iterator begin() const BOOST_NOEXCEPT { return ++end(); }
|
|
1409
|
+
//! <b>Effects</b>: Returns an iterator to the end.
|
|
1410
|
+
iterator end() BOOST_NOEXCEPT { return iterator(blist.header(), 0); }
|
|
1411
|
+
//! <b>Effects</b>: Returns a const_iterator to the end.
|
|
1412
|
+
const_iterator end() const BOOST_NOEXCEPT { return const_iterator(blist.header(), 0); }
|
|
1413
|
+
//! <b>Effects</b>: Returns a reverse_iterator to the rbegin.
|
|
1414
|
+
reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); }
|
|
1415
|
+
//! <b>Effects</b>: Returns a const_reverse_iterator to the rbegin.
|
|
1416
|
+
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
|
1417
|
+
//! <b>Effects</b>: Returns a reverse_iterator to the rend.
|
|
1418
|
+
reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); }
|
|
1419
|
+
//! <b>Effects</b>: Returns a const_reverse_iterator to the rend.
|
|
1420
|
+
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
|
1421
|
+
//! <b>Effects</b>: Returns a const_iterator to the first element.
|
|
1422
|
+
const_iterator cbegin() const BOOST_NOEXCEPT { return begin(); }
|
|
1423
|
+
//! <b>Effects</b>: Returns a const_iterator to the end.
|
|
1424
|
+
const_iterator cend() const BOOST_NOEXCEPT { return end(); }
|
|
1425
|
+
//! <b>Effects</b>: Returns a const_reverse_iterator to the rbegin.
|
|
1426
|
+
const_reverse_iterator crbegin()const BOOST_NOEXCEPT { return rbegin(); }
|
|
1427
|
+
//! <b>Effects</b>: Returns a const_reverse_iterator to the rend.
|
|
1428
|
+
const_reverse_iterator crend() const BOOST_NOEXCEPT { return rend(); }
|
|
1429
|
+
|
|
1430
|
+
//////////////////////////////////////////////
|
|
1431
|
+
//
|
|
1432
|
+
// capacity
|
|
1433
|
+
//
|
|
1434
|
+
//////////////////////////////////////////////
|
|
1435
|
+
|
|
1436
|
+
//! <b>Effects</b>: Returns true if the nest contains no elements.
|
|
1437
|
+
//!
|
|
1438
|
+
//! <b>Complexity</b>: Constant.
|
|
1439
|
+
bool empty() const BOOST_NOEXCEPT { return size_ == 0; }
|
|
1440
|
+
|
|
1441
|
+
//! <b>Effects</b>: Returns the number of elements.
|
|
1442
|
+
//!
|
|
1443
|
+
//! <b>Complexity</b>: Constant.
|
|
1444
|
+
size_type size() const BOOST_NOEXCEPT { return size_; }
|
|
1445
|
+
|
|
1446
|
+
//! <b>Effects</b>: Returns the maximum possible number of elements.
|
|
1447
|
+
//!
|
|
1448
|
+
//! <b>Complexity</b>: Constant.
|
|
1449
|
+
size_type max_size() const BOOST_NOEXCEPT
|
|
1450
|
+
{
|
|
1451
|
+
std::size_t bs = (std::size_t)block_alloc_traits::max_size(al()) * sizeof(block_type);
|
|
1452
|
+
allocator_type val_al(al());
|
|
1453
|
+
std::size_t vs = (std::size_t)allocator_traits_type::max_size(val_al) * sizeof(T);
|
|
1454
|
+
return (size_type)((std::min)(bs, vs) / (sizeof(block_type) + sizeof(T) * N) * N);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
//! <b>Effects</b>: Returns the total number of slots (used and unused).
|
|
1458
|
+
//!
|
|
1459
|
+
//! <b>Complexity</b>: Constant.
|
|
1460
|
+
size_type capacity() const BOOST_NOEXCEPT { return num_blocks * N; }
|
|
1461
|
+
|
|
1462
|
+
//! <b>Effects</b>: Reserves space for at least n elements.
|
|
1463
|
+
//!
|
|
1464
|
+
//! <b>Complexity</b>: Linear.
|
|
1465
|
+
void reserve(size_type n)
|
|
1466
|
+
{
|
|
1467
|
+
if(n > max_size()) {
|
|
1468
|
+
throw_length_error("Requested capacity greater than max_size()");
|
|
1469
|
+
}
|
|
1470
|
+
while(capacity() < n) (void)priv_create_new_available_block();
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
//! <b>Effects</b>: Compacts elements and removes unused blocks.
|
|
1474
|
+
//!
|
|
1475
|
+
//! <b>Complexity</b>: Linear.
|
|
1476
|
+
void shrink_to_fit()
|
|
1477
|
+
{
|
|
1478
|
+
priv_compact_noop_track();
|
|
1479
|
+
trim_capacity();
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
//! <b>Effects</b>: Releases all reserved (empty) blocks.
|
|
1483
|
+
//!
|
|
1484
|
+
//! <b>Complexity</b>: Linear on the number of reserved (empty) blocks.
|
|
1485
|
+
void trim_capacity() BOOST_NOEXCEPT { trim_capacity(0); }
|
|
1486
|
+
|
|
1487
|
+
//! <b>Effects</b>: Releases reserved blocks until capacity() <= n.
|
|
1488
|
+
//!
|
|
1489
|
+
//! <b>Complexity</b>: Linear on the number of reserved (empty) blocks released.
|
|
1490
|
+
void trim_capacity(size_type n) BOOST_NOEXCEPT
|
|
1491
|
+
{
|
|
1492
|
+
if(capacity() <= n) return;
|
|
1493
|
+
|
|
1494
|
+
//The available list is partitioned as [partial... | empty...], so all
|
|
1495
|
+
//reserved (mask == 0) blocks sit at the back. Walk it backwards from
|
|
1496
|
+
//prev_available and stop at the first non-empty block: this makes the
|
|
1497
|
+
//operation linear on the number of reserved blocks, not on the whole
|
|
1498
|
+
//available list.
|
|
1499
|
+
block_base_pointer pbb = blist.header()->prev_available;
|
|
1500
|
+
while((capacity() - n >= N) && pbb != blist.header() && pbb->mask == 0) {
|
|
1501
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
1502
|
+
pbb = pbb->prev_available;
|
|
1503
|
+
blist.unlink_available(pb);
|
|
1504
|
+
priv_delete_block(pb);
|
|
1505
|
+
--num_blocks;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
//////////////////////////////////////////////
|
|
1510
|
+
//
|
|
1511
|
+
// modifiers
|
|
1512
|
+
//
|
|
1513
|
+
//////////////////////////////////////////////
|
|
1514
|
+
|
|
1515
|
+
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
|
1516
|
+
|
|
1517
|
+
//! <b>Effects</b>: Inserts an element constructed in-place with args.
|
|
1518
|
+
//!
|
|
1519
|
+
//! <b>Returns</b>: An iterator to the inserted element.
|
|
1520
|
+
//!
|
|
1521
|
+
//! <b>Throws</b>: Nothing unless the element's constructor throws. If it does,
|
|
1522
|
+
//! the container is left in its original state (strong exception guarantee):
|
|
1523
|
+
//! any block speculatively allocated for the new element is freed.
|
|
1524
|
+
//!
|
|
1525
|
+
//! <b>Complexity</b>: Constant (amortized).
|
|
1526
|
+
template<class ...Args>
|
|
1527
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
|
|
1528
|
+
{
|
|
1529
|
+
block_base_pointer const pbb_prev = blist.next_available;
|
|
1530
|
+
int n;
|
|
1531
|
+
block_pointer const pb = priv_retrieve_available_block(n);
|
|
1532
|
+
//Store the mask on a register so that some compilers
|
|
1533
|
+
//don't reload it asumming construction can modify it.
|
|
1534
|
+
const mask_type m = pb->mask;
|
|
1535
|
+
this->priv_construct_or_restore_capacity(
|
|
1536
|
+
boost::movelib::to_raw_pointer(pb->data()) + n, pbb_prev,
|
|
1537
|
+
boost::forward<Args>(args)...);
|
|
1538
|
+
const mask_type new_mask = m | (m + 1u);
|
|
1539
|
+
pb->mask = new_mask;
|
|
1540
|
+
const mask_type mask_plus_one = new_mask + 1u;
|
|
1541
|
+
if (BOOST_UNLIKELY(mask_plus_one <= 2)) {
|
|
1542
|
+
// pb->mask == 0 (impossible), 1 or full
|
|
1543
|
+
if (mask_plus_one == 0) blist.unlink_available(pb);
|
|
1544
|
+
// pb->mask == 1
|
|
1545
|
+
else blist.link_at_back(pb);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
++size_;
|
|
1549
|
+
return iterator(pb, n);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
//! <b>Effects</b>: Inserts an element constructed in-place with args (hint ignored).
|
|
1553
|
+
//!
|
|
1554
|
+
//! <b>Returns</b>: An iterator to the inserted element.
|
|
1555
|
+
//!
|
|
1556
|
+
//! <b>Complexity</b>: Constant (amortized).
|
|
1557
|
+
template<class ...Args>
|
|
1558
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
|
|
1559
|
+
{ return emplace(boost::forward<Args>(args)...); }
|
|
1560
|
+
|
|
1561
|
+
//! <b>Effects</b>: Inserts an element constructed in-place with args.
|
|
1562
|
+
//!
|
|
1563
|
+
//! <b>Returns</b>: An iterator to the inserted element.
|
|
1564
|
+
//!
|
|
1565
|
+
//! <b>Throws</b>: Nothing unless the element's constructor throws.
|
|
1566
|
+
//! Basic exception guarantee.
|
|
1567
|
+
//!
|
|
1568
|
+
//! <b>Complexity</b>: Constant (amortized).
|
|
1569
|
+
//!
|
|
1570
|
+
//! <b>Note</b>: Experimental API.
|
|
1571
|
+
template<class ...Args>
|
|
1572
|
+
BOOST_CONTAINER_FORCEINLINE iterator quick_emplace(BOOST_FWD_REF(Args)... args)
|
|
1573
|
+
{
|
|
1574
|
+
//Read the available block's mask exactly once and keep it in a register.
|
|
1575
|
+
block_base_pointer const pbb = blist.next_available;
|
|
1576
|
+
block_pointer pb;
|
|
1577
|
+
mask_type m;
|
|
1578
|
+
int n;
|
|
1579
|
+
if (BOOST_LIKELY(pbb != blist.header())) {
|
|
1580
|
+
m = pbb->mask;
|
|
1581
|
+
n = dtl::unchecked_countr_one(m);
|
|
1582
|
+
pb = static_cast_block_pointer(pbb);
|
|
1583
|
+
}
|
|
1584
|
+
else {
|
|
1585
|
+
m = 0; //freshly created: mask == 0, n = 0
|
|
1586
|
+
n = 0;
|
|
1587
|
+
pb = priv_create_new_available_block();
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
//If construct throws, the (possibly freshly allocated) block is left
|
|
1591
|
+
//linked as an empty available block: size_/mask are only updated below,
|
|
1592
|
+
//so no element is counted. This is the same state reserve() produces.
|
|
1593
|
+
//This decision simplifies the implementation and improves performance
|
|
1594
|
+
//for some compilers (no exception rollback code needed).
|
|
1595
|
+
block_alloc_traits::construct
|
|
1596
|
+
(al(), boost::movelib::to_raw_pointer(pb->data()) + n, boost::forward<Args>(args)...);
|
|
1597
|
+
|
|
1598
|
+
const mask_type new_mask = m | (m + 1u);
|
|
1599
|
+
pb->mask = new_mask;
|
|
1600
|
+
const mask_type new_mask_plus_one = new_mask + 1u;
|
|
1601
|
+
if (BOOST_UNLIKELY(new_mask_plus_one <= 2u)) {
|
|
1602
|
+
// new_mask == full (block just filled)
|
|
1603
|
+
if (new_mask_plus_one == 0u) blist.unlink_available(pb);
|
|
1604
|
+
// new_mask == 1 (block went empty -> non-empty)
|
|
1605
|
+
else blist.link_at_back(pb);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
++size_;
|
|
1609
|
+
return iterator(pb, n);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
|
1613
|
+
|
|
1614
|
+
#define BOOST_CONTAINER_NEST_QUICK_EMPLACE_BODY(N) \
|
|
1615
|
+
block_base_pointer const pbb = blist.next_available; \
|
|
1616
|
+
block_pointer pb; \
|
|
1617
|
+
mask_type m; \
|
|
1618
|
+
int n; \
|
|
1619
|
+
if (BOOST_LIKELY(pbb != blist.header())) { \
|
|
1620
|
+
m = pbb->mask; \
|
|
1621
|
+
n = dtl::unchecked_countr_one(m); \
|
|
1622
|
+
pb = static_cast_block_pointer(pbb); \
|
|
1623
|
+
} \
|
|
1624
|
+
else { \
|
|
1625
|
+
m = 0; \
|
|
1626
|
+
n = 0; \
|
|
1627
|
+
pb = priv_create_new_available_block(); \
|
|
1628
|
+
} \
|
|
1629
|
+
block_alloc_traits::construct \
|
|
1630
|
+
(al(), boost::movelib::to_raw_pointer(pb->data()) + n \
|
|
1631
|
+
BOOST_MOVE_I##N BOOST_MOVE_FWD##N); \
|
|
1632
|
+
const mask_type new_mask = m | (m + 1u); \
|
|
1633
|
+
pb->mask = new_mask; \
|
|
1634
|
+
const mask_type new_mask_plus_one = new_mask + 1u; \
|
|
1635
|
+
if (BOOST_UNLIKELY(new_mask_plus_one <= 2u)) { \
|
|
1636
|
+
if (new_mask_plus_one == 0u) blist.unlink_available(pb); \
|
|
1637
|
+
else blist.link_at_back(pb); \
|
|
1638
|
+
} \
|
|
1639
|
+
++size_; \
|
|
1640
|
+
return iterator(pb, n); \
|
|
1641
|
+
//
|
|
1642
|
+
|
|
1643
|
+
#define BOOST_CONTAINER_NEST_EMPLACE_CODE(N) \
|
|
1644
|
+
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
|
1645
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N) \
|
|
1646
|
+
{ \
|
|
1647
|
+
block_base_pointer const pbb_prev = blist.next_available; \
|
|
1648
|
+
int n; \
|
|
1649
|
+
block_pointer const pb = priv_retrieve_available_block(n); \
|
|
1650
|
+
const mask_type m = pb->mask; \
|
|
1651
|
+
this->priv_construct_or_restore_capacity( \
|
|
1652
|
+
boost::movelib::to_raw_pointer(pb->data()) + n, pbb_prev \
|
|
1653
|
+
BOOST_MOVE_I##N BOOST_MOVE_FWD##N); \
|
|
1654
|
+
const mask_type new_mask = m | (m + 1u); \
|
|
1655
|
+
pb->mask = new_mask; \
|
|
1656
|
+
const mask_type mask_plus_one = new_mask + 1u; \
|
|
1657
|
+
if (BOOST_UNLIKELY(mask_plus_one <= 2)) { \
|
|
1658
|
+
if (mask_plus_one == 0) blist.unlink_available(pb); \
|
|
1659
|
+
else blist.link_at_back(pb); \
|
|
1660
|
+
} \
|
|
1661
|
+
++size_; \
|
|
1662
|
+
return iterator(pb, n); \
|
|
1663
|
+
} \
|
|
1664
|
+
\
|
|
1665
|
+
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
|
1666
|
+
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
|
|
1667
|
+
{ return emplace(BOOST_MOVE_FWD##N); } \
|
|
1668
|
+
\
|
|
1669
|
+
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
|
1670
|
+
BOOST_CONTAINER_FORCEINLINE iterator quick_emplace(BOOST_MOVE_UREF##N) \
|
|
1671
|
+
{ \
|
|
1672
|
+
BOOST_CONTAINER_NEST_QUICK_EMPLACE_BODY(N) \
|
|
1673
|
+
} \
|
|
1674
|
+
//
|
|
1675
|
+
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NEST_EMPLACE_CODE)
|
|
1676
|
+
#undef BOOST_CONTAINER_NEST_EMPLACE_CODE
|
|
1677
|
+
#undef BOOST_CONTAINER_NEST_QUICK_EMPLACE_BODY
|
|
1678
|
+
|
|
1679
|
+
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
|
1680
|
+
|
|
1681
|
+
//! <b>Effects</b>: Inserts a copy of x.
|
|
1682
|
+
//!
|
|
1683
|
+
//! <b>Returns</b>: An iterator to the inserted element.
|
|
1684
|
+
//!
|
|
1685
|
+
//! <b>Complexity</b>: Constant (amortized).
|
|
1686
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const T& x)
|
|
1687
|
+
{ return emplace(x); }
|
|
1688
|
+
|
|
1689
|
+
//! <b>Effects</b>: Inserts a copy of x (hint ignored).
|
|
1690
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator, const T& x)
|
|
1691
|
+
{ return emplace(x); }
|
|
1692
|
+
|
|
1693
|
+
//! <b>Effects</b>: Inserts x by moving.
|
|
1694
|
+
//!
|
|
1695
|
+
//! <b>Returns</b>: An iterator to the inserted element.
|
|
1696
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x)
|
|
1697
|
+
{ return emplace(boost::move(x)); }
|
|
1698
|
+
|
|
1699
|
+
//! <b>Effects</b>: Inserts x by moving (hint ignored).
|
|
1700
|
+
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator, BOOST_RV_REF(value_type) x)
|
|
1701
|
+
{ return emplace(boost::move(x)); }
|
|
1702
|
+
|
|
1703
|
+
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
|
1704
|
+
//! <b>Effects</b>: Inserts elements from il.
|
|
1705
|
+
//!
|
|
1706
|
+
//! <b>Complexity</b>: Linear.
|
|
1707
|
+
void insert(std::initializer_list<value_type> il)
|
|
1708
|
+
{ insert(il.begin(), il.end()); }
|
|
1709
|
+
#endif
|
|
1710
|
+
|
|
1711
|
+
//! <b>Effects</b>: Inserts copies of elements in [first, last).
|
|
1712
|
+
//!
|
|
1713
|
+
//! <b>Complexity</b>: Linear.
|
|
1714
|
+
template<class InpIt>
|
|
1715
|
+
void insert(InpIt first, InpIt last
|
|
1716
|
+
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
|
1717
|
+
, typename dtl::disable_if_convertible<InpIt, size_type>::type* = 0
|
|
1718
|
+
#endif
|
|
1719
|
+
)
|
|
1720
|
+
{
|
|
1721
|
+
priv_insert_range_copy(first, last);
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
//! <b>Effects</b>: Inserts n copies of x.
|
|
1725
|
+
//!
|
|
1726
|
+
//! <b>Complexity</b>: Linear.
|
|
1727
|
+
void insert(size_type n, const T& x)
|
|
1728
|
+
{
|
|
1729
|
+
priv_insert_n_copies(n, x);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
//! <b>Effects</b>: Erases the element at position pos.
|
|
1733
|
+
//!
|
|
1734
|
+
//! <b>Returns</b>: An iterator to the element after the erased one.
|
|
1735
|
+
//!
|
|
1736
|
+
//! <b>Complexity</b>: Constant.
|
|
1737
|
+
BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator pos)
|
|
1738
|
+
{
|
|
1739
|
+
block_base_pointer pbb = pos.pbb;
|
|
1740
|
+
int n = pos.n;
|
|
1741
|
+
++pos;
|
|
1742
|
+
priv_erase_impl(pbb, n);
|
|
1743
|
+
return iterator(pos.pbb, pos.n);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
//! <b>Effects</b>: Erases the element at pos without returning iterator.
|
|
1747
|
+
//! Potentially faster than erase().
|
|
1748
|
+
//!
|
|
1749
|
+
//! <b>Complexity</b>: Constant.
|
|
1750
|
+
BOOST_CONTAINER_FORCEINLINE void erase_void(const_iterator pos)
|
|
1751
|
+
{
|
|
1752
|
+
priv_erase_impl(pos.pbb, pos.n);
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
//! <b>Effects</b>: Erases elements in [first, last).
|
|
1756
|
+
//!
|
|
1757
|
+
//! <b>Returns</b>: An iterator to the element after the erased range.
|
|
1758
|
+
//!
|
|
1759
|
+
//! <b>Complexity</b>: Linear to the range size.
|
|
1760
|
+
iterator erase(const_iterator first, const_iterator last)
|
|
1761
|
+
{
|
|
1762
|
+
{
|
|
1763
|
+
block_base_pointer pbb_first = first.pbb;
|
|
1764
|
+
while(first != last) {
|
|
1765
|
+
first = erase(first);
|
|
1766
|
+
if(first.pbb != pbb_first) break;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
block_base_pointer pbb = first.pbb;
|
|
1770
|
+
if(pbb != last.pbb){
|
|
1771
|
+
do {
|
|
1772
|
+
block_pointer const pb = static_cast_block_pointer(pbb);
|
|
1773
|
+
const mask_type m = pb->mask;
|
|
1774
|
+
pbb = pb->next;
|
|
1775
|
+
pb->mask = 0;
|
|
1776
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled) {
|
|
1777
|
+
BOOST_CONTAINER_NEST_PREFETCH(static_cast<block_type&>(*pbb).data());
|
|
1778
|
+
}
|
|
1779
|
+
size_ -= priv_destroy_all_in_nonempty_block(boost::movelib::to_raw_pointer(pb->data()), m);
|
|
1780
|
+
blist.unlink(pb);
|
|
1781
|
+
//Block is being fully emptied. If it was partial it is already in
|
|
1782
|
+
//the available list, so take it out first; then (re)link it at the
|
|
1783
|
+
//back, where all reserved (empty) blocks are kept grouped.
|
|
1784
|
+
if(BOOST_LIKELY(m != full))
|
|
1785
|
+
blist.unlink_available(pb);
|
|
1786
|
+
blist.link_available_at_back(pb);
|
|
1787
|
+
} while(pbb != last.pbb);
|
|
1788
|
+
first = const_iterator(pbb, nest_detail::first_in_mask(pbb->mask));
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
while(first != last)
|
|
1792
|
+
first = erase(first);
|
|
1793
|
+
return iterator(last.pbb, last.n);
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
//! <b>Effects</b>: Swaps the contents of *this and x.
|
|
1797
|
+
//!
|
|
1798
|
+
//! <b>Throws</b>: Nothing.
|
|
1799
|
+
//!
|
|
1800
|
+
//! <b>Complexity</b>: Constant.
|
|
1801
|
+
void swap(nest& x)
|
|
1802
|
+
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
|
|
1803
|
+
|| allocator_traits_type::is_always_equal::value)
|
|
1804
|
+
{
|
|
1805
|
+
BOOST_STATIC_CONSTEXPR bool pocs_val =
|
|
1806
|
+
allocator_traits_type::propagate_on_container_swap::value;
|
|
1807
|
+
priv_swap_impl(x, dtl::bool_<pocs_val>());
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
//! <b>Effects</b>: Erases all elements.
|
|
1811
|
+
//!
|
|
1812
|
+
//! <b>Complexity</b>: Linear.
|
|
1813
|
+
void clear() BOOST_NOEXCEPT
|
|
1814
|
+
{
|
|
1815
|
+
block_base_pointer const hdr = blist.header();
|
|
1816
|
+
#define BOOST_CONTAINER_NEST_CLEAR_BIDIR
|
|
1817
|
+
#if defined(BOOST_CONTAINER_NEST_CLEAR_BIDIR)
|
|
1818
|
+
// Dual-cursor (bidirectional) traversal. A single cold next-pointer chase
|
|
1819
|
+
// is address-serial: the address of block i+1 is produced by the load on
|
|
1820
|
+
// block i, so it runs at one full DRAM miss per block and software
|
|
1821
|
+
// prefetch cannot help. The main list is doubly linked, so we walk it from
|
|
1822
|
+
// both ends toward the middle: the front (->next) and back (->prev) chains
|
|
1823
|
+
// are independent, keeping two block-header misses in flight at once
|
|
1824
|
+
// (memory-level parallelism) which hides the latency. clear() visits every
|
|
1825
|
+
// block and block order is irrelevant, so this is a pure scheduling change
|
|
1826
|
+
// with the same end state (main list emptied, every block reserved).
|
|
1827
|
+
block_base_pointer f = blist.next; // front cursor (advances via ->next)
|
|
1828
|
+
block_base_pointer b = blist.prev; // back cursor (advances via ->prev)
|
|
1829
|
+
|
|
1830
|
+
while (f != hdr) {
|
|
1831
|
+
// Two independent dependency chains; issue both header loads up front.
|
|
1832
|
+
const mask_type mf = f->mask;
|
|
1833
|
+
const mask_type mb = b->mask;
|
|
1834
|
+
block_base_pointer const fn = f->next; // capture advances before mutating
|
|
1835
|
+
block_base_pointer const bp = b->prev;
|
|
1836
|
+
f->mask = 0;
|
|
1837
|
+
b->mask = 0;
|
|
1838
|
+
|
|
1839
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled) {
|
|
1840
|
+
BOOST_CONTAINER_NEST_PREFETCH(fn);
|
|
1841
|
+
BOOST_CONTAINER_NEST_PREFETCH(bp);
|
|
1842
|
+
BOOST_IF_CONSTEXPR(!dtl::is_trivially_destructible<T>::value) {
|
|
1843
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(fn);
|
|
1844
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(bp);
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
block_pointer const pf = static_cast_block_pointer(f);
|
|
1849
|
+
if (f == b) { // odd count: lone middle block
|
|
1850
|
+
priv_clear_block(pf, mf);
|
|
1851
|
+
break;
|
|
1852
|
+
}
|
|
1853
|
+
priv_clear_block(pf, mf); // front
|
|
1854
|
+
priv_clear_block(static_cast_block_pointer(b), mb); // back
|
|
1855
|
+
if (fn == b) break; // even count: that was the last pair
|
|
1856
|
+
f = fn;
|
|
1857
|
+
b = bp;
|
|
1858
|
+
}
|
|
1859
|
+
#else
|
|
1860
|
+
block_base_pointer pbb = blist.next;
|
|
1861
|
+
|
|
1862
|
+
while(pbb != hdr) {
|
|
1863
|
+
const mask_type m = pbb->mask; //!= 0 (main-list membership)
|
|
1864
|
+
pbb->mask = 0;
|
|
1865
|
+
block_pointer const pb = static_cast_block_pointer(pbb);
|
|
1866
|
+
pbb = pbb->next;
|
|
1867
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled) {
|
|
1868
|
+
BOOST_CONTAINER_NEST_PREFETCH(pbb->next);
|
|
1869
|
+
BOOST_IF_CONSTEXPR(!dtl::is_trivially_destructible<T>::value)
|
|
1870
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(pbb);
|
|
1871
|
+
}
|
|
1872
|
+
priv_clear_block(pb, m);
|
|
1873
|
+
}
|
|
1874
|
+
#endif
|
|
1875
|
+
|
|
1876
|
+
blist.next = blist.prev = hdr;
|
|
1877
|
+
size_ = 0;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
//////////////////////////////////////////////
|
|
1881
|
+
//
|
|
1882
|
+
// hive operations
|
|
1883
|
+
//
|
|
1884
|
+
//////////////////////////////////////////////
|
|
1885
|
+
|
|
1886
|
+
//! <b>Effects</b>: Transfers all elements from x into *this.
|
|
1887
|
+
//!
|
|
1888
|
+
//! <b>Requires</b>: get_allocator() == x.get_allocator().
|
|
1889
|
+
//!
|
|
1890
|
+
//! <b>Complexity</b>: Linear in x.size().
|
|
1891
|
+
void splice(nest& x)
|
|
1892
|
+
{
|
|
1893
|
+
BOOST_ASSERT(this != &x);
|
|
1894
|
+
BOOST_ASSERT(priv_alloc() == x.priv_alloc());
|
|
1895
|
+
block_base_pointer pbb = x.blist.header()->next;
|
|
1896
|
+
while(pbb != x.blist.header()) {
|
|
1897
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
1898
|
+
pbb = pbb->next;
|
|
1899
|
+
if(pb->mask != full) {
|
|
1900
|
+
x.blist.unlink_available(pb);
|
|
1901
|
+
blist.link_available_at_front(pb);
|
|
1902
|
+
}
|
|
1903
|
+
x.blist.unlink(pb);
|
|
1904
|
+
blist.link_at_back(pb);
|
|
1905
|
+
--x.num_blocks;
|
|
1906
|
+
++num_blocks;
|
|
1907
|
+
size_type const s = (size_type)dtl::popcount(pb->mask);
|
|
1908
|
+
x.size_ -= (size_type)s;
|
|
1909
|
+
size_ += (size_type)s;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
//! <b>Effects</b>: Transfers all elements from x into *this.
|
|
1914
|
+
void splice(BOOST_RV_REF(nest) x)
|
|
1915
|
+
{ this->splice(static_cast<nest&>(x)); }
|
|
1916
|
+
|
|
1917
|
+
//! <b>Effects</b>: Removes consecutive duplicate elements.
|
|
1918
|
+
//!
|
|
1919
|
+
//! <b>Returns</b>: The number of elements removed.
|
|
1920
|
+
//!
|
|
1921
|
+
//! <b>Complexity</b>: Linear.
|
|
1922
|
+
template<class BinaryPredicate>
|
|
1923
|
+
size_type unique(BinaryPredicate pred)
|
|
1924
|
+
{
|
|
1925
|
+
size_type s = size_;
|
|
1926
|
+
const_iterator first = cbegin();
|
|
1927
|
+
const_iterator last = cend();
|
|
1928
|
+
while(first != last) {
|
|
1929
|
+
const_iterator next_it = first;
|
|
1930
|
+
++next_it;
|
|
1931
|
+
nest_detail::unique_pred_adaptor<T, BinaryPredicate> adaptor(
|
|
1932
|
+
dtl::addressof(*first), pred);
|
|
1933
|
+
first = erase(next_it,
|
|
1934
|
+
nest_detail::find_if_not(next_it, last, adaptor));
|
|
1935
|
+
}
|
|
1936
|
+
return (size_type)(s - size_);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
//! <b>Effects</b>: Removes consecutive equal elements.
|
|
1940
|
+
//!
|
|
1941
|
+
//! <b>Returns</b>: The number of elements removed.
|
|
1942
|
+
size_type unique()
|
|
1943
|
+
{ return unique(std::equal_to<T>()); }
|
|
1944
|
+
|
|
1945
|
+
#if defined(BOOST_MSVC)
|
|
1946
|
+
#pragma warning(push)
|
|
1947
|
+
#pragma warning(disable:4127) // conditional expression is constant
|
|
1948
|
+
#endif
|
|
1949
|
+
|
|
1950
|
+
//! <b>Effects</b>: Sorts elements according to comp.
|
|
1951
|
+
//!
|
|
1952
|
+
//! <b>Complexity</b>: O(n log n).
|
|
1953
|
+
template<class Compare>
|
|
1954
|
+
void sort(Compare comp)
|
|
1955
|
+
{
|
|
1956
|
+
priv_sort_impl(comp);
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
#if defined(BOOST_MSVC)
|
|
1960
|
+
#pragma warning(pop) // C4127
|
|
1961
|
+
#endif
|
|
1962
|
+
|
|
1963
|
+
//! <b>Effects</b>: Sorts elements in ascending order.
|
|
1964
|
+
//!
|
|
1965
|
+
//! <b>Complexity</b>: O(n log n).
|
|
1966
|
+
void sort()
|
|
1967
|
+
{ sort(std::less<T>()); }
|
|
1968
|
+
|
|
1969
|
+
//! <b>Effects</b>: Returns an iterator to the element pointed to by p.
|
|
1970
|
+
//!
|
|
1971
|
+
//! <b>Complexity</b>: Linear.
|
|
1972
|
+
iterator get_iterator(const_pointer p)
|
|
1973
|
+
{
|
|
1974
|
+
std::less<const T*> less_cmp;
|
|
1975
|
+
block_base_pointer pbb = blist.next;
|
|
1976
|
+
while(pbb != blist.header()) {
|
|
1977
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
1978
|
+
const T* raw_data = boost::movelib::to_raw_pointer(pb->data());
|
|
1979
|
+
const T* raw_p = boost::movelib::to_raw_pointer(p);
|
|
1980
|
+
if(!less_cmp(raw_p, raw_data) &&
|
|
1981
|
+
less_cmp(raw_p, raw_data + N)) {
|
|
1982
|
+
int const n = (int)(p - pb->data());
|
|
1983
|
+
BOOST_ASSERT_MSG(
|
|
1984
|
+
(pb->mask & ((mask_type)(1) << n)) != 0,
|
|
1985
|
+
"p points to an invalid element");
|
|
1986
|
+
return iterator(pb, n);
|
|
1987
|
+
}
|
|
1988
|
+
pbb = pbb->next;
|
|
1989
|
+
}
|
|
1990
|
+
BOOST_ASSERT_MSG(false, "p does not point into the extents of *this");
|
|
1991
|
+
#if defined(BOOST_ASSERT_HANDLER_IS_NORETURN)
|
|
1992
|
+
BOOST_UNREACHABLE_RETURN(end());
|
|
1993
|
+
#else
|
|
1994
|
+
return end();
|
|
1995
|
+
#endif
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
//! <b>Effects</b>: Returns a const_iterator to the element pointed to by p.
|
|
1999
|
+
//!
|
|
2000
|
+
//! <b>Complexity</b>: Linear.
|
|
2001
|
+
const_iterator get_iterator(const_pointer p) const
|
|
2002
|
+
{
|
|
2003
|
+
return const_cast<nest*>(this)->get_iterator(p);
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
2007
|
+
private:
|
|
2008
|
+
|
|
2009
|
+
template <class U, class A, class O, class P>
|
|
2010
|
+
friend typename nest<U, A, O>::size_type erase_if(nest<U, A, O>&, P);
|
|
2011
|
+
|
|
2012
|
+
private:
|
|
2013
|
+
//////////////////////////////////////////////
|
|
2014
|
+
//
|
|
2015
|
+
// private: allocator access
|
|
2016
|
+
//
|
|
2017
|
+
//////////////////////////////////////////////
|
|
2018
|
+
|
|
2019
|
+
block_allocator& al() BOOST_NOEXCEPT { return static_cast<block_allocator&>(*this); }
|
|
2020
|
+
const block_allocator& al() const BOOST_NOEXCEPT { return static_cast<const block_allocator&>(*this); }
|
|
2021
|
+
|
|
2022
|
+
allocator_type priv_alloc() const BOOST_NOEXCEPT
|
|
2023
|
+
{ return allocator_type(al()); }
|
|
2024
|
+
|
|
2025
|
+
//////////////////////////////////////////////
|
|
2026
|
+
//
|
|
2027
|
+
// private: block management
|
|
2028
|
+
//
|
|
2029
|
+
//////////////////////////////////////////////
|
|
2030
|
+
|
|
2031
|
+
BOOST_CONTAINER_FORCEINLINE static block_pointer
|
|
2032
|
+
static_cast_block_pointer(block_base_pointer pbb) BOOST_NOEXCEPT
|
|
2033
|
+
{
|
|
2034
|
+
return block_type::static_cast_block_pointer(pbb);
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
void priv_allocate_block_data(block_pointer pb, dtl::bool_<false>)
|
|
2038
|
+
{
|
|
2039
|
+
BOOST_CONTAINER_TRY {
|
|
2040
|
+
allocator_type val_al(al());
|
|
2041
|
+
pb->data_ = allocator_traits_type::allocate(val_al, N);
|
|
2042
|
+
}
|
|
2043
|
+
BOOST_CONTAINER_CATCH(...) {
|
|
2044
|
+
block_alloc_traits::deallocate(al(), pb, 1);
|
|
2045
|
+
BOOST_CONTAINER_RETHROW;
|
|
2046
|
+
}
|
|
2047
|
+
BOOST_CONTAINER_CATCH_END
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
BOOST_CONTAINER_FORCEINLINE void priv_allocate_block_data(block_pointer, dtl::bool_<true>) BOOST_NOEXCEPT {}
|
|
2051
|
+
|
|
2052
|
+
BOOST_CONTAINER_FORCEINLINE void priv_deallocate_block_data(block_pointer pb, dtl::bool_<false>) BOOST_NOEXCEPT
|
|
2053
|
+
{
|
|
2054
|
+
allocator_type val_al(al());
|
|
2055
|
+
allocator_traits_type::deallocate(val_al, pb->data(), N);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
BOOST_CONTAINER_FORCEINLINE void priv_deallocate_block_data(block_pointer, dtl::bool_<true>) BOOST_NOEXCEPT {}
|
|
2059
|
+
|
|
2060
|
+
block_pointer priv_create_new_available_block()
|
|
2061
|
+
{
|
|
2062
|
+
block_pointer pb = block_alloc_traits::allocate(al(), 1);
|
|
2063
|
+
pb->mask = 0;
|
|
2064
|
+
priv_allocate_block_data(pb, dtl::bool_<store_data_in_block>());
|
|
2065
|
+
blist.link_available_at_back(pb);
|
|
2066
|
+
++num_blocks;
|
|
2067
|
+
return pb;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
void priv_delete_block(block_pointer pb) BOOST_NOEXCEPT
|
|
2071
|
+
{
|
|
2072
|
+
priv_deallocate_block_data(pb, dtl::bool_<store_data_in_block>());
|
|
2073
|
+
block_alloc_traits::deallocate(al(), pb, 1);
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
BOOST_CONTAINER_FORCEINLINE block_pointer priv_retrieve_available_block(int& n)
|
|
2077
|
+
{
|
|
2078
|
+
if(BOOST_LIKELY(blist.next_available != blist.header())){
|
|
2079
|
+
block_pointer pb = static_cast_block_pointer(blist.next_available);
|
|
2080
|
+
n = dtl::unchecked_countr_one(pb->mask);
|
|
2081
|
+
return pb;
|
|
2082
|
+
}
|
|
2083
|
+
else {
|
|
2084
|
+
n = 0;
|
|
2085
|
+
return priv_create_new_available_block();
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// If the next_available block at the moment of failure is not the same as the one
|
|
2090
|
+
// observed before calling priv_retrieve_available_block, a new (and now empty) block
|
|
2091
|
+
// was freshly allocated for the failed construction: free it to restore capacity.
|
|
2092
|
+
BOOST_CONTAINER_NOINLINE void priv_restore_capacity_on_throw(block_base_pointer pbb_prev) BOOST_NOEXCEPT
|
|
2093
|
+
{
|
|
2094
|
+
if(blist.next_available != pbb_prev) {
|
|
2095
|
+
block_pointer const pb_new = static_cast_block_pointer(blist.next_available);
|
|
2096
|
+
blist.unlink_available(pb_new);
|
|
2097
|
+
priv_delete_block(pb_new);
|
|
2098
|
+
--num_blocks;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// The try/catch lives here (not inline in emplace) on purpose: MSVC will not
|
|
2103
|
+
// inline a function that contains its own EH scope, so keeping emplace
|
|
2104
|
+
// EH-clean lets it be inlined into the caller's insert loop. This is a plain
|
|
2105
|
+
// (non-FORCEINLINE) helper so the EH scope stays out of emplace.
|
|
2106
|
+
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
|
2107
|
+
template<class ...Args>
|
|
2108
|
+
inline void priv_construct_or_restore_capacity
|
|
2109
|
+
(T* p, block_base_pointer pbb_prev, BOOST_FWD_REF(Args)... args)
|
|
2110
|
+
{
|
|
2111
|
+
BOOST_CONTAINER_TRY{
|
|
2112
|
+
block_alloc_traits::construct(al(), p, boost::forward<Args>(args)...);
|
|
2113
|
+
}
|
|
2114
|
+
BOOST_CONTAINER_CATCH(...){
|
|
2115
|
+
this->priv_restore_capacity_on_throw(pbb_prev);
|
|
2116
|
+
BOOST_CONTAINER_RETHROW;
|
|
2117
|
+
}
|
|
2118
|
+
BOOST_CONTAINER_CATCH_END
|
|
2119
|
+
}
|
|
2120
|
+
#else
|
|
2121
|
+
#define BOOST_CONTAINER_NEST_CONSTRUCT_OR_RESTORE_CODE(N) \
|
|
2122
|
+
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
|
2123
|
+
inline void priv_construct_or_restore_capacity \
|
|
2124
|
+
(T* p, block_base_pointer pbb_prev BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
|
|
2125
|
+
{ \
|
|
2126
|
+
BOOST_CONTAINER_TRY{ \
|
|
2127
|
+
block_alloc_traits::construct(al(), p BOOST_MOVE_I##N BOOST_MOVE_FWD##N); \
|
|
2128
|
+
} \
|
|
2129
|
+
BOOST_CONTAINER_CATCH(...){ \
|
|
2130
|
+
this->priv_restore_capacity_on_throw(pbb_prev); \
|
|
2131
|
+
BOOST_CONTAINER_RETHROW; \
|
|
2132
|
+
} \
|
|
2133
|
+
BOOST_CONTAINER_CATCH_END \
|
|
2134
|
+
} \
|
|
2135
|
+
//
|
|
2136
|
+
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NEST_CONSTRUCT_OR_RESTORE_CODE)
|
|
2137
|
+
#undef BOOST_CONTAINER_NEST_CONSTRUCT_OR_RESTORE_CODE
|
|
2138
|
+
#endif
|
|
2139
|
+
|
|
2140
|
+
//////////////////////////////////////////////
|
|
2141
|
+
//
|
|
2142
|
+
// private: destruction helpers
|
|
2143
|
+
//
|
|
2144
|
+
//////////////////////////////////////////////
|
|
2145
|
+
|
|
2146
|
+
BOOST_CONTAINER_FORCEINLINE size_type priv_destroy_all_in_nonempty_block(T* data, mask_type m) BOOST_NOEXCEPT
|
|
2147
|
+
{
|
|
2148
|
+
BOOST_ASSERT(m != 0);
|
|
2149
|
+
const size_type r = (size_type)dtl::popcount(m); (void)data;
|
|
2150
|
+
BOOST_IF_CONSTEXPR(!dtl::is_trivially_destructible<T>::value) {
|
|
2151
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2152
|
+
do {
|
|
2153
|
+
int n = nest_detail::first_in_mask(m);
|
|
2154
|
+
block_alloc_traits::destroy(al(), data + n);
|
|
2155
|
+
m &= m - 1;
|
|
2156
|
+
} while(m);
|
|
2157
|
+
}
|
|
2158
|
+
return r;
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
BOOST_CONTAINER_FORCEINLINE size_type priv_destroy_all_in_full_block(T* data, mask_type mask) BOOST_NOEXCEPT
|
|
2162
|
+
{
|
|
2163
|
+
(void)data; (void)mask;
|
|
2164
|
+
BOOST_ASSERT(mask == full);
|
|
2165
|
+
BOOST_IF_CONSTEXPR(!dtl::is_trivially_destructible<T>::value) {
|
|
2166
|
+
(void)mask;
|
|
2167
|
+
T* const data_end = data + N;
|
|
2168
|
+
|
|
2169
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2170
|
+
for (; data != data_end; ++data) {
|
|
2171
|
+
block_alloc_traits::destroy(al(), data);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
return (size_type)N;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
// Per-block work shared by clear()'s traversal variants: destroy the live
|
|
2178
|
+
// elements of 'pb' (using the captured pre-clear mask 'm') and, for a full
|
|
2179
|
+
// block (which is not on the available list), append it there. The caller is
|
|
2180
|
+
// responsible for resetting pb->mask to 0. Block order is irrelevant here.
|
|
2181
|
+
BOOST_CONTAINER_FORCEINLINE void priv_clear_block(block_pointer pb, mask_type m) BOOST_NOEXCEPT
|
|
2182
|
+
{
|
|
2183
|
+
T* const pd = boost::movelib::to_raw_pointer(pb->data());
|
|
2184
|
+
if (m == full) {
|
|
2185
|
+
//Full blocks are not on the available list; add them. Partial blocks
|
|
2186
|
+
//are already there. Every block becomes reserved (mask == 0).
|
|
2187
|
+
priv_destroy_all_in_full_block(pd, m);
|
|
2188
|
+
blist.link_available_at_back(pb);
|
|
2189
|
+
}
|
|
2190
|
+
else
|
|
2191
|
+
priv_destroy_all_in_nonempty_block(pd, m);
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
// Per-block work shared by priv_reset()'s traversal variants: destroy the
|
|
2195
|
+
// live elements of a main-list block (mask 'm' != 0; partial or full) and
|
|
2196
|
+
// free it. Empty/reserved blocks carry no elements and are freed directly
|
|
2197
|
+
// with priv_delete_block instead. priv_delete_block does not unlink, so the
|
|
2198
|
+
// caller may free blocks in any order provided list advances were captured
|
|
2199
|
+
// from still-live nodes beforehand.
|
|
2200
|
+
BOOST_CONTAINER_FORCEINLINE void priv_reset_block(block_pointer pb, mask_type m) BOOST_NOEXCEPT
|
|
2201
|
+
{
|
|
2202
|
+
BOOST_ASSERT(m != 0);
|
|
2203
|
+
T* const pd = boost::movelib::to_raw_pointer(pb->data());
|
|
2204
|
+
if (m == full)
|
|
2205
|
+
priv_destroy_all_in_full_block(pd, m);
|
|
2206
|
+
else
|
|
2207
|
+
priv_destroy_all_in_nonempty_block(pd, m);
|
|
2208
|
+
priv_delete_block(pb);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
//////////////////////////////////////////////
|
|
2212
|
+
//
|
|
2213
|
+
// private: reset (destroy all + free)
|
|
2214
|
+
//
|
|
2215
|
+
//////////////////////////////////////////////
|
|
2216
|
+
|
|
2217
|
+
void priv_reset() BOOST_NOEXCEPT
|
|
2218
|
+
{
|
|
2219
|
+
// Phase A sequential (empties), then a bidirectional main-list
|
|
2220
|
+
// walk for partial+full blocks. The single forward next-pointer chase of
|
|
2221
|
+
// variant 0 is address-serial (one DRAM miss per block, no MLP); walking
|
|
2222
|
+
// the doubly-linked main list from both ends gives two independent
|
|
2223
|
+
// header-miss streams. NOTE: because reset frees as it goes, neighbor data
|
|
2224
|
+
// prefetch must not dereference an already-freed block, so the next-pair
|
|
2225
|
+
// data prefetch is issued only on non-terminal iterations (when fn/bp are
|
|
2226
|
+
// strictly inside the unprocessed (f, b) range and hence still alive).
|
|
2227
|
+
block_base_pointer const hdr = blist.header();
|
|
2228
|
+
|
|
2229
|
+
// A) empty (reserved) blocks, from the back of the available list
|
|
2230
|
+
block_base_pointer pbb = hdr->prev_available;
|
|
2231
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2232
|
+
while(pbb != hdr && pbb->mask == 0) {
|
|
2233
|
+
block_pointer const pb = static_cast_block_pointer(pbb);
|
|
2234
|
+
pbb = pbb->prev_available;
|
|
2235
|
+
|
|
2236
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled)
|
|
2237
|
+
BOOST_CONTAINER_NEST_PREFETCH(pbb);
|
|
2238
|
+
|
|
2239
|
+
priv_delete_block(pb);
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
// B) partial + full blocks, from both ends of the main list
|
|
2243
|
+
block_base_pointer f = blist.next;
|
|
2244
|
+
block_base_pointer b = blist.prev;
|
|
2245
|
+
while(f != hdr) {
|
|
2246
|
+
const mask_type mf = f->mask;
|
|
2247
|
+
const mask_type mb = b->mask;
|
|
2248
|
+
block_base_pointer const fn = f->next;
|
|
2249
|
+
block_base_pointer const bp = b->prev;
|
|
2250
|
+
block_pointer const pf = static_cast_block_pointer(f);
|
|
2251
|
+
|
|
2252
|
+
if(f == b) { // odd count: lone middle block
|
|
2253
|
+
priv_reset_block(pf, mf);
|
|
2254
|
+
break;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
block_pointer const pbk = static_cast_block_pointer(b);
|
|
2258
|
+
const bool last_pair = (fn == b); // even count: final pair
|
|
2259
|
+
|
|
2260
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled){
|
|
2261
|
+
if(!last_pair){ // fn, bp strictly inside (f,b): alive
|
|
2262
|
+
BOOST_CONTAINER_NEST_PREFETCH(fn);
|
|
2263
|
+
BOOST_CONTAINER_NEST_PREFETCH(bp);
|
|
2264
|
+
BOOST_IF_CONSTEXPR(!dtl::is_trivially_destructible<T>::value){
|
|
2265
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(fn);
|
|
2266
|
+
BOOST_CONTAINER_NEST_PREFETCH_BLOCK(bp);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
priv_reset_block(pf, mf);
|
|
2272
|
+
priv_reset_block(pbk, mb);
|
|
2273
|
+
if(last_pair) break;
|
|
2274
|
+
f = fn;
|
|
2275
|
+
b = bp;
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
blist.reset();
|
|
2279
|
+
num_blocks = 0;
|
|
2280
|
+
size_ = 0;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
//////////////////////////////////////////////
|
|
2284
|
+
//
|
|
2285
|
+
// private: erase implementation
|
|
2286
|
+
//
|
|
2287
|
+
//////////////////////////////////////////////
|
|
2288
|
+
|
|
2289
|
+
BOOST_CONTAINER_FORCEINLINE void priv_erase_impl(block_base_pointer pbb, int n) BOOST_NOEXCEPT
|
|
2290
|
+
{
|
|
2291
|
+
block_pointer const pb = static_cast_block_pointer(pbb);
|
|
2292
|
+
const mask_type m = pb->mask; //Load constant before any "opaque" operations like "destroy"
|
|
2293
|
+
const mask_type new_mask = m & ~((mask_type)(1) << n);
|
|
2294
|
+
pb->mask = new_mask;
|
|
2295
|
+
|
|
2296
|
+
block_alloc_traits::destroy(al(), boost::movelib::to_raw_pointer(pb->data()) + n);
|
|
2297
|
+
|
|
2298
|
+
if(BOOST_UNLIKELY(m == full))
|
|
2299
|
+
blist.link_available_at_front(pb);
|
|
2300
|
+
|
|
2301
|
+
//With N > 1 both conditions can't be true
|
|
2302
|
+
else if(BOOST_UNLIKELY(new_mask == 0)) {
|
|
2303
|
+
//Block just became empty: take it out of the main list and move it
|
|
2304
|
+
//to the back of the available list so reserved blocks stay grouped
|
|
2305
|
+
//there (keeps trim_capacity linear on the number of reserved blocks).
|
|
2306
|
+
blist.unlink(pb);
|
|
2307
|
+
blist.unlink_available(pb);
|
|
2308
|
+
blist.link_available_at_back(pb);
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
--size_;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
//////////////////////////////////////////////
|
|
2315
|
+
//
|
|
2316
|
+
// private: range insert / assign
|
|
2317
|
+
//
|
|
2318
|
+
//////////////////////////////////////////////
|
|
2319
|
+
|
|
2320
|
+
template<class InpIt>
|
|
2321
|
+
void priv_insert_range_copy(InpIt first, InpIt last)
|
|
2322
|
+
{
|
|
2323
|
+
while(first != last) {
|
|
2324
|
+
int n;
|
|
2325
|
+
block_pointer pb = priv_retrieve_available_block(n);
|
|
2326
|
+
for(; ; ) {
|
|
2327
|
+
block_alloc_traits::construct(
|
|
2328
|
+
al(), boost::movelib::to_raw_pointer(pb->data() + n), *first);
|
|
2329
|
+
++first;
|
|
2330
|
+
++size_;
|
|
2331
|
+
if(BOOST_UNLIKELY(pb->mask == 0)) blist.link_at_back(pb);
|
|
2332
|
+
pb->mask |= pb->mask + 1;
|
|
2333
|
+
if(pb->mask == full){
|
|
2334
|
+
blist.unlink_available(pb);
|
|
2335
|
+
break;
|
|
2336
|
+
}
|
|
2337
|
+
else if(first == last) return;
|
|
2338
|
+
n = dtl::unchecked_countr_one(pb->mask);
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
template<class InpIt>
|
|
2344
|
+
void priv_insert_range_move(InpIt first, InpIt last)
|
|
2345
|
+
{
|
|
2346
|
+
this->priv_insert_range_copy( boost::make_move_iterator(first)
|
|
2347
|
+
, boost::make_move_iterator(last));
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
void priv_insert_n_copies(size_type count, const T& x)
|
|
2351
|
+
{
|
|
2352
|
+
typedef constant_iterator<T> const_it;
|
|
2353
|
+
this->priv_insert_range_copy(const_it(x, count), const_it());
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
void priv_insert_n_default(size_type count)
|
|
2357
|
+
{
|
|
2358
|
+
typedef value_init_construct_iterator<value_type> value_init_iterator;
|
|
2359
|
+
this->priv_insert_range_copy(value_init_iterator(count), value_init_iterator());
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
template<class InpIt>
|
|
2363
|
+
void priv_range_assign(InpIt first, InpIt last)
|
|
2364
|
+
{
|
|
2365
|
+
block_base_pointer pbb = blist.next;
|
|
2366
|
+
int n = -1;
|
|
2367
|
+
if(first != last) {
|
|
2368
|
+
for(; pbb != blist.header(); pbb = pbb->next) {
|
|
2369
|
+
n = 0;
|
|
2370
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
2371
|
+
for(mask_type bit = 1; bit; bit <<= 1, ++n) {
|
|
2372
|
+
if(pb->mask & bit) {
|
|
2373
|
+
pb->data()[n] = *first;
|
|
2374
|
+
++first;
|
|
2375
|
+
}
|
|
2376
|
+
else {
|
|
2377
|
+
block_alloc_traits::construct(
|
|
2378
|
+
al(), boost::movelib::to_raw_pointer(pb->data() + n), *first);
|
|
2379
|
+
++first;
|
|
2380
|
+
++size_;
|
|
2381
|
+
pb->mask |= bit;
|
|
2382
|
+
if(pb->mask == full) blist.unlink_available(pb);
|
|
2383
|
+
}
|
|
2384
|
+
if(first == last) goto exit;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
exit: ;
|
|
2388
|
+
}
|
|
2389
|
+
if(first != last) {
|
|
2390
|
+
priv_insert_range_copy(first, last);
|
|
2391
|
+
}
|
|
2392
|
+
else {
|
|
2393
|
+
erase( (n == -1) ? const_iterator(pbb, nest_detail::first_in_mask(pbb->mask)) : ++const_iterator(pbb, n)
|
|
2394
|
+
, cend());
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
void priv_assign_n(size_type count, const T& val)
|
|
2399
|
+
{
|
|
2400
|
+
typedef constant_iterator<T> const_it;
|
|
2401
|
+
this->priv_range_assign(const_it(val, count), const_it());
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
//////////////////////////////////////////////
|
|
2405
|
+
//
|
|
2406
|
+
// private: move assign
|
|
2407
|
+
//
|
|
2408
|
+
//////////////////////////////////////////////
|
|
2409
|
+
|
|
2410
|
+
void priv_move_assign(nest& x, dtl::true_type /* can transfer */)
|
|
2411
|
+
{
|
|
2412
|
+
dtl::bool_<allocator_traits_type::
|
|
2413
|
+
propagate_on_container_move_assignment::value> pocma;
|
|
2414
|
+
priv_reset();
|
|
2415
|
+
nest_detail::move_assign_if(pocma, al(), x.al());
|
|
2416
|
+
blist = boost::move(x.blist);
|
|
2417
|
+
num_blocks = x.num_blocks;
|
|
2418
|
+
size_ = x.size_;
|
|
2419
|
+
x.num_blocks = 0;
|
|
2420
|
+
x.size_ = 0;
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
void priv_move_assign(nest& x, dtl::false_type /* maybe move data */)
|
|
2424
|
+
{
|
|
2425
|
+
if(al() == x.al()) {
|
|
2426
|
+
priv_move_assign(x, dtl::true_type());
|
|
2427
|
+
}
|
|
2428
|
+
else {
|
|
2429
|
+
// Move-assign element by element
|
|
2430
|
+
priv_move_assign_elements(x);
|
|
2431
|
+
x.priv_reset();
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
void priv_move_assign_elements(nest& x)
|
|
2436
|
+
{
|
|
2437
|
+
this->priv_range_assign( boost::make_move_iterator(x.begin())
|
|
2438
|
+
, boost::make_move_iterator(x.end()) );
|
|
2439
|
+
x.clear();
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
//////////////////////////////////////////////
|
|
2443
|
+
//
|
|
2444
|
+
// private: swap
|
|
2445
|
+
//
|
|
2446
|
+
//////////////////////////////////////////////
|
|
2447
|
+
|
|
2448
|
+
void priv_swap_impl(nest& x, dtl::true_type /* propagate alloc */)
|
|
2449
|
+
{
|
|
2450
|
+
boost::adl_move_swap(al(), x.al());
|
|
2451
|
+
boost::adl_move_swap(blist, x.blist);
|
|
2452
|
+
boost::adl_move_swap(num_blocks, x.num_blocks);
|
|
2453
|
+
boost::adl_move_swap(size_, x.size_);
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
void priv_swap_impl(nest& x, dtl::false_type /* don't propagate */)
|
|
2457
|
+
{
|
|
2458
|
+
BOOST_ASSERT(al() == x.al());
|
|
2459
|
+
boost::adl_move_swap(blist, x.blist);
|
|
2460
|
+
boost::adl_move_swap(num_blocks, x.num_blocks);
|
|
2461
|
+
boost::adl_move_swap(size_, x.size_);
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
//////////////////////////////////////////////
|
|
2465
|
+
//
|
|
2466
|
+
// private: sort
|
|
2467
|
+
//
|
|
2468
|
+
//////////////////////////////////////////////
|
|
2469
|
+
|
|
2470
|
+
struct sort_proxy
|
|
2471
|
+
{
|
|
2472
|
+
T* p;
|
|
2473
|
+
size_type n;
|
|
2474
|
+
};
|
|
2475
|
+
|
|
2476
|
+
template<class Compare>
|
|
2477
|
+
void priv_sort_impl(Compare comp)
|
|
2478
|
+
{
|
|
2479
|
+
// Try transfer_sort for small element types
|
|
2480
|
+
BOOST_IF_CONSTEXPR(sizeof(T) <= sizeof(sort_proxy)) {
|
|
2481
|
+
if(priv_transfer_sort(comp)) return;
|
|
2482
|
+
}
|
|
2483
|
+
else {
|
|
2484
|
+
BOOST_STATIC_CONSTEXPR std::size_t memory_threshold = 2 * 1024 * 1024;
|
|
2485
|
+
if((std::size_t)size_ * sizeof(sort_proxy) <= memory_threshold) {
|
|
2486
|
+
if(priv_proxy_sort(comp)) return;
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
priv_compact_sort(comp);
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
template<class Compare>
|
|
2493
|
+
bool priv_transfer_sort(Compare comp)
|
|
2494
|
+
{
|
|
2495
|
+
if(size_ > 1) {
|
|
2496
|
+
nest_detail::buffer<T, block_allocator> buf(size_, al());
|
|
2497
|
+
if(!buf.data) return false;
|
|
2498
|
+
|
|
2499
|
+
// Move all elements to buffer
|
|
2500
|
+
priv_visit_all_move_to_buffer(buf);
|
|
2501
|
+
std::sort(buf.begin(), buf.end(), comp);
|
|
2502
|
+
// Move sorted elements back
|
|
2503
|
+
priv_visit_all_move_from_buffer(buf);
|
|
2504
|
+
}
|
|
2505
|
+
return true;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
void priv_visit_all_move_to_buffer(nest_detail::buffer<T, block_allocator>& buf)
|
|
2509
|
+
{
|
|
2510
|
+
block_base_pointer pbb = blist.next;
|
|
2511
|
+
while(pbb != blist.header()) {
|
|
2512
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
2513
|
+
pbb = pbb->next;
|
|
2514
|
+
mask_type m = pb->mask;
|
|
2515
|
+
while(m) {
|
|
2516
|
+
int n = nest_detail::first_in_mask(m);
|
|
2517
|
+
buf.push_back_move(pb->data()[n]);
|
|
2518
|
+
m &= m - 1;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
void priv_visit_all_move_from_buffer(nest_detail::buffer<T, block_allocator>& buf)
|
|
2524
|
+
{
|
|
2525
|
+
block_base_pointer pbb = blist.next;
|
|
2526
|
+
while(pbb != blist.header()) {
|
|
2527
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
2528
|
+
pbb = pbb->next;
|
|
2529
|
+
mask_type m = pb->mask;
|
|
2530
|
+
while(m) {
|
|
2531
|
+
int n = nest_detail::first_in_mask(m);
|
|
2532
|
+
pb->data()[n] = boost::move(*buf.begin());
|
|
2533
|
+
buf.erase_front();
|
|
2534
|
+
m &= m - 1;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
template<class Compare>
|
|
2540
|
+
bool priv_proxy_sort(Compare comp)
|
|
2541
|
+
{
|
|
2542
|
+
if(size_ > 1) {
|
|
2543
|
+
void* raw = ::operator new(size_ * sizeof(sort_proxy), std::nothrow);
|
|
2544
|
+
if(!raw) return false;
|
|
2545
|
+
nest_detail::raw_memory_holder holder(raw);
|
|
2546
|
+
sort_proxy* proxies = static_cast<sort_proxy*>(raw);
|
|
2547
|
+
|
|
2548
|
+
size_type i = 0;
|
|
2549
|
+
block_base_pointer pbb = blist.next;
|
|
2550
|
+
while(pbb != blist.header()) {
|
|
2551
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
2552
|
+
pbb = pbb->next;
|
|
2553
|
+
mask_type m = pb->mask;
|
|
2554
|
+
while(m) {
|
|
2555
|
+
int n = nest_detail::first_in_mask(m);
|
|
2556
|
+
proxies[i].p = boost::movelib::to_raw_pointer(pb->data() + n);
|
|
2557
|
+
proxies[i].n = i;
|
|
2558
|
+
++i;
|
|
2559
|
+
m &= m - 1;
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
nest_detail::sort_proxy_comparator<T, Compare> proxy_comp(comp);
|
|
2564
|
+
std::sort(proxies, proxies + size_, proxy_comp);
|
|
2565
|
+
|
|
2566
|
+
// Rearrange elements according to sorted proxy order
|
|
2567
|
+
for(i = 0; i < size_; ++i) {
|
|
2568
|
+
if(proxies[i].n != i) {
|
|
2569
|
+
T x = boost::move(*(proxies[i].p));
|
|
2570
|
+
size_type j = i;
|
|
2571
|
+
do {
|
|
2572
|
+
size_type k = proxies[j].n;
|
|
2573
|
+
*(proxies[j].p) = boost::move(*proxies[k].p);
|
|
2574
|
+
proxies[j].n = j;
|
|
2575
|
+
j = k;
|
|
2576
|
+
} while(proxies[j].n != i);
|
|
2577
|
+
*(proxies[j].p) = boost::move(x);
|
|
2578
|
+
proxies[j].n = j;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
return true;
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
template<class Compare>
|
|
2586
|
+
void priv_compact_sort(Compare comp)
|
|
2587
|
+
{
|
|
2588
|
+
typedef nest_detail::sort_iterator<T, N> sort_iter;
|
|
2589
|
+
|
|
2590
|
+
if(size_ > 1) {
|
|
2591
|
+
std::size_t nblocks = (std::size_t)((size_ + N - 1) / N);
|
|
2592
|
+
void* raw = ::operator new(nblocks * sizeof(T*));
|
|
2593
|
+
nest_detail::raw_memory_holder holder(raw);
|
|
2594
|
+
T** ptrs = static_cast<T**>(raw);
|
|
2595
|
+
|
|
2596
|
+
std::size_t idx = 0;
|
|
2597
|
+
priv_compact_with_tracking(ptrs, idx);
|
|
2598
|
+
BOOST_ASSERT(idx == nblocks);
|
|
2599
|
+
|
|
2600
|
+
std::sort( sort_iter(ptrs, 0)
|
|
2601
|
+
, sort_iter(ptrs, (std::ptrdiff_t)size_), comp);
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
//////////////////////////////////////////////
|
|
2606
|
+
//
|
|
2607
|
+
// private: compact
|
|
2608
|
+
//
|
|
2609
|
+
//////////////////////////////////////////////
|
|
2610
|
+
|
|
2611
|
+
void priv_compact_noop_track()
|
|
2612
|
+
{
|
|
2613
|
+
block_base_pointer pbbx = blist.next;
|
|
2614
|
+
while(pbbx != blist.header()) {
|
|
2615
|
+
block_pointer pbx = static_cast_block_pointer(pbbx);
|
|
2616
|
+
block_base_pointer pbby = pbbx->next;
|
|
2617
|
+
if(pbx->mask != full) {
|
|
2618
|
+
do {
|
|
2619
|
+
if(pbby->mask == full) {
|
|
2620
|
+
do {
|
|
2621
|
+
// skip full blocks (noop track)
|
|
2622
|
+
pbby = pbby->next;
|
|
2623
|
+
} while(pbby->mask == full);
|
|
2624
|
+
blist.unlink(pbx);
|
|
2625
|
+
blist.link_before(pbx, static_cast_block_pointer(pbby));
|
|
2626
|
+
}
|
|
2627
|
+
if(pbby == blist.header()) {
|
|
2628
|
+
priv_compact_single(pbx);
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2631
|
+
else {
|
|
2632
|
+
block_pointer pby = static_cast_block_pointer(pbby);
|
|
2633
|
+
priv_compact_pair(pbx, pby);
|
|
2634
|
+
if(pby->mask == 0) {
|
|
2635
|
+
pbby = pby->next;
|
|
2636
|
+
//pby was non-full (hence in the available list) and has
|
|
2637
|
+
//just been drained empty. Move it to the back so all
|
|
2638
|
+
//reserved blocks stay grouped there for trim_capacity.
|
|
2639
|
+
blist.unlink(pby);
|
|
2640
|
+
blist.unlink_available(pby);
|
|
2641
|
+
blist.link_available_at_back(pby);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
} while(pbx->mask != full);
|
|
2645
|
+
blist.unlink_available(pbx);
|
|
2646
|
+
}
|
|
2647
|
+
pbbx = pbby;
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
void priv_compact_with_tracking(T** ptrs, std::size_t& idx)
|
|
2652
|
+
{
|
|
2653
|
+
block_base_pointer pbbx = blist.next;
|
|
2654
|
+
while(pbbx != blist.header()) {
|
|
2655
|
+
block_pointer pbx = static_cast_block_pointer(pbbx);
|
|
2656
|
+
block_base_pointer pbby = pbbx->next;
|
|
2657
|
+
if(pbx->mask != full) {
|
|
2658
|
+
do {
|
|
2659
|
+
if(pbby->mask == full) {
|
|
2660
|
+
do {
|
|
2661
|
+
ptrs[idx++] = boost::movelib::to_raw_pointer(
|
|
2662
|
+
static_cast_block_pointer(pbby)->data());
|
|
2663
|
+
pbby = pbby->next;
|
|
2664
|
+
} while(pbby->mask == full);
|
|
2665
|
+
blist.unlink(pbx);
|
|
2666
|
+
blist.link_before(pbx, static_cast_block_pointer(pbby));
|
|
2667
|
+
}
|
|
2668
|
+
if(pbby == blist.header()) {
|
|
2669
|
+
priv_compact_single(pbx);
|
|
2670
|
+
ptrs[idx++] = boost::movelib::to_raw_pointer(pbx->data());
|
|
2671
|
+
return;
|
|
2672
|
+
}
|
|
2673
|
+
else {
|
|
2674
|
+
block_pointer pby = static_cast_block_pointer(pbby);
|
|
2675
|
+
priv_compact_pair(pbx, pby);
|
|
2676
|
+
if(pby->mask == 0) {
|
|
2677
|
+
pbby = pby->next;
|
|
2678
|
+
//pby was non-full (hence in the available list) and has
|
|
2679
|
+
//just been drained empty. Move it to the back so all
|
|
2680
|
+
//reserved blocks stay grouped there for trim_capacity.
|
|
2681
|
+
blist.unlink(pby);
|
|
2682
|
+
blist.unlink_available(pby);
|
|
2683
|
+
blist.link_available_at_back(pby);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
} while(pbx->mask != full);
|
|
2687
|
+
blist.unlink_available(pbx);
|
|
2688
|
+
}
|
|
2689
|
+
ptrs[idx++] = boost::movelib::to_raw_pointer(pbx->data());
|
|
2690
|
+
pbbx = pbby;
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
void priv_compact_pair(block_pointer pbx, block_pointer pby)
|
|
2695
|
+
{
|
|
2696
|
+
std::size_t cx = static_cast<std::size_t>(dtl::popcount(pbx->mask));
|
|
2697
|
+
std::size_t cy = static_cast<std::size_t>(dtl::popcount(pby->mask));
|
|
2698
|
+
if(cx < cy) {
|
|
2699
|
+
boost::adl_move_swap(cx, cy);
|
|
2700
|
+
nest_detail::swap_payload(*pbx, *pby);
|
|
2701
|
+
}
|
|
2702
|
+
std::size_t c = (std::min)(N - cx, cy);
|
|
2703
|
+
while(c--) {
|
|
2704
|
+
std::size_t n = static_cast<std::size_t>(dtl::unchecked_countr_one(pbx->mask));
|
|
2705
|
+
std::size_t m = static_cast<std::size_t>(nest_detail::last_in_mask(pby->mask));
|
|
2706
|
+
block_alloc_traits::construct(
|
|
2707
|
+
al(), boost::movelib::to_raw_pointer(pbx->data() + n),
|
|
2708
|
+
boost::move(pby->data()[m]));
|
|
2709
|
+
block_alloc_traits::destroy(
|
|
2710
|
+
al(), boost::movelib::to_raw_pointer(pby->data() + m));
|
|
2711
|
+
pbx->mask |= pbx->mask + 1;
|
|
2712
|
+
pby->mask &= ~((mask_type)(1) << m);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
void priv_compact_single(block_pointer pb)
|
|
2717
|
+
{
|
|
2718
|
+
for(; ;) {
|
|
2719
|
+
std::size_t n = (std::size_t)dtl::unchecked_countr_one(pb->mask);
|
|
2720
|
+
std::size_t m = static_cast<std::size_t>(nest_detail::last_in_mask(pb->mask));
|
|
2721
|
+
if(n > m) return;
|
|
2722
|
+
block_alloc_traits::construct(
|
|
2723
|
+
al(), boost::movelib::to_raw_pointer(pb->data() + n),
|
|
2724
|
+
boost::move(pb->data()[m]));
|
|
2725
|
+
block_alloc_traits::destroy(
|
|
2726
|
+
al(), boost::movelib::to_raw_pointer(pb->data() + m));
|
|
2727
|
+
pb->mask |= pb->mask + 1;
|
|
2728
|
+
pb->mask &= ~((mask_type)(1) << m);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
//////////////////////////////////////////////
|
|
2733
|
+
//
|
|
2734
|
+
// private: erase_if impl
|
|
2735
|
+
//
|
|
2736
|
+
//////////////////////////////////////////////
|
|
2737
|
+
|
|
2738
|
+
template<class Predicate>
|
|
2739
|
+
size_type priv_erase_if(Predicate pred)
|
|
2740
|
+
{
|
|
2741
|
+
size_type s = size_;
|
|
2742
|
+
block_base_pointer pbb = blist.next;
|
|
2743
|
+
while(pbb != blist.header()) {
|
|
2744
|
+
block_pointer pb = static_cast_block_pointer(pbb);
|
|
2745
|
+
pbb = pb->next;
|
|
2746
|
+
BOOST_IF_CONSTEXPR(prefetch_enabled) {
|
|
2747
|
+
BOOST_CONTAINER_NEST_PREFETCH(static_cast<block_type&>(*pbb).data());
|
|
2748
|
+
}
|
|
2749
|
+
mask_type m = pb->mask;
|
|
2750
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2751
|
+
do {
|
|
2752
|
+
int n = nest_detail::first_in_mask(m);
|
|
2753
|
+
if(pred(pb->data()[n])) priv_erase_impl(pb, n);
|
|
2754
|
+
m &= m - 1;
|
|
2755
|
+
} while(m);
|
|
2756
|
+
}
|
|
2757
|
+
return (size_type)(s - size_);
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
//////////////////////////////////////////////
|
|
2761
|
+
//
|
|
2762
|
+
// private: data members
|
|
2763
|
+
//
|
|
2764
|
+
//////////////////////////////////////////////
|
|
2765
|
+
|
|
2766
|
+
block_base blist;
|
|
2767
|
+
size_type num_blocks;
|
|
2768
|
+
size_type size_;
|
|
2769
|
+
|
|
2770
|
+
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
|
|
2771
|
+
};
|
|
2772
|
+
|
|
2773
|
+
//////////////////////////////////////////////
|
|
2774
|
+
//
|
|
2775
|
+
// free functions
|
|
2776
|
+
//
|
|
2777
|
+
//////////////////////////////////////////////
|
|
2778
|
+
|
|
2779
|
+
//! <b>Effects</b>: Swaps x and y.
|
|
2780
|
+
template<class T, class Allocator, class Options>
|
|
2781
|
+
inline void swap(nest<T, Allocator, Options>& x, nest<T, Allocator, Options>& y)
|
|
2782
|
+
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
|
|
2783
|
+
{
|
|
2784
|
+
x.swap(y);
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
//! <b>Effects</b>: Erases all elements for which pred returns true.
|
|
2788
|
+
//!
|
|
2789
|
+
//! <b>Returns</b>: The number of erased elements.
|
|
2790
|
+
template<class T, class Allocator, class Options, class Predicate>
|
|
2791
|
+
typename nest<T, Allocator, Options>::size_type
|
|
2792
|
+
erase_if(nest<T, Allocator, Options>& x, Predicate pred)
|
|
2793
|
+
{
|
|
2794
|
+
return x.priv_erase_if(pred);
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
//! <b>Effects</b>: Erases all elements equal to value.
|
|
2798
|
+
//!
|
|
2799
|
+
//! <b>Returns</b>: The number of erased elements.
|
|
2800
|
+
template<class T, class Allocator, class Options>
|
|
2801
|
+
typename nest<T, Allocator, Options>::size_type
|
|
2802
|
+
erase(nest<T, Allocator, Options>& x, const T& value)
|
|
2803
|
+
{
|
|
2804
|
+
return boost::container::erase_if(x, equal_to_value<T>(value));
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
//! <b>Effects</b>: Calls f(*it) for each iterator it in [first, last) until
|
|
2808
|
+
//! f(*it) returns false.
|
|
2809
|
+
//!
|
|
2810
|
+
//! <b>Returns</b>: A std::pair containing the iterator where visitation
|
|
2811
|
+
//! stopped (or last if all calls returned true) and the (possibly moved)
|
|
2812
|
+
//! functor f.
|
|
2813
|
+
//!
|
|
2814
|
+
//! <b>Complexity</b>: Linear in the distance between first and last.
|
|
2815
|
+
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch, class F>
|
|
2816
|
+
std::pair< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>, F >
|
|
2817
|
+
for_each_while
|
|
2818
|
+
( nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> first
|
|
2819
|
+
, nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> last
|
|
2820
|
+
, F f)
|
|
2821
|
+
{
|
|
2822
|
+
typedef nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> iter_t;
|
|
2823
|
+
typedef typename iter_t::block_base_pointer bbp_t;
|
|
2824
|
+
typedef typename iter_t::block_type block_t;
|
|
2825
|
+
typedef typename iter_t::nonconst_pointer value_ptr_t;
|
|
2826
|
+
typedef typename iter_t::mask_type mask_t;
|
|
2827
|
+
typedef std::pair<iter_t, F> result_type;
|
|
2828
|
+
|
|
2829
|
+
BOOST_STATIC_CONSTEXPR mask_t full = iter_t::full;
|
|
2830
|
+
|
|
2831
|
+
if(BOOST_UNLIKELY(first == last))
|
|
2832
|
+
return result_type(last, f);
|
|
2833
|
+
|
|
2834
|
+
bbp_t pbb = first.pbb;
|
|
2835
|
+
bbp_t const last_pbb = last.pbb;
|
|
2836
|
+
int const last_n = last.n;
|
|
2837
|
+
mask_t m = pbb->mask & (full << first.n);
|
|
2838
|
+
|
|
2839
|
+
for(; ;) {
|
|
2840
|
+
block_t& pbn = static_cast<block_t&>(*pbb->next);
|
|
2841
|
+
BOOST_IF_CONSTEXPR(Prefetch)
|
|
2842
|
+
BOOST_CONTAINER_NEST_PREFETCH(&pbn.mask);
|
|
2843
|
+
//Mask the mask for the last block
|
|
2844
|
+
const mask_t is_last = mask_t(pbb == last_pbb);
|
|
2845
|
+
m &= (is_last << last_n) - mask_t(1);
|
|
2846
|
+
|
|
2847
|
+
//Next block prefetch
|
|
2848
|
+
BOOST_IF_CONSTEXPR(Prefetch) {
|
|
2849
|
+
BOOST_CONTAINER_NEST_PREFETCH(&pbn.next->next);
|
|
2850
|
+
const int next_n = nest_detail::first_in_mask(pbn.mask);
|
|
2851
|
+
BOOST_CONTAINER_NEST_PREFETCH(pbn.data() + next_n);
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
//Mask can become zero if the last iterator is in the 0 position
|
|
2855
|
+
value_ptr_t const pd = block_t::static_cast_block_pointer(pbb)->data();
|
|
2856
|
+
|
|
2857
|
+
BOOST_CONTAINER_UNROLL(4)
|
|
2858
|
+
while(m) {
|
|
2859
|
+
int n = nest_detail::first_in_mask(m);
|
|
2860
|
+
if (!f(pd[n]))
|
|
2861
|
+
return result_type(iter_t(pbb, n), f);
|
|
2862
|
+
m &= m - 1;
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
if(is_last)
|
|
2866
|
+
return result_type(last, f);
|
|
2867
|
+
|
|
2868
|
+
pbb = pbb->next;
|
|
2869
|
+
m = pbb->mask;
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
//! <b>Effects</b>: Calls f(*it) for each iterator it in [first, last).
|
|
2874
|
+
//!
|
|
2875
|
+
//! <b>Returns</b>: The (possibly moved) functor f.
|
|
2876
|
+
//!
|
|
2877
|
+
//! <b>Complexity</b>: Linear in the distance between first and last.
|
|
2878
|
+
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch, class F>
|
|
2879
|
+
F for_each
|
|
2880
|
+
( nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> first
|
|
2881
|
+
, nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> last
|
|
2882
|
+
, F f)
|
|
2883
|
+
{
|
|
2884
|
+
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type
|
|
2885
|
+
element_t;
|
|
2886
|
+
nest_detail::for_each_adaptor<F, element_t> adaptor(f);
|
|
2887
|
+
(void)boost::container::for_each_while(first, last, adaptor);
|
|
2888
|
+
return f;
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
//! <b>Effects</b>: Calls f(x) for each element x in x.
|
|
2892
|
+
//!
|
|
2893
|
+
//! <b>Returns</b>: The (possibly moved) functor f.
|
|
2894
|
+
//!
|
|
2895
|
+
//! <b>Complexity</b>: Linear in the number of elements.
|
|
2896
|
+
template<class T, class Allocator, class Options, class F>
|
|
2897
|
+
F for_each(nest<T, Allocator, Options>& x, F f)
|
|
2898
|
+
{
|
|
2899
|
+
nest_detail::for_each_adaptor<F, T> adaptor(f);
|
|
2900
|
+
(void)boost::container::for_each_while(x.begin(), x.end(), adaptor);
|
|
2901
|
+
return f;
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
//! <b>Effects</b>: Calls f(x) for each const element x in x.
|
|
2905
|
+
//!
|
|
2906
|
+
//! <b>Returns</b>: The (possibly moved) functor f.
|
|
2907
|
+
//!
|
|
2908
|
+
//! <b>Complexity</b>: Linear in the number of elements.
|
|
2909
|
+
template<class T, class Allocator, class Options, class F>
|
|
2910
|
+
F for_each(const nest<T, Allocator, Options>& x, F f)
|
|
2911
|
+
{
|
|
2912
|
+
nest_detail::for_each_adaptor<F, const T> adaptor(f);
|
|
2913
|
+
(void)boost::container::for_each_while(x.begin(), x.end(), adaptor);
|
|
2914
|
+
return f;
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
//! <b>Effects</b>: Calls f(x) for each element x of x until f(x) returns false.
|
|
2918
|
+
//!
|
|
2919
|
+
//! <b>Returns</b>: A std::pair with the iterator where visitation stopped (or
|
|
2920
|
+
//! end() if all calls returned true) and the (possibly moved) functor f.
|
|
2921
|
+
//!
|
|
2922
|
+
//! <b>Complexity</b>: Linear in the number of elements.
|
|
2923
|
+
template<class T, class Allocator, class Options, class F>
|
|
2924
|
+
std::pair<typename nest<T, Allocator, Options>::iterator, F>
|
|
2925
|
+
for_each_while(nest<T, Allocator, Options>& x, F f)
|
|
2926
|
+
{
|
|
2927
|
+
typedef typename nest<T, Allocator, Options>::iterator iter_t;
|
|
2928
|
+
nest_detail::ref_predicate_adaptor<F, T> adaptor(f);
|
|
2929
|
+
iter_t const it = boost::container::for_each_while(
|
|
2930
|
+
x.begin(), x.end(), adaptor).first;
|
|
2931
|
+
return std::pair<iter_t, F>(it, f);
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
//! <b>Effects</b>: Calls f(x) for each const element x of x until f(x)
|
|
2935
|
+
//! returns false.
|
|
2936
|
+
//!
|
|
2937
|
+
//! <b>Returns</b>: A std::pair with the const_iterator where visitation
|
|
2938
|
+
//! stopped (or end() if all calls returned true) and the (possibly moved)
|
|
2939
|
+
//! functor f.
|
|
2940
|
+
//!
|
|
2941
|
+
//! <b>Complexity</b>: Linear in the number of elements.
|
|
2942
|
+
template<class T, class Allocator, class Options, class F>
|
|
2943
|
+
std::pair<typename nest<T, Allocator, Options>::const_iterator, F>
|
|
2944
|
+
for_each_while(const nest<T, Allocator, Options>& x, F f)
|
|
2945
|
+
{
|
|
2946
|
+
typedef typename nest<T, Allocator, Options>::const_iterator citer_t;
|
|
2947
|
+
nest_detail::ref_predicate_adaptor<F, const T> adaptor(f);
|
|
2948
|
+
citer_t const it = boost::container::for_each_while(
|
|
2949
|
+
x.begin(), x.end(), adaptor).first;
|
|
2950
|
+
return std::pair<citer_t, F>(it, f);
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
|
|
2954
|
+
|
|
2955
|
+
//! <b>Deduction guide</b>: allows a `nest` to be constructed from the iterator range
|
|
2956
|
+
//! <code>[first, last)</code>, deducing the element type from the value type of
|
|
2957
|
+
//! `InpIt` and optionally taking the allocator type from the supplied allocator.
|
|
2958
|
+
template<
|
|
2959
|
+
class InpIt,
|
|
2960
|
+
class Allocator = void
|
|
2961
|
+
>
|
|
2962
|
+
nest(InpIt, InpIt, Allocator = Allocator())
|
|
2963
|
+
-> nest<
|
|
2964
|
+
typename iterator_traits<InpIt>::value_type,
|
|
2965
|
+
Allocator,
|
|
2966
|
+
void>;
|
|
2967
|
+
|
|
2968
|
+
#endif
|
|
2969
|
+
|
|
2970
|
+
}} // namespace boost::container
|
|
2971
|
+
|
|
2972
|
+
#if defined(BOOST_MSVC)
|
|
2973
|
+
#pragma warning(pop) /* C4714 */
|
|
2974
|
+
#endif
|
|
2975
|
+
|
|
2976
|
+
#include <boost/container/detail/config_end.hpp>
|
|
2977
|
+
|
|
2978
|
+
#endif // BOOST_CONTAINER_EXPERIMENTAL_NEST_HPP
|