summaryrefslogtreecommitdiff
path: root/boost
diff options
context:
space:
mode:
Diffstat (limited to 'boost')
-rw-r--r--boost/atomic/detail/atomic_template.hpp16
-rw-r--r--boost/atomic/detail/config.hpp5
-rw-r--r--boost/atomic/detail/ops_emulated.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_alpha.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_arm.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_atomic.hpp5
-rw-r--r--boost/atomic/detail/ops_gcc_ppc.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_sparc.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_sync.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_x86.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_x86_dcas.hpp29
-rw-r--r--boost/atomic/detail/ops_linux_arm.hpp2
-rw-r--r--boost/atomic/detail/ops_msvc_arm.hpp2
-rw-r--r--boost/atomic/detail/ops_msvc_x86.hpp8
-rw-r--r--boost/atomic/detail/ops_windows.hpp2
-rw-r--r--boost/bind/arg.hpp13
-rw-r--r--boost/config/compiler/intel.hpp9
-rw-r--r--boost/config/compiler/nvcc.hpp8
-rw-r--r--boost/config/compiler/sunpro_cc.hpp2
-rw-r--r--boost/config/compiler/visualc.hpp19
-rw-r--r--boost/config/stdlib/dinkumware.hpp13
-rw-r--r--boost/config/stdlib/libcomo.hpp7
-rw-r--r--boost/config/stdlib/libcpp.hpp21
-rw-r--r--boost/config/stdlib/libstdcpp3.hpp19
-rw-r--r--boost/config/stdlib/modena.hpp7
-rw-r--r--boost/config/stdlib/msl.hpp7
-rw-r--r--boost/config/stdlib/roguewave.hpp7
-rw-r--r--boost/config/stdlib/sgi.hpp9
-rw-r--r--boost/config/stdlib/stlport.hpp7
-rw-r--r--boost/config/stdlib/vacpp.hpp7
-rw-r--r--boost/container/detail/copy_move_algo.hpp69
-rw-r--r--boost/container/detail/flat_tree.hpp2
-rw-r--r--boost/container/detail/iterators.hpp1
-rw-r--r--boost/container/detail/pair.hpp44
-rw-r--r--boost/container/detail/variadic_templates_tools.hpp26
-rw-r--r--boost/container/detail/workaround.hpp3
-rw-r--r--boost/container/uses_allocator_fwd.hpp4
-rw-r--r--boost/container/vector.hpp4
-rw-r--r--boost/context/detail/apply.hpp19
-rw-r--r--boost/context/detail/invoke.hpp4
-rw-r--r--boost/context/execution_context.hpp6
-rw-r--r--boost/context/execution_context_v1.hpp10
-rw-r--r--boost/context/execution_context_v2.hpp358
-rw-r--r--boost/context/execution_context_v2_void.ipp189
-rw-r--r--boost/convert.hpp2
-rw-r--r--boost/convert/base.hpp2
-rw-r--r--boost/convert/detail/boost_parameter_ext.hpp2
-rw-r--r--boost/convert/detail/char.hpp2
-rw-r--r--boost/convert/detail/forward.hpp2
-rw-r--r--boost/convert/detail/has_member.hpp2
-rw-r--r--boost/convert/detail/is_callable.hpp2
-rw-r--r--boost/convert/detail/is_converter.hpp2
-rw-r--r--boost/convert/detail/is_fun.hpp2
-rw-r--r--boost/convert/detail/is_string.hpp2
-rw-r--r--boost/convert/detail/range.hpp2
-rw-r--r--boost/convert/lexical_cast.hpp2
-rw-r--r--boost/convert/parameters.hpp2
-rw-r--r--boost/convert/printf.hpp2
-rw-r--r--boost/convert/spirit.hpp2
-rw-r--r--boost/convert/stream.hpp2
-rw-r--r--boost/convert/strtol.hpp36
-rw-r--r--boost/core/lightweight_test.hpp27
-rw-r--r--boost/coroutine/detail/config.hpp6
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv2.ipp12
-rw-r--r--boost/coroutine2/detail/pull_coroutine.hpp6
-rw-r--r--boost/coroutine2/detail/pull_coroutine.ipp6
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv2.ipp12
-rw-r--r--boost/coroutine2/detail/push_coroutine.hpp6
-rw-r--r--boost/coroutine2/detail/push_coroutine.ipp6
-rw-r--r--boost/current_function.hpp6
-rw-r--r--boost/date_time/gregorian/greg_facet.hpp20
-rw-r--r--boost/date_time/gregorian/greg_serialize.hpp5
-rw-r--r--boost/detail/winapi/file_management.hpp24
-rw-r--r--boost/detail/winapi/system.hpp10
-rw-r--r--boost/exception/detail/error_info_impl.hpp4
-rw-r--r--boost/exception/detail/shared_ptr.hpp17
-rw-r--r--boost/exception/errinfo_api_function.hpp2
-rw-r--r--boost/exception/errinfo_errno.hpp2
-rw-r--r--boost/exception/exception.hpp11
-rw-r--r--boost/exception/get_error_info.hpp3
-rw-r--r--boost/exception/info.hpp166
-rw-r--r--boost/fiber/algo/work_stealing.hpp82
-rw-r--r--boost/fiber/all.hpp10
-rw-r--r--boost/fiber/bounded_channel.hpp2
-rw-r--r--boost/fiber/buffered_channel.hpp589
-rw-r--r--boost/fiber/channel_op_status.hpp6
-rw-r--r--boost/fiber/condition_variable.hpp2
-rw-r--r--boost/fiber/context.hpp22
-rw-r--r--boost/fiber/detail/config.hpp27
-rw-r--r--boost/fiber/detail/context_mpsc_queue.hpp98
-rw-r--r--boost/fiber/detail/context_spmc_queue.hpp158
-rw-r--r--boost/fiber/detail/cpu_relax.hpp56
-rw-r--r--boost/fiber/detail/data.hpp2
-rw-r--r--boost/fiber/detail/futex.hpp61
-rw-r--r--boost/fiber/detail/spinlock.hpp49
-rw-r--r--boost/fiber/detail/spinlock_ttas.hpp112
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive.hpp117
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp111
-rw-r--r--boost/fiber/detail/spinlock_ttas_futex.hpp104
-rw-r--r--boost/fiber/detail/wrap.hpp7
-rw-r--r--boost/fiber/fiber.hpp2
-rw-r--r--boost/fiber/future/async.hpp3
-rw-r--r--boost/fiber/future/detail/shared_state.hpp2
-rw-r--r--boost/fiber/future/future.hpp14
-rw-r--r--boost/fiber/scheduler.hpp15
-rw-r--r--boost/fiber/unbounded_channel.hpp2
-rw-r--r--boost/fiber/unbuffered_channel.hpp540
-rw-r--r--boost/filesystem/operations.hpp79
-rw-r--r--boost/filesystem/path.hpp63
-rw-r--r--boost/format/alt_sstream_impl.hpp4
-rw-r--r--boost/functional/hash/detail/hash_float.hpp2
-rw-r--r--boost/functional/hash/hash.hpp12
-rw-r--r--boost/fusion/adapted/std_array.hpp23
-rw-r--r--boost/fusion/adapted/std_array/detail/array_size.hpp25
-rw-r--r--boost/fusion/adapted/std_array/detail/at_impl.hpp45
-rw-r--r--boost/fusion/adapted/std_array/detail/begin_impl.hpp41
-rw-r--r--boost/fusion/adapted/std_array/detail/category_of_impl.hpp35
-rw-r--r--boost/fusion/adapted/std_array/detail/end_impl.hpp45
-rw-r--r--boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp32
-rw-r--r--boost/fusion/adapted/std_array/detail/is_view_impl.hpp33
-rw-r--r--boost/fusion/adapted/std_array/detail/size_impl.hpp41
-rw-r--r--boost/fusion/adapted/std_array/detail/value_at_impl.hpp32
-rw-r--r--boost/fusion/adapted/std_array/std_array_iterator.hpp109
-rw-r--r--boost/fusion/adapted/std_array/tag_of.hpp52
-rw-r--r--boost/fusion/adapted/struct/detail/define_struct.hpp162
-rw-r--r--boost/fusion/container/deque/detail/keyed_element.hpp10
-rw-r--r--boost/fusion/container/vector/detail/config.hpp2
-rw-r--r--boost/fusion/container/vector/vector.hpp169
-rw-r--r--boost/fusion/support/detail/and.hpp39
-rw-r--r--boost/fusion/tuple/tuple.hpp37
-rw-r--r--boost/fusion/view/zip_view/zip_view.hpp2
-rw-r--r--boost/geometry/algorithms/detail/azimuth.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp100
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrichment_info.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp111
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp273
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp57
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp70
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp3
-rw-r--r--boost/geometry/algorithms/detail/result_inverse.hpp44
-rw-r--r--boost/geometry/algorithms/detail/thomas_inverse.hpp191
-rw-r--r--boost/geometry/extensions/algorithms/inverse.hpp59
-rw-r--r--boost/geometry/formulas/andoyer_inverse.hpp (renamed from boost/geometry/algorithms/detail/andoyer_inverse.hpp)150
-rw-r--r--boost/geometry/formulas/differential_quantities.hpp300
-rw-r--r--boost/geometry/formulas/gnomonic_intersection.hpp148
-rw-r--r--boost/geometry/formulas/gnomonic_spheroid.hpp126
-rw-r--r--boost/geometry/formulas/result_direct.hpp39
-rw-r--r--boost/geometry/formulas/result_inverse.hpp39
-rw-r--r--boost/geometry/formulas/sjoberg_intersection.hpp385
-rw-r--r--boost/geometry/formulas/thomas_direct.hpp249
-rw-r--r--boost/geometry/formulas/thomas_inverse.hpp221
-rw-r--r--boost/geometry/formulas/vincenty_direct.hpp (renamed from boost/geometry/algorithms/detail/vincenty_direct.hpp)78
-rw-r--r--boost/geometry/formulas/vincenty_inverse.hpp (renamed from boost/geometry/algorithms/detail/vincenty_inverse.hpp)66
-rw-r--r--boost/geometry/geometries/adapted/std_array.hpp115
-rw-r--r--boost/geometry/index/detail/predicates.hpp6
-rw-r--r--boost/geometry/index/predicates.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp35
-rw-r--r--boost/geometry/strategies/cartesian/point_in_box.hpp44
-rw-r--r--boost/geometry/strategies/geographic/distance_andoyer.hpp5
-rw-r--r--boost/geometry/strategies/geographic/distance_thomas.hpp8
-rw-r--r--boost/geometry/strategies/geographic/distance_vincenty.hpp8
-rw-r--r--boost/geometry/strategies/geographic/side_andoyer.hpp10
-rw-r--r--boost/geometry/strategies/geographic/side_detail.hpp8
-rw-r--r--boost/geometry/strategies/geographic/side_thomas.hpp10
-rw-r--r--boost/geometry/strategies/geographic/side_vincenty.hpp10
-rw-r--r--boost/graph/adjacency_iterator.hpp1
-rw-r--r--boost/graph/adjacency_list.hpp25
-rw-r--r--boost/graph/detail/read_graphviz_new.hpp2
-rw-r--r--boost/graph/detail/read_graphviz_spirit.hpp2
-rw-r--r--boost/graph/distributed/mpi_process_group.hpp1
-rw-r--r--boost/graph/graph_utility.hpp58
-rw-r--r--boost/graph/gursoy_atun_layout.hpp7
-rw-r--r--boost/graph/properties.hpp7
-rw-r--r--boost/graph/random.hpp1
-rw-r--r--boost/graph/reverse_graph.hpp7
-rw-r--r--boost/graph/vf2_sub_graph_iso.hpp15
-rw-r--r--boost/hana/at.hpp2
-rw-r--r--boost/hana/basic_tuple.hpp5
-rw-r--r--boost/hana/bool.hpp17
-rw-r--r--boost/hana/concept.hpp1
-rw-r--r--boost/hana/concept/applicative.hpp12
-rw-r--r--boost/hana/concept/comonad.hpp14
-rw-r--r--boost/hana/concept/comparable.hpp11
-rw-r--r--boost/hana/concept/constant.hpp10
-rw-r--r--boost/hana/concept/euclidean_ring.hpp14
-rw-r--r--boost/hana/concept/foldable.hpp12
-rw-r--r--boost/hana/concept/functor.hpp14
-rw-r--r--boost/hana/concept/group.hpp13
-rw-r--r--boost/hana/concept/hashable.hpp10
-rw-r--r--boost/hana/concept/integral_constant.hpp15
-rw-r--r--boost/hana/concept/iterable.hpp16
-rw-r--r--boost/hana/concept/logical.hpp14
-rw-r--r--boost/hana/concept/metafunction.hpp15
-rw-r--r--boost/hana/concept/monad.hpp12
-rw-r--r--boost/hana/concept/monad_plus.hpp12
-rw-r--r--boost/hana/concept/monoid.hpp13
-rw-r--r--boost/hana/concept/orderable.hpp11
-rw-r--r--boost/hana/concept/product.hpp12
-rw-r--r--boost/hana/concept/ring.hpp13
-rw-r--r--boost/hana/concept/searchable.hpp12
-rw-r--r--boost/hana/concept/sequence.hpp15
-rw-r--r--boost/hana/concept/struct.hpp10
-rw-r--r--boost/hana/config.hpp6
-rw-r--r--boost/hana/detail/concepts.hpp2
-rw-r--r--boost/hana/detail/integral_constant.hpp245
-rw-r--r--boost/hana/detail/type_at.hpp57
-rw-r--r--boost/hana/drop_front.hpp2
-rw-r--r--boost/hana/equal.hpp16
-rw-r--r--boost/hana/experimental/printable.hpp14
-rw-r--r--boost/hana/experimental/type_name.hpp64
-rw-r--r--boost/hana/experimental/types.hpp32
-rw-r--r--boost/hana/ext/std/array.hpp2
-rw-r--r--boost/hana/ext/std/integral_constant.hpp2
-rw-r--r--boost/hana/fwd/concept/comparable.hpp13
-rw-r--r--boost/hana/fwd/integral_constant.hpp226
-rw-r--r--boost/hana/fwd/map.hpp50
-rw-r--r--boost/hana/fwd/string.hpp33
-rw-r--r--boost/hana/fwd/type.hpp10
-rw-r--r--boost/hana/length.hpp4
-rw-r--r--boost/hana/map.hpp69
-rw-r--r--boost/hana/string.hpp45
-rw-r--r--boost/hana/version.hpp2
-rw-r--r--boost/interprocess/detail/nothrow.hpp3
-rwxr-xr-x[-rw-r--r--]boost/interprocess/detail/shared_dir_helpers.hpp25
-rw-r--r--boost/interprocess/detail/workaround.hpp3
-rw-r--r--boost/interprocess/mapped_region.hpp5
-rw-r--r--boost/interprocess/streams/bufferstream.hpp24
-rw-r--r--boost/interprocess/xsi_key.hpp8
-rw-r--r--boost/intrusive/detail/hashtable_node.hpp27
-rw-r--r--boost/intrusive/detail/workaround.hpp3
-rw-r--r--boost/intrusive/member_value_traits.hpp1
-rw-r--r--boost/intrusive/unordered_set.hpp56
-rw-r--r--boost/iostreams/detail/config/fpos.hpp12
-rw-r--r--boost/iostreams/positioning.hpp6
-rw-r--r--boost/lexical_cast/detail/converter_lexical_streams.hpp64
-rw-r--r--boost/lexical_cast/detail/converter_numeric.hpp34
-rw-r--r--boost/lockfree/detail/prefix.hpp7
-rw-r--r--boost/lockfree/queue.hpp2
-rw-r--r--boost/lockfree/stack.hpp4
-rw-r--r--boost/log/keywords/enable_final_rotation.hpp40
-rw-r--r--boost/log/sinks/text_file_backend.hpp30
-rw-r--r--boost/log/sources/record_ostream.hpp203
-rw-r--r--boost/log/utility/formatting_ostream.hpp47
-rw-r--r--boost/log/utility/setup/filter_parser.hpp4
-rw-r--r--boost/log/utility/type_info_wrapper.hpp194
-rw-r--r--boost/make_default.hpp2
-rw-r--r--boost/math/common_factor_rt.hpp6
-rw-r--r--boost/math/special_functions/gamma.hpp6
-rw-r--r--boost/math/tools/polynomial.hpp2
-rw-r--r--boost/math/tools/tuple.hpp1
-rw-r--r--boost/math/tr1.hpp2
-rw-r--r--boost/metaparse.hpp5
-rw-r--r--boost/metaparse/string.hpp8
-rw-r--r--boost/metaparse/v1/impl/split_at_c.hpp6
-rw-r--r--boost/metaparse/v1/impl/string.hpp2125
-rw-r--r--boost/metaparse/v1/impl/string_at.hpp41
-rw-r--r--boost/metaparse/v1/string.hpp64
-rw-r--r--boost/move/algo/detail/adaptive_sort_merge.hpp1761
-rw-r--r--boost/move/algo/detail/basic_op.hpp40
-rw-r--r--boost/move/algo/detail/bufferless_merge_sort.hpp120
-rw-r--r--boost/move/algo/detail/merge.hpp48
-rw-r--r--boost/move/detail/move_helpers.hpp50
-rw-r--r--boost/move/detail/workaround.hpp5
-rw-r--r--boost/move/make_unique.hpp3
-rw-r--r--boost/mpi/communicator.hpp74
-rw-r--r--boost/mpi/datatype.hpp13
-rw-r--r--boost/multiprecision/concepts/mp_number_archetypes.hpp1
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp89
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp9
-rw-r--r--boost/multiprecision/cpp_int/misc.hpp1
-rw-r--r--boost/multiprecision/detail/default_ops.hpp898
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp28
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp71
-rw-r--r--boost/multiprecision/detail/integer_ops.hpp14
-rw-r--r--boost/multiprecision/detail/number_base.hpp20
-rw-r--r--boost/multiprecision/detail/number_compare.hpp178
-rw-r--r--boost/multiprecision/float128.hpp106
-rw-r--r--boost/multiprecision/gmp.hpp12
-rw-r--r--boost/multiprecision/mpfi.hpp89
-rw-r--r--boost/multiprecision/mpfr.hpp178
-rw-r--r--boost/multiprecision/number.hpp26
-rw-r--r--boost/multiprecision/rational_adaptor.hpp1
-rw-r--r--boost/optional/detail/optional_config.hpp17
-rw-r--r--boost/optional/detail/optional_reference_spec.hpp78
-rw-r--r--boost/optional/optional.hpp295
-rw-r--r--boost/pending/container_traits.hpp29
-rw-r--r--boost/phoenix/bind/bind_function.hpp148
-rw-r--r--boost/phoenix/bind/bind_function_object.hpp75
-rw-r--r--boost/phoenix/bind/bind_member_function.hpp287
-rw-r--r--boost/phoenix/bind/detail/cpp03/bind_function.hpp113
-rw-r--r--boost/phoenix/bind/detail/cpp03/bind_function_object.hpp74
-rw-r--r--boost/phoenix/bind/detail/cpp03/bind_member_function.hpp251
-rw-r--r--boost/phoenix/bind/detail/cpp03/function_ptr.hpp (renamed from boost/phoenix/bind/detail/function_ptr.hpp)9
-rw-r--r--boost/phoenix/bind/detail/cpp03/member_function_ptr.hpp (renamed from boost/phoenix/bind/detail/member_function_ptr.hpp)9
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function.hpp)10
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_10.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_10.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_20.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_20.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_30.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_30.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_40.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_40.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_50.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_50.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object.hpp)10
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_10.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object_10.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_20.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object_20.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_30.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object_30.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_40.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object_40.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_function_object_50.hpp (renamed from boost/phoenix/bind/preprocessed/bind_function_object_50.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function.hpp)10
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function_10.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function_10.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function_20.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function_20.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function_30.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function_30.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function_40.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function_40.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/bind_member_function_50.hpp (renamed from boost/phoenix/bind/preprocessed/bind_member_function_50.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr.hpp)10
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr_10.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr_10.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr_20.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr_20.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr_30.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr_30.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr_40.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr_40.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/function_ptr_50.hpp (renamed from boost/phoenix/bind/detail/preprocessed/function_ptr_50.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr.hpp)10
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr_10.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr_10.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr_20.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr_20.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr_30.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr_30.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr_40.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr_40.hpp)0
-rw-r--r--boost/phoenix/bind/detail/cpp03/preprocessed/member_function_ptr_50.hpp (renamed from boost/phoenix/bind/detail/preprocessed/member_function_ptr_50.hpp)0
-rw-r--r--boost/phoenix/config.hpp7
-rw-r--r--boost/phoenix/core/actor.hpp220
-rw-r--r--boost/phoenix/core/argument.hpp6
-rw-r--r--boost/phoenix/core/call.hpp65
-rw-r--r--boost/phoenix/core/detail/cpp03/actor_operator.hpp (renamed from boost/phoenix/core/detail/actor_operator.hpp)4
-rw-r--r--boost/phoenix/core/detail/cpp03/actor_result_of.hpp (renamed from boost/phoenix/core/detail/actor_result_of.hpp)21
-rw-r--r--boost/phoenix/core/detail/cpp03/assign.hpp97
-rw-r--r--boost/phoenix/core/detail/cpp03/call.hpp (renamed from boost/phoenix/core/detail/call.hpp)7
-rw-r--r--boost/phoenix/core/detail/cpp03/expression.hpp111
-rw-r--r--boost/phoenix/core/detail/cpp03/function_equal.hpp77
-rw-r--r--boost/phoenix/core/detail/cpp03/function_eval.hpp124
-rw-r--r--boost/phoenix/core/detail/cpp03/function_eval_expr.hpp39
-rw-r--r--boost/phoenix/core/detail/cpp03/phx2_result.hpp73
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator_10.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator_10.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator_20.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator_20.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator_30.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator_30.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator_40.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator_40.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_operator_50.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_operator_50.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of_10.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of_10.hpp)15
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of_20.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of_20.hpp)15
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of_30.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of_30.hpp)15
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of_40.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of_40.hpp)15
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/actor_result_of_50.hpp (renamed from boost/phoenix/core/detail/preprocessed/actor_result_of_50.hpp)15
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument.hpp (renamed from boost/phoenix/core/preprocessed/argument.hpp)20
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_no_predefined_10.hpp (renamed from boost/phoenix/core/preprocessed/argument_no_predefined_10.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_no_predefined_20.hpp (renamed from boost/phoenix/core/preprocessed/argument_no_predefined_20.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_no_predefined_30.hpp (renamed from boost/phoenix/core/preprocessed/argument_no_predefined_30.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_no_predefined_40.hpp (renamed from boost/phoenix/core/preprocessed/argument_no_predefined_40.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_no_predefined_50.hpp (renamed from boost/phoenix/core/preprocessed/argument_no_predefined_50.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_predefined_10.hpp (renamed from boost/phoenix/core/preprocessed/argument_predefined_10.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_predefined_20.hpp (renamed from boost/phoenix/core/preprocessed/argument_predefined_20.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_predefined_30.hpp (renamed from boost/phoenix/core/preprocessed/argument_predefined_30.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_predefined_40.hpp (renamed from boost/phoenix/core/preprocessed/argument_predefined_40.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/argument_predefined_50.hpp (renamed from boost/phoenix/core/preprocessed/argument_predefined_50.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign.hpp (renamed from boost/phoenix/core/preprocessed/actor.hpp)14
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign_10.hpp (renamed from boost/phoenix/core/preprocessed/actor_10.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign_20.hpp (renamed from boost/phoenix/core/preprocessed/actor_20.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign_30.hpp (renamed from boost/phoenix/core/preprocessed/actor_30.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign_40.hpp (renamed from boost/phoenix/core/preprocessed/actor_40.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/assign_50.hpp (renamed from boost/phoenix/core/preprocessed/actor_50.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call.hpp (renamed from boost/phoenix/core/detail/preprocessed/call.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call_10.hpp (renamed from boost/phoenix/core/detail/preprocessed/call_10.hpp)3
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call_20.hpp (renamed from boost/phoenix/core/detail/preprocessed/call_20.hpp)3
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call_30.hpp (renamed from boost/phoenix/core/detail/preprocessed/call_30.hpp)3
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call_40.hpp (renamed from boost/phoenix/core/detail/preprocessed/call_40.hpp)3
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/call_50.hpp (renamed from boost/phoenix/core/detail/preprocessed/call_50.hpp)3
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression.hpp (renamed from boost/phoenix/core/preprocessed/expression.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression_10.hpp (renamed from boost/phoenix/core/preprocessed/expression_10.hpp)27
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression_20.hpp (renamed from boost/phoenix/core/preprocessed/expression_20.hpp)47
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression_30.hpp (renamed from boost/phoenix/core/preprocessed/expression_30.hpp)67
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression_40.hpp (renamed from boost/phoenix/core/preprocessed/expression_40.hpp)87
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/expression_50.hpp (renamed from boost/phoenix/core/preprocessed/expression_50.hpp)107
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal.hpp (renamed from boost/phoenix/core/preprocessed/function_equal.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal_10.hpp (renamed from boost/phoenix/core/preprocessed/function_equal_10.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal_20.hpp (renamed from boost/phoenix/core/preprocessed/function_equal_20.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal_30.hpp (renamed from boost/phoenix/core/preprocessed/function_equal_30.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal_40.hpp (renamed from boost/phoenix/core/preprocessed/function_equal_40.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_equal_50.hpp (renamed from boost/phoenix/core/preprocessed/function_equal_50.hpp)0
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_10.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval_10.hpp)50
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_20.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval_20.hpp)50
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_30.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval_30.hpp)50
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_40.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval_40.hpp)50
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_50.hpp (renamed from boost/phoenix/core/detail/preprocessed/function_eval_50.hpp)50
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr.hpp25
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr_10.hpp8
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr_20.hpp8
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr_30.hpp8
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr_40.hpp8
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/function_eval_expr_50.hpp8
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result.hpp)10
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result_10.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result_10.hpp)18
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result_20.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result_20.hpp)38
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result_30.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result_30.hpp)58
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result_40.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result_40.hpp)78
-rw-r--r--boost/phoenix/core/detail/cpp03/preprocessed/phx2_result_50.hpp (renamed from boost/phoenix/core/detail/preprocessed/phx2_result_50.hpp)98
-rw-r--r--boost/phoenix/core/detail/expression.hpp56
-rw-r--r--boost/phoenix/core/detail/function_eval.hpp194
-rw-r--r--boost/phoenix/core/detail/index_sequence.hpp17
-rw-r--r--boost/phoenix/core/detail/phx2_result.hpp80
-rw-r--r--boost/phoenix/core/expression.hpp128
-rw-r--r--boost/phoenix/core/function_equal.hpp96
-rw-r--r--boost/phoenix/core/limits.hpp37
-rw-r--r--boost/phoenix/function/detail/cpp03/function_operator.hpp (renamed from boost/phoenix/function/detail/function_operator.hpp)4
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator.hpp)10
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator_10.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator_10.hpp)0
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator_20.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator_20.hpp)0
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator_30.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator_30.hpp)0
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator_40.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator_40.hpp)0
-rw-r--r--boost/phoenix/function/detail/cpp03/preprocessed/function_operator_50.hpp (renamed from boost/phoenix/function/detail/preprocessed/function_operator_50.hpp)0
-rw-r--r--boost/phoenix/function/function.hpp16
-rw-r--r--boost/phoenix/function/lazy_list.hpp4
-rw-r--r--boost/phoenix/object/construct.hpp20
-rw-r--r--boost/phoenix/object/detail/cpp03/construct.hpp (renamed from boost/phoenix/object/detail/construct.hpp)4
-rw-r--r--boost/phoenix/object/detail/cpp03/construct_eval.hpp (renamed from boost/phoenix/object/detail/construct_eval.hpp)4
-rw-r--r--boost/phoenix/object/detail/cpp03/construct_expr.hpp34
-rw-r--r--boost/phoenix/object/detail/cpp03/new.hpp (renamed from boost/phoenix/object/detail/new.hpp)4
-rw-r--r--boost/phoenix/object/detail/cpp03/new_eval.hpp (renamed from boost/phoenix/object/detail/new_eval.hpp)4
-rw-r--r--boost/phoenix/object/detail/cpp03/new_expr.hpp34
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct.hpp)10
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_10.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_10.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_20.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_20.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_30.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_30.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_40.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_40.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_50.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_50.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval.hpp)10
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval_10.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval_10.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval_20.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval_20.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval_30.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval_30.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval_40.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval_40.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_eval_50.hpp (renamed from boost/phoenix/object/detail/preprocessed/construct_eval_50.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr.hpp25
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr_10.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr_20.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr_30.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr_40.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/construct_expr_50.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new.hpp (renamed from boost/phoenix/object/detail/preprocessed/new.hpp)10
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_10.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_10.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_20.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_20.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_30.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_30.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_40.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_40.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_50.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_50.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval.hpp)10
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval_10.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval_10.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval_20.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval_20.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval_30.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval_30.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval_40.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval_40.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_eval_50.hpp (renamed from boost/phoenix/object/detail/preprocessed/new_eval_50.hpp)0
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr.hpp25
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr_10.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr_20.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr_30.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr_40.hpp7
-rw-r--r--boost/phoenix/object/detail/cpp03/preprocessed/new_expr_50.hpp7
-rw-r--r--boost/phoenix/object/new.hpp18
-rw-r--r--boost/phoenix/operator/detail/cpp03/mem_fun_ptr_eval.hpp78
-rw-r--r--boost/phoenix/operator/detail/cpp03/mem_fun_ptr_eval_result_of.hpp (renamed from boost/phoenix/operator/detail/mem_fun_ptr_eval_result_of.hpp)2
-rw-r--r--boost/phoenix/operator/detail/cpp03/mem_fun_ptr_expr.hpp33
-rw-r--r--boost/phoenix/operator/detail/cpp03/mem_fun_ptr_gen.hpp (renamed from boost/phoenix/operator/detail/mem_fun_ptr_gen.hpp)23
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval.hpp25
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_10.hpp (renamed from boost/phoenix/operator/preprocessed/member_10.hpp)218
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_20.hpp (renamed from boost/phoenix/operator/preprocessed/member_20.hpp)418
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_30.hpp878
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_40.hpp (renamed from boost/phoenix/operator/preprocessed/member_30.hpp)918
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_50.hpp (renamed from boost/phoenix/operator/preprocessed/member_40.hpp)1118
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_eval_result_of.hpp25
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr.hpp25
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr_10.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen_10.hpp)233
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr_20.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen_20.hpp)443
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr_30.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen_30.hpp)653
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr_40.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen_40.hpp)863
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_expr_50.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen_50.hpp)1073
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen.hpp (renamed from boost/phoenix/operator/detail/preprocessed/mem_fun_ptr_gen.hpp)10
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen_10.hpp234
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen_20.hpp444
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen_30.hpp654
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen_40.hpp864
-rw-r--r--boost/phoenix/operator/detail/cpp03/preprocessed/mem_fun_ptr_gen_50.hpp1074
-rw-r--r--boost/phoenix/operator/member.hpp108
-rw-r--r--boost/phoenix/operator/preprocessed/member.hpp25
-rw-r--r--boost/phoenix/operator/preprocessed/member_50.hpp2494
-rw-r--r--boost/phoenix/scope/detail/cpp03/dynamic.hpp (renamed from boost/phoenix/scope/detail/dynamic.hpp)4
-rw-r--r--boost/phoenix/scope/detail/cpp03/lambda.hpp39
-rw-r--r--boost/phoenix/scope/detail/cpp03/local_gen.hpp66
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic.hpp)10
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic_10.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic_10.hpp)0
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic_20.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic_20.hpp)0
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic_30.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic_30.hpp)0
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic_40.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic_40.hpp)0
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/dynamic_50.hpp (renamed from boost/phoenix/scope/detail/preprocessed/dynamic_50.hpp)0
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda.hpp (renamed from boost/phoenix/scope/preprocessed/lambda.hpp)10
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda_10.hpp (renamed from boost/phoenix/scope/preprocessed/lambda_10.hpp)293
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda_20.hpp (renamed from boost/phoenix/scope/preprocessed/lambda_20.hpp)293
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda_30.hpp (renamed from boost/phoenix/scope/preprocessed/lambda_30.hpp)293
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda_40.hpp (renamed from boost/phoenix/scope/preprocessed/lambda_40.hpp)293
-rw-r--r--boost/phoenix/scope/detail/cpp03/preprocessed/lambda_50.hpp (renamed from boost/phoenix/scope/preprocessed/lambda_50.hpp)293
-rw-r--r--boost/phoenix/scope/detail/local_gen.hpp73
-rw-r--r--boost/phoenix/scope/detail/make_locals.hpp108
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals.hpp25
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals_10.hpp227
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals_20.hpp447
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals_30.hpp667
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals_40.hpp887
-rw-r--r--boost/phoenix/scope/detail/preprocessed/make_locals_50.hpp1107
-rw-r--r--boost/phoenix/scope/dynamic.hpp10
-rw-r--r--boost/phoenix/scope/lambda.hpp51
-rw-r--r--boost/phoenix/scope/let.hpp4
-rw-r--r--boost/phoenix/statement/detail/preprocessed/try_catch_eval_10.hpp30
-rw-r--r--boost/phoenix/statement/detail/preprocessed/try_catch_eval_20.hpp60
-rw-r--r--boost/phoenix/statement/detail/preprocessed/try_catch_eval_30.hpp90
-rw-r--r--boost/phoenix/statement/detail/preprocessed/try_catch_eval_40.hpp120
-rw-r--r--boost/phoenix/statement/detail/preprocessed/try_catch_eval_50.hpp150
-rw-r--r--boost/phoenix/statement/detail/try_catch_eval.hpp3
-rw-r--r--boost/phoenix/statement/try_catch.hpp4
-rw-r--r--boost/phoenix/stl/algorithm/detail/has_find.hpp10
-rw-r--r--boost/phoenix/stl/algorithm/detail/is_unordered_set_or_map.hpp55
-rw-r--r--boost/phoenix/stl/container/container.hpp68
-rw-r--r--boost/phoenix/stl/container/detail/container.hpp20
-rw-r--r--boost/phoenix/support/preprocessed/vector_10.hpp109
-rw-r--r--boost/phoenix/support/preprocessed/vector_20.hpp199
-rw-r--r--boost/phoenix/support/preprocessed/vector_30.hpp289
-rw-r--r--boost/phoenix/support/preprocessed/vector_40.hpp379
-rw-r--r--boost/phoenix/support/preprocessed/vector_50.hpp469
-rw-r--r--boost/phoenix/support/vector.hpp22
-rw-r--r--boost/pointer_cast.hpp76
-rw-r--r--boost/property_map/parallel/parallel_property_maps.hpp1
-rw-r--r--boost/property_map/property_map.hpp31
-rw-r--r--boost/python/converter/registered.hpp37
-rw-r--r--boost/python/converter/shared_ptr_from_python.hpp80
-rw-r--r--boost/python/converter/shared_ptr_to_python.hpp29
-rwxr-xr-xboost/python/detail/is_shared_ptr.hpp18
-rw-r--r--boost/python/detail/value_is_shared_ptr.hpp23
-rw-r--r--boost/python/make_constructor.hpp13
-rw-r--r--boost/python/numpy.hpp33
-rw-r--r--boost/python/numpy/dtype.hpp117
-rw-r--r--boost/python/numpy/internal.hpp35
-rw-r--r--boost/python/numpy/invoke_matching.hpp186
-rw-r--r--boost/python/numpy/matrix.hpp82
-rw-r--r--boost/python/numpy/ndarray.hpp296
-rw-r--r--boost/python/numpy/numpy_object_mgr_traits.hpp36
-rw-r--r--boost/python/numpy/scalars.hpp58
-rw-r--r--boost/python/numpy/ufunc.hpp205
-rw-r--r--boost/python/object/class_metadata.hpp111
-rw-r--r--boost/python/object/make_ptr_instance.hpp6
-rw-r--r--boost/python/object/pointer_holder.hpp8
-rw-r--r--boost/python/object/py_function.hpp10
-rw-r--r--boost/python/object_core.hpp1
-rwxr-xr-xboost/python/refcount.hpp2
-rw-r--r--boost/python/str.hpp2
-rw-r--r--boost/python/to_python_indirect.hpp4
-rw-r--r--boost/python/to_python_value.hpp52
-rw-r--r--boost/range/size_type.hpp5
-rw-r--r--boost/regex/pending/unicode_iterator.hpp2
-rw-r--r--boost/signals2/slot_base.hpp2
-rw-r--r--boost/smart_ptr/bad_weak_ptr.hpp9
-rw-r--r--boost/smart_ptr/detail/atomic_count.hpp3
-rw-r--r--boost/smart_ptr/detail/sp_counted_base.hpp5
-rw-r--r--boost/smart_ptr/detail/sp_counted_base_clang.hpp9
-rw-r--r--boost/smart_ptr/detail/spinlock.hpp3
-rw-r--r--boost/smart_ptr/make_shared_object.hpp570
-rw-r--r--boost/test/execution_monitor.hpp40
-rw-r--r--boost/test/impl/compiler_log_formatter.ipp4
-rw-r--r--boost/test/impl/execution_monitor.ipp49
-rw-r--r--boost/test/impl/framework.ipp248
-rw-r--r--boost/test/impl/test_tree.ipp3
-rw-r--r--boost/test/impl/unit_test_parameters.ipp18
-rw-r--r--boost/test/included/unit_test.hpp3
-rw-r--r--boost/test/tools/collection_comparison_op.hpp51
-rw-r--r--boost/test/tools/cstring_comparison_op.hpp20
-rw-r--r--boost/test/tools/fpc_op.hpp6
-rw-r--r--boost/test/tree/test_case_template.hpp17
-rw-r--r--boost/test/unit_test_log_formatter.hpp6
-rw-r--r--boost/test/unit_test_parameters.hpp2
-rw-r--r--boost/test/utils/is_cstring.hpp31
-rw-r--r--boost/test/utils/is_forward_iterable.hpp5
-rw-r--r--boost/test/utils/iterator/token_iterator.hpp8
-rw-r--r--boost/test/utils/runtime/cla/parser.hpp33
-rw-r--r--boost/test/utils/runtime/parameter.hpp2
-rw-r--r--boost/thread/pthread/condition_variable.hpp6
-rw-r--r--boost/thread/synchronized_value.hpp12
-rw-r--r--boost/thread/user_scheduler.hpp2
-rw-r--r--boost/type_index/detail/compile_time_type_info.hpp36
-rw-r--r--boost/type_index/runtime_cast.hpp28
-rw-r--r--boost/type_index/runtime_cast/boost_shared_ptr_cast.hpp46
-rw-r--r--boost/type_index/runtime_cast/detail/runtime_cast_impl.hpp57
-rw-r--r--boost/type_index/runtime_cast/pointer_cast.hpp74
-rw-r--r--boost/type_index/runtime_cast/reference_cast.hpp66
-rw-r--r--boost/type_index/runtime_cast/register_runtime_class.hpp88
-rw-r--r--boost/type_index/runtime_cast/std_shared_ptr_cast.hpp46
-rw-r--r--boost/units/base_units/cgs/biot.hpp2
-rw-r--r--boost/units/conversion.hpp2
-rw-r--r--boost/units/io.hpp81
-rw-r--r--boost/units/systems/si/codata/physico-chemical_constants.hpp24
-rw-r--r--boost/unordered/detail/allocate.hpp285
-rw-r--r--boost/unordered/detail/buckets.hpp51
-rw-r--r--boost/unordered/detail/equivalent.hpp300
-rw-r--r--boost/unordered/detail/extract_key.hpp2
-rw-r--r--boost/unordered/detail/fwd.hpp36
-rw-r--r--boost/unordered/detail/map.hpp18
-rw-r--r--boost/unordered/detail/set.hpp18
-rw-r--r--boost/unordered/detail/table.hpp71
-rw-r--r--boost/unordered/detail/unique.hpp211
-rw-r--r--boost/unordered/detail/util.hpp2
-rw-r--r--boost/unordered/unordered_map.hpp308
-rw-r--r--boost/unordered/unordered_set.hpp302
-rw-r--r--boost/utility/compare_pointees.hpp12
-rw-r--r--boost/utility/string_view.hpp4
-rw-r--r--boost/uuid/detail/uuid_x86.hpp8
-rw-r--r--boost/uuid/random_generator.hpp12
-rw-r--r--boost/uuid/seed_rng.hpp12
-rw-r--r--boost/version.hpp4
620 files changed, 25384 insertions, 20013 deletions
diff --git a/boost/atomic/detail/atomic_template.hpp b/boost/atomic/detail/atomic_template.hpp
index 2deaded62f..dd3c741506 100644
--- a/boost/atomic/detail/atomic_template.hpp
+++ b/boost/atomic/detail/atomic_template.hpp
@@ -78,9 +78,9 @@ class base_atomic< T, int >
private:
typedef T value_type;
typedef T difference_type;
- typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::is_signed< T >::value > operations;
protected:
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, boost::is_signed< T >::value > operations;
typedef value_type value_arg_type;
public:
@@ -234,9 +234,9 @@ class base_atomic< bool, int >
{
private:
typedef bool value_type;
- typedef atomics::detail::operations< 1u, false > operations;
protected:
+ typedef atomics::detail::operations< 1u, false > operations;
typedef value_type value_arg_type;
public:
@@ -321,9 +321,9 @@ class base_atomic< T, void >
{
private:
typedef T value_type;
- typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
typedef value_type const& value_arg_type;
public:
@@ -410,9 +410,9 @@ class base_atomic< T*, void* >
private:
typedef T* value_type;
typedef std::ptrdiff_t difference_type;
- typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
typedef value_type value_arg_type;
public:
@@ -540,9 +540,9 @@ class base_atomic< void*, void* >
private:
typedef void* value_type;
typedef std::ptrdiff_t difference_type;
- typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
protected:
+ typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations;
typedef value_type value_arg_type;
public:
@@ -677,6 +677,9 @@ public:
typedef typename base_type::storage_type storage_type;
public:
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = base_type::operations::is_always_lock_free;
+
+public:
BOOST_DEFAULTED_FUNCTION(atomic(), BOOST_NOEXCEPT {})
// NOTE: The constructor is made explicit because gcc 4.7 complains that
@@ -706,6 +709,9 @@ public:
BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&) volatile)
};
+template< typename T >
+BOOST_CONSTEXPR_OR_CONST bool atomic< T >::is_always_lock_free;
+
typedef atomic< char > atomic_char;
typedef atomic< unsigned char > atomic_uchar;
typedef atomic< signed char > atomic_schar;
diff --git a/boost/atomic/detail/config.hpp b/boost/atomic/detail/config.hpp
index 489281c2b4..00f7bff696 100644
--- a/boost/atomic/detail/config.hpp
+++ b/boost/atomic/detail/config.hpp
@@ -60,14 +60,15 @@
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA
#endif
-#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 403)
+#if ((defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 403)) ||\
+ defined(__SUNPRO_CC)
// This macro indicates we're using older binutils that don't support implied zero displacements for memory opereands,
// making code like this invalid:
// movl 4+(%%edx), %%eax
#define BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS
#endif
-#if defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500)
+#if defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500) || defined(__SUNPRO_CC)
// This macro indicates that the compiler does not support allocating rax:rdx register pairs ("A") in asm blocks
#define BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS
#endif
diff --git a/boost/atomic/detail/ops_emulated.hpp b/boost/atomic/detail/ops_emulated.hpp
index 17032917fe..a21128ec69 100644
--- a/boost/atomic/detail/ops_emulated.hpp
+++ b/boost/atomic/detail/ops_emulated.hpp
@@ -35,6 +35,8 @@ struct emulated_operations
{
typedef T storage_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false;
+
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
lockpool::scoped_lock lock(&storage);
diff --git a/boost/atomic/detail/ops_gcc_alpha.hpp b/boost/atomic/detail/ops_gcc_alpha.hpp
index 3c0e258ceb..15118f58a2 100644
--- a/boost/atomic/detail/ops_gcc_alpha.hpp
+++ b/boost/atomic/detail/ops_gcc_alpha.hpp
@@ -63,6 +63,8 @@ namespace detail {
struct gcc_alpha_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
diff --git a/boost/atomic/detail/ops_gcc_arm.hpp b/boost/atomic/detail/ops_gcc_arm.hpp
index d2c2f39a2c..e181b16853 100644
--- a/boost/atomic/detail/ops_gcc_arm.hpp
+++ b/boost/atomic/detail/ops_gcc_arm.hpp
@@ -100,6 +100,8 @@ namespace detail {
struct gcc_arm_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
diff --git a/boost/atomic/detail/ops_gcc_atomic.hpp b/boost/atomic/detail/ops_gcc_atomic.hpp
index 573a695d08..0a34c01f16 100644
--- a/boost/atomic/detail/ops_gcc_atomic.hpp
+++ b/boost/atomic/detail/ops_gcc_atomic.hpp
@@ -85,6 +85,11 @@ struct gcc_atomic_operations
{
typedef T storage_type;
+ // Note: In the current implementation, gcc_atomic_operations are used onlu when the particularly sized __atomic
+ // intrinsics are always lock-free (i.e. the corresponding LOCK_FREE macro is 2). Therefore it is safe to
+ // always set is_always_lock_free to true here.
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
__atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
diff --git a/boost/atomic/detail/ops_gcc_ppc.hpp b/boost/atomic/detail/ops_gcc_ppc.hpp
index 9131791193..4183bc0485 100644
--- a/boost/atomic/detail/ops_gcc_ppc.hpp
+++ b/boost/atomic/detail/ops_gcc_ppc.hpp
@@ -85,6 +85,8 @@ namespace detail {
struct gcc_ppc_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
#if defined(__powerpc64__) || defined(__PPC64__)
diff --git a/boost/atomic/detail/ops_gcc_sparc.hpp b/boost/atomic/detail/ops_gcc_sparc.hpp
index faefecaf76..fd42fa8095 100644
--- a/boost/atomic/detail/ops_gcc_sparc.hpp
+++ b/boost/atomic/detail/ops_gcc_sparc.hpp
@@ -34,6 +34,8 @@ namespace detail {
struct gcc_sparc_cas_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
diff --git a/boost/atomic/detail/ops_gcc_sync.hpp b/boost/atomic/detail/ops_gcc_sync.hpp
index 87f2f53029..2f41aff279 100644
--- a/boost/atomic/detail/ops_gcc_sync.hpp
+++ b/boost/atomic/detail/ops_gcc_sync.hpp
@@ -33,6 +33,8 @@ namespace detail {
struct gcc_sync_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
diff --git a/boost/atomic/detail/ops_gcc_x86.hpp b/boost/atomic/detail/ops_gcc_x86.hpp
index a4e4af3660..98dcdc064e 100644
--- a/boost/atomic/detail/ops_gcc_x86.hpp
+++ b/boost/atomic/detail/ops_gcc_x86.hpp
@@ -42,6 +42,8 @@ namespace detail {
struct gcc_x86_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
index 47cc36d8e7..2f51182e5a 100644
--- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp
+++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
@@ -38,6 +38,8 @@ struct gcc_dcas_x86
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
if ((((uint32_t)&storage) & 0x00000007) == 0)
@@ -367,9 +369,12 @@ struct gcc_dcas_x86_64
typedef typename make_storage_type< 16u, Signed >::type storage_type;
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
uint64_t const* p_value = (uint64_t const*)&v;
+ const uint64_t v_lo = p_value[0], v_hi = p_value[1];
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
@@ -379,7 +384,7 @@ struct gcc_dcas_x86_64
"1: lock; cmpxchg16b %[dest]\n\t"
"jne 1b\n\t"
: [dest] "=o" (storage)
- : "b" (p_value[0]), "c" (p_value[1])
+ : "b" (v_lo), "c" (v_hi)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -391,7 +396,7 @@ struct gcc_dcas_x86_64
"1: lock; cmpxchg16b 0(%[dest])\n\t"
"jne 1b\n\t"
:
- : "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage)
+ : "b" (v_lo), "c" (v_hi), [dest] "r" (&storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -466,6 +471,7 @@ struct gcc_dcas_x86_64
#elif defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
uint64_t const* p_desired = (uint64_t const*)&desired;
+ const uint64_t desired_lo = p_desired[0], desired_hi = p_desired[1];
bool success;
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
@@ -477,7 +483,7 @@ struct gcc_dcas_x86_64
"movq %%rax, %[expected]\n\t"
"movq %%rdx, 8+%[expected]\n\t"
: [dest] "+m" (storage), [expected] "+o" (expected), [success] "=q" (success)
- : "b" (p_desired[0]), "c" (p_desired[1])
+ : "b" (desired_lo), "c" (desired_hi)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -490,7 +496,7 @@ struct gcc_dcas_x86_64
"movq %%rax, 0(%[expected])\n\t"
"movq %%rdx, 8(%[expected])\n\t"
: [dest] "+m" (storage), [success] "=q" (success)
- : "b" (p_desired[0]), "c" (p_desired[1]), [expected] "r" (&expected)
+ : "b" (desired_lo), "c" (desired_hi), [expected] "r" (&expected)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -498,6 +504,7 @@ struct gcc_dcas_x86_64
return success;
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
uint64_t const* p_desired = (uint64_t const*)&desired;
+ const uint64_t desired_lo = p_desired[0], desired_hi = p_desired[1];
bool success;
__asm__ __volatile__
(
@@ -505,10 +512,10 @@ struct gcc_dcas_x86_64
"sete %[success]\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
: "+A,A" (expected), [dest] "+m,m" (storage), [success] "=q,m" (success)
- : "b,b" (p_desired[0]), "c,c" (p_desired[1])
+ : "b,b" (desired_lo), "c,c" (desired_hi)
#else
: "+A" (expected), [dest] "+m" (storage), [success] "=q" (success)
- : "b" (p_desired[0]), "c" (p_desired[1])
+ : "b" (desired_lo), "c" (desired_hi)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
@@ -538,6 +545,7 @@ struct gcc_dcas_x86_64
// GCC 4.4 can't allocate rax:rdx register pair either but it also doesn't support 128-bit __sync_val_compare_and_swap
storage_type old_value;
uint64_t const* p_value = (uint64_t const*)&v;
+ const uint64_t v_lo = p_value[0], v_hi = p_value[1];
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
@@ -549,7 +557,7 @@ struct gcc_dcas_x86_64
"movq %%rax, %[old_value]\n\t"
"movq %%rdx, 8+%[old_value]\n\t"
: [dest] "+o" (storage), [old_value] "=o" (old_value)
- : "b" (p_value[0]), "c" (p_value[1])
+ : "b" (v_lo), "c" (v_hi)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -563,7 +571,7 @@ struct gcc_dcas_x86_64
"movq %%rax, 0(%[old_value])\n\t"
"movq %%rdx, 8(%[old_value])\n\t"
:
- : "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage), [old_value] "r" (&old_value)
+ : "b" (v_lo), "c" (v_hi), [dest] "r" (&storage), [old_value] "r" (&old_value)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory", "rax", "rdx"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -571,6 +579,7 @@ struct gcc_dcas_x86_64
return old_value;
#else // defined(BOOST_ATOMIC_DETAIL_NO_ASM_RAX_RDX_PAIRS)
uint64_t const* p_value = (uint64_t const*)&v;
+ const uint64_t v_lo = p_value[0], v_hi = p_value[1];
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
__asm__ __volatile__
(
@@ -580,7 +589,7 @@ struct gcc_dcas_x86_64
"1: lock; cmpxchg16b %[dest]\n\t"
"jne 1b\n\t"
: "=&A" (v), [dest] "+o" (storage)
- : "b" (p_value[0]), "c" (p_value[1])
+ : "b" (v_lo), "c" (v_hi)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
@@ -592,7 +601,7 @@ struct gcc_dcas_x86_64
"1: lock; cmpxchg16b 0(%[dest])\n\t"
"jne 1b\n\t"
: "=&A" (v)
- : "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (&storage)
+ : "b" (v_lo), "c" (v_hi), [dest] "r" (&storage)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
diff --git a/boost/atomic/detail/ops_linux_arm.hpp b/boost/atomic/detail/ops_linux_arm.hpp
index 41713a35f5..01894b63ee 100644
--- a/boost/atomic/detail/ops_linux_arm.hpp
+++ b/boost/atomic/detail/ops_linux_arm.hpp
@@ -57,6 +57,8 @@ namespace detail {
struct linux_arm_cas_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
if ((order & memory_order_release) != 0)
diff --git a/boost/atomic/detail/ops_msvc_arm.hpp b/boost/atomic/detail/ops_msvc_arm.hpp
index ff953d67e3..fd07f093fb 100644
--- a/boost/atomic/detail/ops_msvc_arm.hpp
+++ b/boost/atomic/detail/ops_msvc_arm.hpp
@@ -53,6 +53,8 @@ namespace detail {
struct msvc_arm_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
diff --git a/boost/atomic/detail/ops_msvc_x86.hpp b/boost/atomic/detail/ops_msvc_x86.hpp
index 04b496efb6..24824214dd 100644
--- a/boost/atomic/detail/ops_msvc_x86.hpp
+++ b/boost/atomic/detail/ops_msvc_x86.hpp
@@ -72,6 +72,8 @@ namespace detail {
struct msvc_x86_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
@@ -610,6 +612,8 @@ struct msvc_dcas_x86
typedef typename make_storage_type< 8u, Signed >::type storage_type;
typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
// Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
//
// The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
@@ -768,7 +772,7 @@ struct msvc_dcas_x86
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
- static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
+ static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
@@ -863,6 +867,8 @@ struct msvc_dcas_x86_64
typedef typename make_storage_type< 16u, Signed >::type storage_type;
typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type;
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
storage_type value = const_cast< storage_type& >(storage);
diff --git a/boost/atomic/detail/ops_windows.hpp b/boost/atomic/detail/ops_windows.hpp
index 191eb84d0a..867f1c6113 100644
--- a/boost/atomic/detail/ops_windows.hpp
+++ b/boost/atomic/detail/ops_windows.hpp
@@ -43,6 +43,8 @@ namespace detail {
struct windows_operations_base
{
+ static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
+
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
long tmp;
diff --git a/boost/bind/arg.hpp b/boost/bind/arg.hpp
index a74b8298be..cb52e6689f 100644
--- a/boost/bind/arg.hpp
+++ b/boost/bind/arg.hpp
@@ -21,20 +21,27 @@
#include <boost/config.hpp>
#include <boost/is_placeholder.hpp>
-#include <boost/static_assert.hpp>
namespace boost
{
+template<bool Eq> struct _arg_eq
+{
+};
+
+template<> struct _arg_eq<true>
+{
+ typedef void type;
+};
+
template< int I > struct arg
{
BOOST_CONSTEXPR arg()
{
}
- template< class T > BOOST_CONSTEXPR arg( T const & /* t */ )
+ template< class T > BOOST_CONSTEXPR arg( T const & /* t */, typename _arg_eq< I == is_placeholder<T>::value >::type * = 0 )
{
- BOOST_STATIC_ASSERT( I == is_placeholder<T>::value );
}
};
diff --git a/boost/config/compiler/intel.hpp b/boost/config/compiler/intel.hpp
index 80969e9edd..1885ea281f 100644
--- a/boost/config/compiler/intel.hpp
+++ b/boost/config/compiler/intel.hpp
@@ -35,6 +35,10 @@
#endif
+#if (__INTEL_COMPILER <= 1600) && !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
+# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
+#endif
+
#else
#include <boost/config/compiler/gcc.hpp>
@@ -496,6 +500,11 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# define BOOST_NO_CXX11_HDR_TUPLE
#endif
+// Broken in all versions up to 17:
+#if !defined(BOOST_NO_CXX14_CONSTEXPR)
+#define BOOST_NO_CXX14_CONSTEXPR
+#endif
+
#if (BOOST_INTEL_CXX_VERSION < 1200)
//
// fenv.h appears not to work with Intel prior to 12.0:
diff --git a/boost/config/compiler/nvcc.hpp b/boost/config/compiler/nvcc.hpp
index 5a047070af..b31d4f4fa4 100644
--- a/boost/config/compiler/nvcc.hpp
+++ b/boost/config/compiler/nvcc.hpp
@@ -22,3 +22,11 @@
#if !defined(__CUDACC_VER__) || (__CUDACC_VER__ < 70500)
# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif
+// The same bug is back again in 8.0:
+#if (__CUDACC_VER__ > 80000) && (__CUDACC_VER__ < 80100)
+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#endif
+// Most recent CUDA (8.0) has no constexpr support in msvc mode:
+#if defined(_MSC_VER)
+# define BOOST_NO_CXX11_CONSTEXPR
+#endif
diff --git a/boost/config/compiler/sunpro_cc.hpp b/boost/config/compiler/sunpro_cc.hpp
index 8f07e0e9a2..ac259fce28 100644
--- a/boost/config/compiler/sunpro_cc.hpp
+++ b/boost/config/compiler/sunpro_cc.hpp
@@ -152,7 +152,7 @@
#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
# define BOOST_NO_CXX14_CONSTEXPR
#endif
-#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304)
+#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304) || (__cplusplus < 201402L)
# define BOOST_NO_CXX14_DECLTYPE_AUTO
#endif
#if (__cplusplus < 201304) // There's no SD6 check for this....
diff --git a/boost/config/compiler/visualc.hpp b/boost/config/compiler/visualc.hpp
index 72caff4974..cdbc9b6701 100644
--- a/boost/config/compiler/visualc.hpp
+++ b/boost/config/compiler/visualc.hpp
@@ -190,6 +190,13 @@
# define BOOST_NO_CXX11_CONSTEXPR
#endif
+// C++14 features supported by VC++ 15 Preview 5
+//
+#if (_MSC_VER < 1910)
+# define BOOST_NO_CXX14_AGGREGATE_NSDMI
+# define BOOST_NO_CXX14_CONSTEXPR
+#endif
+
// MSVC including version 14 has not yet completely
// implemented value-initialization, as is reported:
// "VC++ does not value-initialize members of derived classes without
@@ -210,14 +217,6 @@
// C++ 11:
//
#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
-//
-// C++ 14:
-#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304)
-# define BOOST_NO_CXX14_AGGREGATE_NSDMI
-#endif
-#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
-# define BOOST_NO_CXX14_CONSTEXPR
-#endif
//
// prefix and suffix headers:
@@ -294,8 +293,8 @@
#endif
//
-// last known and checked version is 19.00.23026 (VC++ 2015 RTM):
-#if (_MSC_VER > 1900)
+// last known and checked version is 19.10.24629 (VC++ 2017 RC):
+#if (_MSC_VER > 1910)
# if defined(BOOST_ASSERT_CONFIG)
# error "Unknown compiler version - please run the configure tests and report the results"
# else
diff --git a/boost/config/stdlib/dinkumware.hpp b/boost/config/stdlib/dinkumware.hpp
index af8ddda528..8cf5d4dd26 100644
--- a/boost/config/stdlib/dinkumware.hpp
+++ b/boost/config/stdlib/dinkumware.hpp
@@ -150,13 +150,24 @@
#if defined(__has_include)
#if !__has_include(<shared_mutex>)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
-#elif __cplusplus < 201402
+#elif (__cplusplus < 201402) && !defined(_MSC_VER)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
#elif !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
+# define BOOST_NO_CXX14_STD_EXCHANGE
+#endif
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
+# define BOOST_NO_CXX17_STD_INVOKE
+#endif
+
#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1400)
// Intel's compiler can't handle this header yet:
# define BOOST_NO_CXX11_HDR_ATOMIC
diff --git a/boost/config/stdlib/libcomo.hpp b/boost/config/stdlib/libcomo.hpp
index 941498d076..e3fc627f6f 100644
--- a/boost/config/stdlib/libcomo.hpp
+++ b/boost/config/stdlib/libcomo.hpp
@@ -72,6 +72,13 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
//
// Intrinsic type_traits support.
// The SGI STL has it's own __type_traits class, which
diff --git a/boost/config/stdlib/libcpp.hpp b/boost/config/stdlib/libcpp.hpp
index 096b8c0de2..2eea99977d 100644
--- a/boost/config/stdlib/libcpp.hpp
+++ b/boost/config/stdlib/libcpp.hpp
@@ -32,10 +32,14 @@
#endif
#if __cplusplus < 201103
-# define BOOST_NO_CXX11_HDR_ARRAY
+//
+// These two appear to be somewhat useable in C++03 mode, there may be others...
+//
+//# define BOOST_NO_CXX11_HDR_ARRAY
+//# define BOOST_NO_CXX11_HDR_FORWARD_LIST
+
# define BOOST_NO_CXX11_HDR_CODECVT
# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
-# define BOOST_NO_CXX11_HDR_FORWARD_LIST
# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
# define BOOST_NO_CXX11_HDR_MUTEX
# define BOOST_NO_CXX11_HDR_RANDOM
@@ -75,6 +79,19 @@
#define BOOST_NO_STD_MESSAGES
#endif
+// C++14 features
+#if (_LIBCPP_VERSION < 3700) || (__cplusplus <= 201402L)
+# define BOOST_NO_CXX14_STD_EXCHANGE
+#endif
+
+// C++17 features
+#if (_LIBCPP_VERSION < 3700) || (__cplusplus <= 201402L)
+# define BOOST_NO_CXX17_STD_INVOKE
+#endif
+#if (_LIBCPP_VERSION < 4000) || (__cplusplus <= 201402L)
+# define BOOST_NO_CXX17_STD_APPLY
+#endif
+
#if (_LIBCPP_VERSION <= 1101) && !defined(BOOST_NO_CXX11_THREAD_LOCAL)
// This is a bit of a sledgehammer, because really it's just libc++abi that has no
// support for thread_local, leading to linker errors such as
diff --git a/boost/config/stdlib/libstdcpp3.hpp b/boost/config/stdlib/libstdcpp3.hpp
index 1d8f6ccbce..557767b1fa 100644
--- a/boost/config/stdlib/libstdcpp3.hpp
+++ b/boost/config/stdlib/libstdcpp3.hpp
@@ -98,6 +98,7 @@
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103)
# define BOOST_LIBSTDCXX11
#endif
+
//
// Decide which version of libstdc++ we have, normally
// stdlibc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly
@@ -122,7 +123,9 @@
//
#ifdef __clang__
-#if __has_include(<experimental/any>)
+#if __has_include(<experimental/memory_resource>)
+# define BOOST_LIBSTDCXX_VERSION 60100
+#elif __has_include(<experimental/any>)
# define BOOST_LIBSTDCXX_VERSION 50100
#elif __has_include(<shared_mutex>)
# define BOOST_LIBSTDCXX_VERSION 40900
@@ -139,6 +142,7 @@
#elif __has_include(<array>)
# define BOOST_LIBSTDCXX_VERSION 40300
#endif
+
//
// GCC 4.8 and 9 add working versions of <atomic> and <regex> respectively.
// However, we have no test for these as the headers were present but broken
@@ -236,6 +240,9 @@
// even for the simplest patterns such as "\d" or "[0-9]". This is the case at least in gcc up to 4.8, inclusively.
# define BOOST_NO_CXX11_HDR_REGEX
#endif
+#if (BOOST_LIBSTDCXX_VERSION < 40900) || (__cplusplus <= 201103)
+# define BOOST_NO_CXX14_STD_EXCHANGE
+#endif
#if defined(__clang_major__) && ((__clang_major__ < 3) || ((__clang_major__ == 3) && (__clang_minor__ < 7)))
// As of clang-3.6, libstdc++ header <atomic> throws up errors with clang:
@@ -251,6 +258,16 @@
# define BOOST_NO_CXX11_STD_ALIGN
#endif
+//
+// C++17 features in GCC 6.1 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 60100) || (__cplusplus <= 201402L)
+# define BOOST_NO_CXX17_STD_INVOKE
+#endif
+#if (BOOST_LIBSTDCXX_VERSION < 70100) || (__cplusplus <= 201402L)
+# define BOOST_NO_CXX17_STD_APPLY
+#endif
+
#if defined(__has_include)
#if !__has_include(<shared_mutex>)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
diff --git a/boost/config/stdlib/modena.hpp b/boost/config/stdlib/modena.hpp
index 7a85e0cd57..fa4a818715 100644
--- a/boost/config/stdlib/modena.hpp
+++ b/boost/config/stdlib/modena.hpp
@@ -61,6 +61,13 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
#define BOOST_STDLIB "Modena C++ standard library"
diff --git a/boost/config/stdlib/msl.hpp b/boost/config/stdlib/msl.hpp
index dd2775e10c..8f21a1388d 100644
--- a/boost/config/stdlib/msl.hpp
+++ b/boost/config/stdlib/msl.hpp
@@ -85,4 +85,11 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__)
diff --git a/boost/config/stdlib/roguewave.hpp b/boost/config/stdlib/roguewave.hpp
index 97a2b0b90b..437d38d97c 100644
--- a/boost/config/stdlib/roguewave.hpp
+++ b/boost/config/stdlib/roguewave.hpp
@@ -196,3 +196,10 @@
#else
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
diff --git a/boost/config/stdlib/sgi.hpp b/boost/config/stdlib/sgi.hpp
index c8052717ce..8d2f849f70 100644
--- a/boost/config/stdlib/sgi.hpp
+++ b/boost/config/stdlib/sgi.hpp
@@ -155,4 +155,11 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
-#define BOOST_STDLIB "SGI standard library" \ No newline at end of file
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
+#define BOOST_STDLIB "SGI standard library"
diff --git a/boost/config/stdlib/stlport.hpp b/boost/config/stdlib/stlport.hpp
index bbc4176c90..518f9efd4a 100644
--- a/boost/config/stdlib/stlport.hpp
+++ b/boost/config/stdlib/stlport.hpp
@@ -245,4 +245,11 @@ namespace boost { using std::min; using std::max; }
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT)
diff --git a/boost/config/stdlib/vacpp.hpp b/boost/config/stdlib/vacpp.hpp
index 4ccd0d2466..f9afef6387 100644
--- a/boost/config/stdlib/vacpp.hpp
+++ b/boost/config/stdlib/vacpp.hpp
@@ -61,4 +61,11 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+// C++14 features
+# define BOOST_NO_CXX14_STD_EXCHANGE
+
+// C++17 features
+# define BOOST_NO_CXX17_STD_APPLY
+# define BOOST_NO_CXX17_STD_INVOKE
+
#define BOOST_STDLIB "Visual Age default standard library"
diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp
index ead93c6035..dda311aa33 100644
--- a/boost/container/detail/copy_move_algo.hpp
+++ b/boost/container/detail/copy_move_algo.hpp
@@ -186,8 +186,9 @@ inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
template
<typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
-F memmove_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
if(n){
@@ -199,8 +200,9 @@ F memmove_n(I f, typename boost::container::iterator_traits<I>::difference_type
template
<typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
-I memmove_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{
if(n){
typedef typename boost::container::iterator_traits<I>::value_type value_type;
@@ -212,8 +214,9 @@ I memmove_n_source(I f, typename boost::container::iterator_traits<I>::differenc
template
<typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
-I memmove_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef typename boost::container::iterator_traits<I>::value_type value_type;
if(n){
@@ -332,7 +335,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
- uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -356,7 +359,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
- uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -377,7 +380,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
- uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -401,7 +404,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
- uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -467,7 +470,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -491,7 +494,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
- uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -512,7 +515,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
- uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -536,7 +539,7 @@ template
typename I, // I models InputIterator
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
- uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -556,7 +559,7 @@ template
<typename Allocator,
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memzero_initializable<F, F>::type
- uninitialized_value_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r)
+ uninitialized_value_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -579,7 +582,7 @@ template
<typename Allocator,
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memzero_initializable<F, F>::type
- uninitialized_value_init_alloc_n(Allocator &, typename allocator_traits<Allocator>::difference_type n, F r)
+ uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
typedef typename boost::container::iterator_traits<F>::value_type value_type;
std::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
@@ -603,7 +606,7 @@ inline typename container_detail::enable_if_memzero_initializable<F, F>::type
template
<typename Allocator,
typename F> // F models ForwardIterator
-inline F uninitialized_default_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r)
+inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -675,7 +678,7 @@ template
<typename Allocator,
typename T,
typename F> // F models ForwardIterator
-inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename allocator_traits<Allocator>::difference_type n, F r)
+inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
{
F back = r;
BOOST_TRY{
@@ -728,9 +731,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
- copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ copy_n(I f, U n, F r)
{
while (n--) {
*r = *f;
@@ -741,9 +745,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
- copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ copy_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -754,9 +759,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
- copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ copy_n_source(I f, U n, F r)
{
while (n--) {
boost::container::assign_in_place(r, f);
@@ -767,9 +773,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
- copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ copy_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -780,9 +787,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
- copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r)
+ copy_n_source_dest(I f, U n, F &r)
{
while (n--) {
*r = *f;
@@ -793,9 +801,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
- copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+ copy_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source_dest(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -832,9 +841,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
- move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ move_n(I f, U n, F r)
{
while (n--) {
*r = ::boost::move(*f);
@@ -845,9 +855,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F
template
<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
- move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ move_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n(f, n, r); }
@@ -891,9 +902,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>
template
<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
,typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
- move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r)
+ move_n_source_dest(I f, U n, F &r)
{
while (n--) {
*r = ::boost::move(*f);
@@ -904,9 +916,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I
template
<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
,typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
- move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+ move_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source_dest(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
@@ -917,9 +930,10 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>
template
<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
,typename F> // F models ForwardIterator
inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
- move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
+ move_n_source(I f, U n, F r)
{
while (n--) {
*r = ::boost::move(*f);
@@ -930,9 +944,10 @@ inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I
template
<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
,typename F> // F models ForwardIterator
inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
- move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+ move_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::memmove_n_source(f, n, r); }
//////////////////////////////////////////////////////////////////////////////
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index db73c410a9..93984d18e5 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -409,7 +409,6 @@ class flat_tree
iterator insert_unique(const_iterator hint, const value_type& val)
{
BOOST_ASSERT(this->priv_in_range_or_end(hint));
- std::pair<iterator,bool> ret;
insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, val)
@@ -419,7 +418,6 @@ class flat_tree
iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
{
BOOST_ASSERT(this->priv_in_range_or_end(hint));
- std::pair<iterator,bool> ret;
insert_commit_data data;
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
? this->priv_insert_commit(data, boost::move(val))
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index d3b353a461..11ffaae65e 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -809,6 +809,7 @@ class iterator_from_iiterator
typedef typename types_t::value_type value_type;
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator()
+ : m_iit()
{}
BOOST_CONTAINER_FORCEINLINE explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 096f79561e..4abff4b4d8 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -66,7 +66,8 @@ namespace container {
};
template <int Dummy>
- ::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy;
+ ::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy =
+ reinterpret_cast< ::std::piecewise_construct_t *>(0x01234); //Avoid sanitizer errors on references to null pointers
typedef const std::piecewise_construct_t & piecewise_construct_t;
@@ -84,8 +85,17 @@ typedef unspecified piecewise_construct_t;
//! piecewise_construct_t
static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy);
+///@cond
+
namespace container_detail {
+struct piecewise_construct_use
+{
+ //Avoid warnings of unused "piecewise_construct"
+ piecewise_construct_use()
+ { (void)&::boost::container::piecewise_construct; }
+};
+
template <class T1, class T2>
struct pair;
@@ -130,6 +140,8 @@ struct pair_nat;
template<typename T, typename U, typename V>
void get(T); //to enable ADL
+///@endcond
+
template <class T1, class T2>
struct pair
{
@@ -416,36 +428,6 @@ inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
} //namespace container_detail {
} //namespace container {
-
-//Without this specialization recursive flat_(multi)map instantiation fails
-//because is_enum needs to instantiate the recursive pair, leading to a compilation error).
-//This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation.
-template<class T>
-struct is_enum;
-
-template<class T, class U>
-struct is_enum< ::boost::container::container_detail::pair<T, U> >
-{
- static const bool value = false;
-};
-
-template<class T, class U>
-struct is_enum< ::std::pair<T, U> >
-{
- static const bool value = false;
-};
-
-template <class T>
-struct is_class;
-
-//This specialization is needed to avoid instantiation of pair in
-//is_class, and allow recursive maps.
-template <class T1, class T2>
-struct is_class< ::boost::container::container_detail::pair<T1, T2> >
-{
- static const bool value = true;
-};
-
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T1, class T2>
diff --git a/boost/container/detail/variadic_templates_tools.hpp b/boost/container/detail/variadic_templates_tools.hpp
index f5101c577c..e9fa9cd15a 100644
--- a/boost/container/detail/variadic_templates_tools.hpp
+++ b/boost/container/detail/variadic_templates_tools.hpp
@@ -136,21 +136,25 @@ typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>&
// in a function call.
////////////////////////////////////////////////////
-template<std::size_t ... Indexes>
-struct index_tuple{};
+template<std::size_t...> struct index_tuple{ typedef index_tuple type; };
-template<std::size_t Num, typename Tuple = index_tuple<> >
-struct build_number_seq;
+template<class S1, class S2> struct concat_index_tuple;
-template<std::size_t Num, std::size_t ... Indexes>
-struct build_number_seq<Num, index_tuple<Indexes...> >
- : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
-{};
+template<std::size_t... I1, std::size_t... I2>
+struct concat_index_tuple<index_tuple<I1...>, index_tuple<I2...>>
+ : index_tuple<I1..., (sizeof...(I1)+I2)...>{};
+
+template<std::size_t N> struct build_number_seq;
-template<std::size_t ... Indexes>
-struct build_number_seq<0, index_tuple<Indexes...> >
-{ typedef index_tuple<Indexes...> type; };
+template<std::size_t N>
+struct build_number_seq
+ : concat_index_tuple<typename build_number_seq<N/2>::type
+ ,typename build_number_seq<N - N/2 >::type
+ >::type
+{};
+template<> struct build_number_seq<0> : index_tuple<>{};
+template<> struct build_number_seq<1> : index_tuple<0>{};
}}} //namespace boost { namespace container { namespace container_detail {
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index 64ecd6fd6b..ed57718ba9 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -103,6 +103,9 @@
#elif defined(BOOST_MSVC) && defined(_DEBUG)
//"__forceinline" and MSVC seems to have some bugs in debug mode
#define BOOST_CONTAINER_FORCEINLINE inline
+#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
+ //Older GCCs have problems with forceinline
+ #define BOOST_CONTAINER_FORCEINLINE inline
#else
#define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
#endif
diff --git a/boost/container/uses_allocator_fwd.hpp b/boost/container/uses_allocator_fwd.hpp
index d8fe67fbfe..42a5b904f0 100644
--- a/boost/container/uses_allocator_fwd.hpp
+++ b/boost/container/uses_allocator_fwd.hpp
@@ -30,8 +30,8 @@ namespace container {
static ::std::allocator_arg_t *dummy;
};
- template <int Dummy>
- ::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy;
+ template <int Dummy> //Silence null-reference compiler warnings
+ ::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy = reinterpret_cast< ::std::allocator_arg_t * >(0x1234);
typedef const std::allocator_arg_t & allocator_arg_t;
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index 5d4ab308ca..5d7d765e3d 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -1848,7 +1848,7 @@ class vector
//! <b>Complexity</b>: Amortized constant time.
void push_back(T &&x);
#else
- BOOST_CONTAINER_FORCEINLINE BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -3120,7 +3120,7 @@ class vector
}
else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
::boost::container::uninitialized_move_alloc_n
- (this->m_holder.alloc(), pos, old_finish - pos, new_start + before_plus_new);
+ (this->m_holder.alloc(), pos, static_cast<size_type>(old_finish - pos), new_start + before_plus_new);
this->m_holder.m_size = new_size;
old_values_destroyer.release();
}
diff --git a/boost/context/detail/apply.hpp b/boost/context/detail/apply.hpp
index 54db844b9e..e1dd40a4db 100644
--- a/boost/context/detail/apply.hpp
+++ b/boost/context/detail/apply.hpp
@@ -15,13 +15,20 @@
#include <boost/config.hpp>
#include <boost/context/detail/config.hpp>
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
#include <boost/context/detail/invoke.hpp>
+#endif
#include <boost/context/detail/index_sequence.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4100)
+#endif
+
namespace boost {
namespace context {
namespace detail {
@@ -29,9 +36,17 @@ namespace detail {
template< typename Fn, typename Tpl, std::size_t ... I >
auto
apply_impl( Fn && fn, Tpl && tpl, index_sequence< I ... >)
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
-> decltype( invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) )
+#else
+ -> decltype( std::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) )
+#endif
{
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
return invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... );
+#else
+ return std::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... );
+#endif
}
template< typename Fn, typename Tpl >
@@ -48,6 +63,10 @@ apply( Fn && fn, Tpl && tpl)
}}}
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
diff --git a/boost/context/detail/invoke.hpp b/boost/context/detail/invoke.hpp
index 5ec54800e3..9173cbc793 100644
--- a/boost/context/detail/invoke.hpp
+++ b/boost/context/detail/invoke.hpp
@@ -23,9 +23,6 @@ namespace boost {
namespace context {
namespace detail {
-#if _MSC_VER > 1800
-using std::invoke;
-#else
template< typename Fn, typename ... Args >
typename std::enable_if<
std::is_member_pointer< typename std::decay< Fn >::type >::value,
@@ -43,7 +40,6 @@ typename std::enable_if<
invoke( Fn && fn, Args && ... args) {
return std::forward< Fn >( fn)( std::forward< Args >( args) ... );
}
-#endif
}}}
diff --git a/boost/context/execution_context.hpp b/boost/context/execution_context.hpp
index 9d9294f91d..2eb02e12ee 100644
--- a/boost/context/execution_context.hpp
+++ b/boost/context/execution_context.hpp
@@ -8,7 +8,11 @@
#if ! defined(BOOST_CONTEXT_NO_CXX11)
# if (defined(BOOST_EXECUTION_CONTEXT) && (BOOST_EXECUTION_CONTEXT == 1))
-# include <boost/context/execution_context_v1.hpp>
+# if !defined(BOOST_NO_CXX11_THREAD_LOCAL)
+# include <boost/context/execution_context_v1.hpp>
+# else
+# error "keyword thread_local not supported"
+# endif
# else
# include <boost/context/execution_context_v2.hpp>
# endif
diff --git a/boost/context/execution_context_v1.hpp b/boost/context/execution_context_v1.hpp
index 6881354c88..f3bef45fb6 100644
--- a/boost/context/execution_context_v1.hpp
+++ b/boost/context/execution_context_v1.hpp
@@ -24,7 +24,9 @@
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
+#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
+#endif
#include <boost/context/detail/disable_overload.hpp>
#include <boost/context/detail/fcontext.hpp>
#include <boost/context/fixedsize_stack.hpp>
@@ -157,7 +159,11 @@ transfer_t context_ontop( transfer_t t) {
BOOST_ASSERT( nullptr != tpl);
auto data = std::get< 0 >( * tpl);
typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 1 >( * tpl) );
+#if defined(BOOST_NO_CXX17_STD_APPLY)
dp->data = apply( fn, std::tie( data) );
+#else
+ dp->data = std::apply( fn, std::tie( data) );
+#endif
return { t.fctx, dp };
}
@@ -196,7 +202,11 @@ public:
void run() {
auto data = caller_->resume( nullptr);
+#if defined(BOOST_NO_CXX17_STD_APPLY)
apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
+#else
+ std::apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
+#endif
BOOST_ASSERT_MSG( ! main_ctx, "main-context does not execute activation-record::run()");
}
};
diff --git a/boost/context/execution_context_v2.hpp b/boost/context/execution_context_v2.hpp
index 1bc5f868d0..a037687258 100644
--- a/boost/context/execution_context_v2.hpp
+++ b/boost/context/execution_context_v2.hpp
@@ -13,6 +13,7 @@
#include <cstddef>
#include <cstdint>
#include <cstdlib>
+#include <exception>
#include <functional>
#include <memory>
#include <ostream>
@@ -23,7 +24,9 @@
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
+#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
+#endif
#include <boost/context/detail/disable_overload.hpp>
#include <boost/context/detail/exception.hpp>
#include <boost/context/detail/exchange.hpp>
@@ -39,63 +42,31 @@
# include BOOST_ABI_PREFIX
#endif
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4702)
+#endif
+
namespace boost {
namespace context {
namespace detail {
-inline
-transfer_t context_unwind( transfer_t t) {
- throw forced_unwind( t.fctx);
- return { nullptr, nullptr };
-}
+transfer_t context_unwind( transfer_t);
template< typename Rec >
-transfer_t context_exit( transfer_t t) noexcept {
- Rec * rec = static_cast< Rec * >( t.data);
- // destroy context stack
- rec->deallocate();
- return { nullptr, nullptr };
-}
+transfer_t context_exit( transfer_t) noexcept;
template< typename Rec >
-void context_entry( transfer_t t_) noexcept {
- // transfer control structure to the context-stack
- Rec * rec = static_cast< Rec * >( t_.data);
- BOOST_ASSERT( nullptr != rec);
- transfer_t t = { nullptr, nullptr };
- try {
- // jump back to `context_create()`
- t = jump_fcontext( t_.fctx, nullptr);
- // start executing
- t = rec->run( t);
- } catch ( forced_unwind const& e) {
- t = { e.fctx, nullptr };
- }
- BOOST_ASSERT( nullptr != t.fctx);
- // destroy context-stack of `this`context on next context
- ontop_fcontext( t.fctx, rec, context_exit< Rec >);
- BOOST_ASSERT_MSG( false, "context already terminated");
-}
+void context_entry( transfer_t) noexcept;
template< typename Ctx, typename Fn, typename ... Args >
-transfer_t context_ontop( transfer_t t) {
- auto tpl = static_cast< std::tuple< Fn, std::tuple< Args ... > > * >( t.data);
- BOOST_ASSERT( nullptr != tpl);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
- auto args = std::move( std::get< 1 >( * tpl) );
- Ctx ctx{ t.fctx };
- // execute function
- auto result = apply(
- fn,
- std::tuple_cat(
- std::forward_as_tuple( std::move( ctx) ),
- std::move( args) ) );
- ctx = std::move( std::get< 0 >( result) );
- // apply returned data
- detail::tail( args) = std::move( result);
- std::get< 1 >( * tpl) = std::move( args);
- return { exchange( ctx.fctx_, nullptr), & std::get< 1 >( * tpl) };
-}
+transfer_t context_ontop( transfer_t);
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( StackAlloc, Fn &&, Params && ...);
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( preallocated, StackAlloc, Fn &&, Params && ...);
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
class record {
@@ -138,77 +109,22 @@ public:
std::forward_as_tuple( std::move( from) ),
std::move( args) );
// invoke context-function
+#if defined(BOOST_NO_CXX17_STD_APPLY)
Ctx cc = apply( std::move( fn_), std::move( tpl) );
+#else
+ Ctx cc = std::apply( std::move( fn_), std::move( tpl) );
+#endif
return { exchange( cc.fctx_, nullptr), nullptr };
}
};
-template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
-fcontext_t context_create( StackAlloc salloc, Fn && fn, Params && ... params) {
- typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
-
- auto sctx = salloc.allocate();
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = sctx.size - sizeof( record_t);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( record_t);
- constexpr std::size_t func_size = sizeof( record_t);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) record_t{
- sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
-fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
- typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
-
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = palloc.size - sizeof( record_t);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( record_t);
- constexpr std::size_t func_size = sizeof( record_t);
- // reserve space on stack
- void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) record_t{
- palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
}
template< typename ... Args >
class execution_context {
private:
+ friend class ontop_error;
+
typedef std::tuple< Args ... > args_tpl_t;
typedef std::tuple< execution_context, typename std::decay< Args >::type ... > ret_tpl_t;
@@ -307,30 +223,10 @@ public:
execution_context( execution_context const& other) noexcept = delete;
execution_context & operator=( execution_context const& other) noexcept = delete;
- ret_tpl_t operator()( Args ... args) {
- BOOST_ASSERT( nullptr != fctx_);
- args_tpl_t data( std::forward< Args >( args) ... );
- detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), & data);
- if ( nullptr != t.data) {
- data = std::move( * static_cast< args_tpl_t * >( t.data) );
- }
- return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
- }
+ ret_tpl_t operator()( Args ... args);
template< typename Fn >
- ret_tpl_t operator()( exec_ontop_arg_t, Fn && fn, Args ... args) {
- BOOST_ASSERT( nullptr != fctx_);
- args_tpl_t data{ std::forward< Args >( args) ... };
- auto p = std::make_tuple( fn, std::move( data) );
- detail::transfer_t t = detail::ontop_fcontext(
- detail::exchange( fctx_, nullptr),
- & p,
- detail::context_ontop< execution_context, Fn, Args ... >);
- if ( nullptr != t.data) {
- data = std::move( * static_cast< args_tpl_t * >( t.data) );
- }
- return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
- }
+ ret_tpl_t operator()( exec_ontop_arg_t, Fn && fn, Args ... args);
explicit operator bool() const noexcept {
return nullptr != fctx_;
@@ -379,6 +275,204 @@ public:
}
};
+class ontop_error : public std::exception {
+private:
+ detail::fcontext_t fctx_;
+
+public:
+ ontop_error( detail::fcontext_t fctx) noexcept :
+ fctx_{ fctx } {
+ }
+
+ template< typename ... Args >
+ execution_context< Args ... > get_context() const noexcept {
+ return execution_context< Args ... >{ fctx_ };
+ }
+};
+
+template< typename ... Args >
+typename execution_context< Args ... >::ret_tpl_t
+execution_context< Args ... >::operator()( Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data( std::forward< Args >( args) ... );
+ auto p = std::make_tuple( std::exception_ptr{}, std::move( data) );
+ detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), & p);
+ if ( nullptr != t.data) {
+ auto p = static_cast< std::tuple< std::exception_ptr, args_tpl_t > * >( t.data);
+ std::exception_ptr eptr = std::get< 0 >( * p);
+ if ( eptr) {
+ try {
+ std::rethrow_exception( eptr);
+ } catch (...) {
+ std::throw_with_nested( ontop_error{ t.fctx } );
+ }
+ }
+ data = std::move( std::get< 1 >( * p) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+}
+
+template< typename ... Args >
+template< typename Fn >
+typename execution_context< Args ... >::ret_tpl_t
+execution_context< Args ... >::operator()( exec_ontop_arg_t, Fn && fn, Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data{ std::forward< Args >( args) ... };
+ auto p = std::make_tuple( fn, std::make_tuple( std::exception_ptr{}, std::move( data) ) );
+ detail::transfer_t t = detail::ontop_fcontext(
+ detail::exchange( fctx_, nullptr),
+ & p,
+ detail::context_ontop< execution_context, Fn, Args ... >);
+ if ( nullptr != t.data) {
+ auto p = static_cast< std::tuple< std::exception_ptr, args_tpl_t > * >( t.data);
+ std::exception_ptr eptr = std::get< 0 >( * p);
+ if ( eptr) {
+ try {
+ std::rethrow_exception( eptr);
+ } catch (...) {
+ std::throw_with_nested( ontop_error{ t.fctx } );
+ }
+ }
+ data = std::move( std::get< 1 >( * p) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+}
+
+namespace detail {
+
+template< int N >
+struct helper {
+ template< typename T >
+ static T convert( T && t) noexcept {
+ return std::forward< T >( t);
+ }
+};
+
+template<>
+struct helper< 1 > {
+ template< typename T >
+ static std::tuple< T > convert( T && t) noexcept {
+ return std::make_tuple( std::forward< T >( t) );
+ }
+};
+
+inline
+transfer_t context_unwind( transfer_t t) {
+ throw forced_unwind( t.fctx);
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+transfer_t context_exit( transfer_t t) noexcept {
+ Rec * rec = static_cast< Rec * >( t.data);
+ // destroy context stack
+ rec->deallocate();
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+void context_entry( transfer_t t_) noexcept {
+ // transfer control structure to the context-stack
+ Rec * rec = static_cast< Rec * >( t_.data);
+ BOOST_ASSERT( nullptr != rec);
+ transfer_t t = { nullptr, nullptr };
+ try {
+ // jump back to `context_create()`
+ t = jump_fcontext( t_.fctx, nullptr);
+ // start executing
+ t = rec->run( t);
+ } catch ( forced_unwind const& e) {
+ t = { e.fctx, nullptr };
+ }
+ BOOST_ASSERT( nullptr != t.fctx);
+ // destroy context-stack of `this`context on next context
+ ontop_fcontext( t.fctx, rec, context_exit< Rec >);
+ BOOST_ASSERT_MSG( false, "context already terminated");
+}
+
+template< typename Ctx, typename Fn, typename ... Args >
+transfer_t context_ontop( transfer_t t) {
+ auto p = static_cast< std::tuple< Fn, std::tuple< std::exception_ptr, std::tuple< Args ... > > > * >( t.data);
+ BOOST_ASSERT( nullptr != p);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
+ auto args = std::move( std::get< 1 >( std::get< 1 >( * p) ) );
+ try {
+ // execute function
+#if defined(BOOST_NO_CXX17_STD_APPLY)
+ std::get< 1 >( std::get< 1 >( * p) ) = helper< sizeof ... (Args) >::convert( apply( fn, std::move( args) ) );
+#else
+ std::get< 1 >( std::get< 1 >( * p) ) = helper< sizeof ... (Args) >::convert( std::apply( fn, std::move( args) ) );
+#endif
+ } catch (...) {
+ std::get< 0 >( std::get< 1 >( * p) ) = std::current_exception();
+ }
+ // apply returned data
+ return { t.fctx, & std::get< 1 >( * p) };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
+
#include <boost/context/execution_context_v2_void.ipp>
template< typename ... Args >
@@ -388,6 +482,10 @@ void swap( execution_context< Args ... > & l, execution_context< Args ... > & r)
}}
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
diff --git a/boost/context/execution_context_v2_void.ipp b/boost/context/execution_context_v2_void.ipp
index d0659beafb..fdf15cd564 100644
--- a/boost/context/execution_context_v2_void.ipp
+++ b/boost/context/execution_context_v2_void.ipp
@@ -7,17 +7,13 @@
namespace detail {
template< typename Ctx, typename Fn >
-transfer_t context_ontop_void( transfer_t t) {
- auto tpl = static_cast< std::tuple< Fn > * >( t.data);
- BOOST_ASSERT( nullptr != tpl);
- typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
- Ctx ctx{ t.fctx };
- // execute function
- ctx = apply(
- fn,
- std::forward_as_tuple( std::move( ctx) ) );
- return { exchange( ctx.fctx_, nullptr), nullptr };
-}
+transfer_t context_ontop_void( transfer_t);
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( StackAlloc, Fn &&, Params && ...);
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( preallocated, StackAlloc, Fn &&, Params && ...);
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
class record_void {
@@ -55,81 +51,22 @@ public:
transfer_t run( transfer_t t) {
Ctx from{ t.fctx };
// invoke context-function
- Ctx cc = apply(
- fn_,
- std::tuple_cat(
- params_,
- std::forward_as_tuple( std::move( from) ) ) );
+#if defined(BOOST_NO_CXX17_STD_APPLY)
+ Ctx cc = apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
+#else
+ Ctx cc = std::apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
+#endif
return { exchange( cc.fctx_, nullptr), nullptr };
}
};
-template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
-fcontext_t context_create_void( StackAlloc salloc, Fn && fn, Params && ... params) {
- typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
-
- auto sctx = salloc.allocate();
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = sctx.size - sizeof( record_t);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( record_t);
- constexpr std::size_t func_size = sizeof( record_t);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) record_t{
- sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
-template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
-fcontext_t context_create_void( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
- typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
-
- // reserve space for control structure
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- const std::size_t size = palloc.size - sizeof( record_t);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( record_t);
- constexpr std::size_t func_size = sizeof( record_t);
- // reserve space on stack
- void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
- BOOST_ASSERT( nullptr != fctx);
- // placment new for control structure on context-stack
- auto rec = ::new ( sp) record_t{
- palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
- // transfer control structure to context-stack
- return jump_fcontext( fctx, rec).fctx;
-}
-
}
template<>
class execution_context< void > {
private:
+ friend class ontop_error;
+
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
friend class detail::record_void;
@@ -228,17 +165,33 @@ public:
execution_context operator()() {
BOOST_ASSERT( nullptr != fctx_);
detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), nullptr);
+ if ( nullptr != t.data) {
+ std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
+ try {
+ std::rethrow_exception( * eptr);
+ } catch (...) {
+ std::throw_with_nested( ontop_error{ t.fctx } );
+ }
+ }
return execution_context( t.fctx);
}
template< typename Fn >
execution_context operator()( exec_ontop_arg_t, Fn && fn) {
BOOST_ASSERT( nullptr != fctx_);
- std::tuple< Fn > p = std::forward_as_tuple( fn);
+ auto p = std::make_tuple( fn, std::exception_ptr{} );
detail::transfer_t t = detail::ontop_fcontext(
detail::exchange( fctx_, nullptr),
& p,
detail::context_ontop_void< execution_context, Fn >);
+ if ( nullptr != t.data) {
+ std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
+ try {
+ std::rethrow_exception( * eptr);
+ } catch (...) {
+ std::throw_with_nested( ontop_error{ t.fctx } );
+ }
+ }
return execution_context( t.fctx);
}
@@ -288,3 +241,83 @@ public:
std::swap( fctx_, other.fctx_);
}
};
+
+namespace detail {
+
+template< typename Ctx, typename Fn >
+transfer_t context_ontop_void( transfer_t t) {
+ auto p = static_cast< std::tuple< Fn, std::exception_ptr > * >( t.data);
+ BOOST_ASSERT( nullptr != p);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
+ try {
+ // execute function
+ fn();
+ } catch (...) {
+ std::get< 1 >( * p) = std::current_exception();
+ return { t.fctx, & std::get< 1 >( * p ) };
+ }
+ return { exchange( t.fctx, nullptr), nullptr };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
diff --git a/boost/convert.hpp b/boost/convert.hpp
index fd38fc1c01..8bb93b5912 100644
--- a/boost/convert.hpp
+++ b/boost/convert.hpp
@@ -1,6 +1,6 @@
/// @file
// Boost.Convert
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
//
// Many thanks to Julian Gonggrijp, Rob Stewart, Andrzej Krzemienski, Matus Chochlik, Jeroen Habraken,
// Hartmut Kaiser, Joel De Guzman, Thijs (M.A.) van den Berg, Roland Bock, Gavin Lambert, Paul Bristow,
diff --git a/boost/convert/base.hpp b/boost/convert/base.hpp
index 3d446641d2..41c0e4b29b 100644
--- a/boost/convert/base.hpp
+++ b/boost/convert/base.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/boost_parameter_ext.hpp b/boost/convert/detail/boost_parameter_ext.hpp
index a384018cfb..8d2ee3c402 100644
--- a/boost/convert/detail/boost_parameter_ext.hpp
+++ b/boost/convert/detail/boost_parameter_ext.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/char.hpp b/boost/convert/detail/char.hpp
index 5b3cbda10e..1d375bad51 100644
--- a/boost/convert/detail/char.hpp
+++ b/boost/convert/detail/char.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/forward.hpp b/boost/convert/detail/forward.hpp
index 8d86d8c6a1..0fc55c3aca 100644
--- a/boost/convert/detail/forward.hpp
+++ b/boost/convert/detail/forward.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/has_member.hpp b/boost/convert/detail/has_member.hpp
index fafc39f5c4..68e53807a9 100644
--- a/boost/convert/detail/has_member.hpp
+++ b/boost/convert/detail/has_member.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/is_callable.hpp b/boost/convert/detail/is_callable.hpp
index d516fdc05b..838c248c63 100644
--- a/boost/convert/detail/is_callable.hpp
+++ b/boost/convert/detail/is_callable.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/is_converter.hpp b/boost/convert/detail/is_converter.hpp
index b35470cd19..7633b6daba 100644
--- a/boost/convert/detail/is_converter.hpp
+++ b/boost/convert/detail/is_converter.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/is_fun.hpp b/boost/convert/detail/is_fun.hpp
index 5e1eae2ca6..9fa4d96f9b 100644
--- a/boost/convert/detail/is_fun.hpp
+++ b/boost/convert/detail/is_fun.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/is_string.hpp b/boost/convert/detail/is_string.hpp
index ab682b0c72..ea6ca82e90 100644
--- a/boost/convert/detail/is_string.hpp
+++ b/boost/convert/detail/is_string.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/detail/range.hpp b/boost/convert/detail/range.hpp
index cdfe7b7401..345321039e 100644
--- a/boost/convert/detail/range.hpp
+++ b/boost/convert/detail/range.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/lexical_cast.hpp b/boost/convert/lexical_cast.hpp
index 5a9f77b845..49b96a15df 100644
--- a/boost/convert/lexical_cast.hpp
+++ b/boost/convert/lexical_cast.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/parameters.hpp b/boost/convert/parameters.hpp
index ae5511bfae..fc427c19b5 100644
--- a/boost/convert/parameters.hpp
+++ b/boost/convert/parameters.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/printf.hpp b/boost/convert/printf.hpp
index d33b873d05..443464f0e2 100644
--- a/boost/convert/printf.hpp
+++ b/boost/convert/printf.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/spirit.hpp b/boost/convert/spirit.hpp
index 34ad811b2b..22a88b9b3f 100644
--- a/boost/convert/spirit.hpp
+++ b/boost/convert/spirit.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/stream.hpp b/boost/convert/stream.hpp
index c0f4890b36..086d836175 100644
--- a/boost/convert/stream.hpp
+++ b/boost/convert/stream.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
diff --git a/boost/convert/strtol.hpp b/boost/convert/strtol.hpp
index 5d10bde5a7..de5aa29a8a 100644
--- a/boost/convert/strtol.hpp
+++ b/boost/convert/strtol.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2014 Vladimir Batov.
+// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
@@ -31,18 +31,6 @@ namespace boost { namespace cnv
struct boost::cnv::strtol : public boost::cnv::cnvbase<boost::cnv::strtol>
{
- // C2. Old C-strings have an advantage over [begin, end) ranges. They do not need the 'end' iterator!
- // Instead, they provide a sentinel (0 terminator). Consequently, C strings can be traversed
- // without the need to compare if the 'end' has been reached (i.e. "for (; it != end; ++it)").
- // Instead, the current character is checked if it's 0 (i.e. "for (; *p; ++p)") which is faster.
- //
- // So, the implementation takes advantage of the fact. Namely, we simply check if *cnv_end == 0
- // instead of traversing once with strlen() to find the end iterator and then comparing to it as in
- //
- // char const* str_end = str + strlen(str); // Unnecessary traversal!
- // ...
- // bool const good = ... && cnv_end == str_end;
-
typedef boost::cnv::strtol this_type;
typedef boost::cnv::cnvbase<this_type> base_type;
@@ -209,14 +197,20 @@ template<typename string_type, typename out_type>
void
boost::cnv::strtol::str_to_d(cnv::range<string_type> range, optional<out_type>& result_out) const
{
- typedef cnv::range<string_type> range_type;
- typedef typename range_type::value_type char_type;
-
- char_type const* str = &*range.begin(); // Currently only works with 'char'
- char* cnv_end = 0;
- ldbl_type const result = strtold(str, &cnv_end);
- bool const good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0/*C2*/;
- out_type const max = (std::numeric_limits<out_type>::max)();
+ // C2. Simply check if the end-of-string was reached -- *cnv_end == 0
+ // instead of traversing once with strlen() to find the end iterator
+ // and then comparing to it as in
+ // char const* end = str + strlen(str); // Unnecessary traversal!
+ // bool const good = ... && cnv_end == end;
+
+ typedef cnv::range<string_type> range_type;
+ typedef typename range_type::value_type ch_type;
+
+ ch_type const* str = &*range.begin(); // Currently only works with 'char'
+ char* cnv_end = 0;
+ ldbl_type result = strtold(str, &cnv_end);
+ bool good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0/*C2*/;
+ out_type max = (std::numeric_limits<out_type>::max)();
if (good && -max <= result && result <= max)
result_out = out_type(result);
diff --git a/boost/core/lightweight_test.hpp b/boost/core/lightweight_test.hpp
index cdc8a72d8b..d6db024250 100644
--- a/boost/core/lightweight_test.hpp
+++ b/boost/core/lightweight_test.hpp
@@ -85,6 +85,22 @@ inline void throw_failed_impl(char const * excep, char const * file, int line, c
++test_errors();
}
+// In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
+// A cleaner fix would require common_type trait or some meta-programming, which would introduce a dependency on Boost.TypeTraits. To avoid
+// the dependency we just disable the warnings.
+#if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable: 4389)
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wsign-compare")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wsign-compare"
+# endif
+#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsign-compare"
+#endif
+
template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2,
char const * file, int line, char const * function, T const & t, U const & u )
{
@@ -119,6 +135,16 @@ template<class T, class U> inline void test_ne_impl( char const * expr1, char co
}
}
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wsign-compare")
+# pragma clang diagnostic pop
+# endif
+#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+# pragma GCC diagnostic pop
+#endif
+
} // namespace detail
inline int report_errors()
@@ -144,6 +170,7 @@ inline int report_errors()
} // namespace boost
#define BOOST_TEST(expr) ((expr)? (void)0: ::boost::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION))
+#define BOOST_TEST_NOT(expr) BOOST_TEST(!(expr))
#define BOOST_ERROR(msg) ( ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
diff --git a/boost/coroutine/detail/config.hpp b/boost/coroutine/detail/config.hpp
index 8043e6cf8c..12632bbf7b 100644
--- a/boost/coroutine/detail/config.hpp
+++ b/boost/coroutine/detail/config.hpp
@@ -10,11 +10,11 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
-#ifndef BOOST_COROUTINE_NO_DEPRECATION_WARNING
+#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
-# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINE_NO_DEPRECATION_WARNING.")
+# pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
# elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
-# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINE_NO_DEPRECATION_WARNING."
+# warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
# endif
#endif
diff --git a/boost/coroutine2/detail/pull_control_block_ecv2.ipp b/boost/coroutine2/detail/pull_control_block_ecv2.ipp
index 766a3f59c7..a1c7c93cd0 100644
--- a/boost/coroutine2/detail/pull_control_block_ecv2.ipp
+++ b/boost/coroutine2/detail/pull_control_block_ecv2.ipp
@@ -49,7 +49,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T *) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T *) mutable {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb };
@@ -78,7 +78,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
std::placeholders::_2))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T *) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
// create synthesized push_coroutine< T >
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb };
@@ -199,7 +199,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T *> ctx, T *) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T *> && ctx, T *) mutable {
// create synthesized push_coroutine< T & >
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb };
@@ -228,7 +228,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
std::placeholders::_2))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T *) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
// create synthesized push_coroutine< T & >
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb };
@@ -323,7 +323,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > ctx) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
// create synthesized push_coroutine< void >
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb };
@@ -350,7 +350,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
std::placeholders::_1))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > ctx) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
// create synthesized push_coroutine< void >
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb };
diff --git a/boost/coroutine2/detail/pull_coroutine.hpp b/boost/coroutine2/detail/pull_coroutine.hpp
index 7123eac8b8..b97bdc3e9c 100644
--- a/boost/coroutine2/detail/pull_coroutine.hpp
+++ b/boost/coroutine2/detail/pull_coroutine.hpp
@@ -47,7 +47,7 @@ public:
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine() noexcept;
+ ~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
@@ -159,7 +159,7 @@ public:
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine() noexcept;
+ ~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
@@ -269,7 +269,7 @@ public:
template< typename StackAllocator, typename Fn >
pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine() noexcept;
+ ~pull_coroutine();
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
diff --git a/boost/coroutine2/detail/pull_coroutine.ipp b/boost/coroutine2/detail/pull_coroutine.ipp
index 58fe84575e..9a81893ccb 100644
--- a/boost/coroutine2/detail/pull_coroutine.ipp
+++ b/boost/coroutine2/detail/pull_coroutine.ipp
@@ -59,7 +59,7 @@ pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
}
template< typename T >
-pull_coroutine< T >::~pull_coroutine() noexcept {
+pull_coroutine< T >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
@@ -128,7 +128,7 @@ pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
}
template< typename T >
-pull_coroutine< T & >::~pull_coroutine() noexcept {
+pull_coroutine< T & >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
@@ -189,7 +189,7 @@ pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
}
inline
-pull_coroutine< void >::~pull_coroutine() noexcept {
+pull_coroutine< void >::~pull_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
diff --git a/boost/coroutine2/detail/push_control_block_ecv2.ipp b/boost/coroutine2/detail/push_control_block_ecv2.ipp
index f940bb13b7..7ed6c572e1 100644
--- a/boost/coroutine2/detail/push_control_block_ecv2.ipp
+++ b/boost/coroutine2/detail/push_control_block_ecv2.ipp
@@ -48,7 +48,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T * data) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
@@ -79,7 +79,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
std::placeholders::_2))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T * data) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
// create synthesized pull_coroutine< T >
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
@@ -178,7 +178,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T * data) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
// create synthesized pull_coroutine< T & >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
@@ -209,7 +209,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
std::placeholders::_2))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T * data) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
// create synthesized pull_coroutine< T & >
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
@@ -295,7 +295,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
ctx{ std::allocator_arg, palloc, salloc,
std::move(
std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > ctx) mutable {
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
// create synthesized pull_coroutine< void >
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb };
@@ -322,7 +322,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
std::placeholders::_1))},
#else
ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > ctx) mutable {
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
// create synthesized pull_coroutine< void >
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx};
pull_coroutine< void > synthesized{ & synthesized_cb };
diff --git a/boost/coroutine2/detail/push_coroutine.hpp b/boost/coroutine2/detail/push_coroutine.hpp
index 5d9d092b65..1b62663ab7 100644
--- a/boost/coroutine2/detail/push_coroutine.hpp
+++ b/boost/coroutine2/detail/push_coroutine.hpp
@@ -45,7 +45,7 @@ public:
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine() noexcept;
+ ~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
@@ -125,7 +125,7 @@ public:
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine() noexcept;
+ ~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
@@ -203,7 +203,7 @@ public:
template< typename StackAllocator, typename Fn >
push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine() noexcept;
+ ~push_coroutine();
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
diff --git a/boost/coroutine2/detail/push_coroutine.ipp b/boost/coroutine2/detail/push_coroutine.ipp
index 304e07729e..303961b10f 100644
--- a/boost/coroutine2/detail/push_coroutine.ipp
+++ b/boost/coroutine2/detail/push_coroutine.ipp
@@ -48,7 +48,7 @@ push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
}
template< typename T >
-push_coroutine< T >::~push_coroutine() noexcept {
+push_coroutine< T >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
@@ -108,7 +108,7 @@ push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
}
template< typename T >
-push_coroutine< T & >::~push_coroutine() noexcept {
+push_coroutine< T & >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
@@ -159,7 +159,7 @@ push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
}
inline
-push_coroutine< void >::~push_coroutine() noexcept {
+push_coroutine< void >::~push_coroutine() {
if ( nullptr != cb_) {
cb_->deallocate();
}
diff --git a/boost/current_function.hpp b/boost/current_function.hpp
index 5c113f8093..86955cb041 100644
--- a/boost/current_function.hpp
+++ b/boost/current_function.hpp
@@ -28,7 +28,11 @@ namespace detail
inline void current_function_helper()
{
-#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
+#if defined( BOOST_DISABLE_CURRENT_FUNCTION )
+
+# define BOOST_CURRENT_FUNCTION "(unknown)"
+
+#elif defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
diff --git a/boost/date_time/gregorian/greg_facet.hpp b/boost/date_time/gregorian/greg_facet.hpp
index b8c6d57fe5..624c96e1ed 100644
--- a/boost/date_time/gregorian/greg_facet.hpp
+++ b/boost/date_time/gregorian/greg_facet.hpp
@@ -290,7 +290,17 @@ namespace gregorian {
* names as a default. */
catch(std::bad_cast&){
charT a = '\0';
+
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
std::auto_ptr< const facet_def > f(create_facet_def(a));
+
+#else
+
+ std::unique_ptr< const facet_def > f(create_facet_def(a));
+
+#endif
+
num = date_time::find_match(f->get_short_month_names(),
f->get_long_month_names(),
(greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size,
@@ -332,7 +342,17 @@ namespace gregorian {
* names as a default. */
catch(std::bad_cast&){
charT a = '\0';
+
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
std::auto_ptr< const facet_def > f(create_facet_def(a));
+
+#else
+
+ std::unique_ptr< const facet_def > f(create_facet_def(a));
+
+#endif
+
num = date_time::find_match(f->get_short_weekday_names(),
f->get_long_weekday_names(),
(greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed
diff --git a/boost/date_time/gregorian/greg_serialize.hpp b/boost/date_time/gregorian/greg_serialize.hpp
index a870c7068a..6740a0c50f 100644
--- a/boost/date_time/gregorian/greg_serialize.hpp
+++ b/boost/date_time/gregorian/greg_serialize.hpp
@@ -34,6 +34,11 @@ BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_before)
BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_after)
namespace boost {
+
+ namespace gregorian {
+ std::string to_iso_string(const date&);
+ }
+
namespace serialization {
/*! Method that does serialization for gregorian::date -- splits to load/save
diff --git a/boost/detail/winapi/file_management.hpp b/boost/detail/winapi/file_management.hpp
index 4c28bec5b6..80567bd477 100644
--- a/boost/detail/winapi/file_management.hpp
+++ b/boost/detail/winapi/file_management.hpp
@@ -157,6 +157,12 @@ SetFilePointer(
boost::detail::winapi::LONG_ lpDistanceToMove,
boost::detail::winapi::PLONG_ lpDistanceToMoveHigh,
boost::detail::winapi::DWORD_ dwMoveMethod);
+
+struct _BY_HANDLE_FILE_INFORMATION;
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+GetFileInformationByHandle(
+ boost::detail::winapi::HANDLE_ hFile,
+ ::_BY_HANDLE_FILE_INFORMATION* lpFileInformation);
}
#endif
@@ -358,6 +364,19 @@ typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _WIN32_FIND_DATAW {
#endif
} WIN32_FIND_DATAW_, *PWIN32_FIND_DATAW_, *LPWIN32_FIND_DATAW_;
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _BY_HANDLE_FILE_INFORMATION {
+ DWORD_ dwFileAttributes;
+ FILETIME_ ftCreationTime;
+ FILETIME_ ftLastAccessTime;
+ FILETIME_ ftLastWriteTime;
+ DWORD_ dwVolumeSerialNumber;
+ DWORD_ nFileSizeHigh;
+ DWORD_ nFileSizeLow;
+ DWORD_ nNumberOfLinks;
+ DWORD_ nFileIndexHigh;
+ DWORD_ nFileIndexLow;
+} BY_HANDLE_FILE_INFORMATION_, *PBY_HANDLE_FILE_INFORMATION_, *LPBY_HANDLE_FILE_INFORMATION_;
+
BOOST_FORCEINLINE HANDLE_ FindFirstFileW(LPCWSTR_ lpFileName, WIN32_FIND_DATAW_* lpFindFileData)
{
return ::FindFirstFileW(lpFileName, reinterpret_cast< ::_WIN32_FIND_DATAW* >(lpFindFileData));
@@ -504,6 +523,11 @@ BOOST_FORCEINLINE DWORD_ get_file_attributes(LPCWSTR_ lpFileName)
return ::GetFileAttributesW(lpFileName);
}
+BOOST_FORCEINLINE BOOL_ GetFileInformationByHandle(HANDLE_ h, BY_HANDLE_FILE_INFORMATION_* info)
+{
+ return ::GetFileInformationByHandle(h, reinterpret_cast< ::_BY_HANDLE_FILE_INFORMATION* >(info));
+}
+
}
}
}
diff --git a/boost/detail/winapi/system.hpp b/boost/detail/winapi/system.hpp
index 93a5eeb11c..bdfff662f8 100644
--- a/boost/detail/winapi/system.hpp
+++ b/boost/detail/winapi/system.hpp
@@ -17,6 +17,12 @@
#pragma once
#endif
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+// nonstandard extension used : nameless struct/union
+#pragma warning(disable: 4201)
+#endif
+
#if !defined( BOOST_USE_WINDOWS_H )
extern "C" {
struct _SYSTEM_INFO;
@@ -70,4 +76,8 @@ BOOST_FORCEINLINE VOID_ GetNativeSystemInfo(LPSYSTEM_INFO_ lpSystemInfo)
}
}
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
#endif // BOOST_DETAIL_WINAPI_SYSTEM_HPP
diff --git a/boost/exception/detail/error_info_impl.hpp b/boost/exception/detail/error_info_impl.hpp
index dbe0afdb21..ecd086dd87 100644
--- a/boost/exception/detail/error_info_impl.hpp
+++ b/boost/exception/detail/error_info_impl.hpp
@@ -43,7 +43,7 @@ boost
error_info:
public exception_detail::error_info_base
{
- public:
+ public:
typedef T value_type;
@@ -67,7 +67,7 @@ boost
return value_;
}
- private:
+ private:
error_info & operator=( error_info const & );
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
error_info & operator=( error_info && x );
diff --git a/boost/exception/detail/shared_ptr.hpp b/boost/exception/detail/shared_ptr.hpp
new file mode 100644
index 0000000000..51febe8c8f
--- /dev/null
+++ b/boost/exception/detail/shared_ptr.hpp
@@ -0,0 +1,17 @@
+//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the Boost Software License, Version 1.0. (See accompanying
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef UUID_837060E885AF11E68DA91D15E31AC075
+#define UUID_837060E885AF11E68DA91D15E31AC075
+
+#ifdef BOOST_EXCEPTION_MINI_BOOST
+#include <memory>
+namespace boost { namespace exception_detail { using std::shared_ptr; } }
+#else
+#include <boost/shared_ptr.hpp>
+namespace boost { namespace exception_detail { using boost::shared_ptr; } }
+#endif
+
+#endif
diff --git a/boost/exception/errinfo_api_function.hpp b/boost/exception/errinfo_api_function.hpp
index 481c61314e..0cbbdb90ca 100644
--- a/boost/exception/errinfo_api_function.hpp
+++ b/boost/exception/errinfo_api_function.hpp
@@ -6,7 +6,7 @@
#ifndef UUID_DDFBB4546C1211DEA4659E9055D89593
#define UUID_DDFBB4546C1211DEA4659E9055D89593
-#include "boost/exception/error_info.hpp"
+#include <boost/exception/error_info.hpp>
namespace
boost
diff --git a/boost/exception/errinfo_errno.hpp b/boost/exception/errinfo_errno.hpp
index 657b5f76d5..de44e17155 100644
--- a/boost/exception/errinfo_errno.hpp
+++ b/boost/exception/errinfo_errno.hpp
@@ -13,7 +13,7 @@
#pragma warning(disable:4996)
#endif
-#include "boost/exception/info.hpp"
+#include <boost/exception/info.hpp>
#include <errno.h>
#include <string.h>
diff --git a/boost/exception/exception.hpp b/boost/exception/exception.hpp
index 213af3dbb8..c0fdaf9e55 100644
--- a/boost/exception/exception.hpp
+++ b/boost/exception/exception.hpp
@@ -12,6 +12,14 @@
#pragma warning(push,1)
#endif
+#ifdef BOOST_EXCEPTION_MINI_BOOST
+#include <memory>
+namespace boost { namespace exception_detail { using std::shared_ptr; } }
+#else
+namespace boost { template <class T> class shared_ptr; };
+namespace boost { namespace exception_detail { using boost::shared_ptr; } }
+#endif
+
namespace
boost
{
@@ -144,9 +152,6 @@ boost
# endif
#endif
- template <class T>
- class shared_ptr;
-
namespace
exception_detail
{
diff --git a/boost/exception/get_error_info.hpp b/boost/exception/get_error_info.hpp
index 96be7632cb..51a21ba899 100644
--- a/boost/exception/get_error_info.hpp
+++ b/boost/exception/get_error_info.hpp
@@ -15,7 +15,8 @@
#include <boost/exception/exception.hpp>
#include <boost/exception/detail/error_info_impl.hpp>
#include <boost/exception/detail/type_info.hpp>
-#include <boost/shared_ptr.hpp>
+#include <boost/exception/detail/shared_ptr.hpp>
+#include <boost/assert.hpp>
namespace
boost
diff --git a/boost/exception/info.hpp b/boost/exception/info.hpp
index f955e09845..f06df42aaf 100644
--- a/boost/exception/info.hpp
+++ b/boost/exception/info.hpp
@@ -15,7 +15,7 @@
#include <boost/exception/exception.hpp>
#include <boost/exception/to_string_stub.hpp>
#include <boost/exception/detail/error_info_impl.hpp>
-#include <boost/shared_ptr.hpp>
+#include <boost/exception/detail/shared_ptr.hpp>
#include <boost/config.hpp>
#include <map>
@@ -47,27 +47,27 @@ boost
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template <class Tag,class T>
+ template <class Tag,class T>
inline
error_info<Tag,T>::
- error_info( error_info const & x ):
- value_(x.value_)
- {
- }
+ error_info( error_info const & x ):
+ value_(x.value_)
+ {
+ }
template <class Tag,class T>
inline
error_info<Tag,T>::
- error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value)))):
- value_(std::move(value))
- {
- }
- template <class Tag,class T>
+ error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value)))):
+ value_(std::move(value))
+ {
+ }
+ template <class Tag,class T>
inline
error_info<Tag,T>::
- error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_)))):
- value_(std::move(x.value_))
- {
- }
+ error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_)))):
+ value_(std::move(x.value_))
+ {
+ }
#endif
template <class Tag,class T>
@@ -202,79 +202,79 @@ boost
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class E,class Tag,class T>
E const & set_info( E const &, error_info<Tag,T> && );
- template <class T>
- class set_info_rv;
- template <class Tag,class T>
- class
- set_info_rv<error_info<Tag,T> >
- {
- template <class E,class Tag1,class T1>
- friend E const & set_info( E const &, error_info<Tag1,T1> && );
- template <class E>
- static
- E const &
- set( E const & x, error_info<Tag,T> && v )
- {
- typedef error_info<Tag,T> error_info_tag_t;
- shared_ptr<error_info_tag_t> p( new error_info_tag_t(std::move(v)) );
- exception_detail::error_info_container * c=x.data_.get();
- if( !c )
- x.data_.adopt(c=new exception_detail::error_info_container_impl);
- c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));
- return x;
- }
- };
- template <>
- class
- set_info_rv<throw_function>
- {
- template <class E,class Tag1,class T1>
- friend E const & set_info( E const &, error_info<Tag1,T1> && );
- template <class E>
- static
- E const &
- set( E const & x, throw_function && y )
- {
- x.throw_function_=y.v_;
- return x;
- }
- };
- template <>
- class
- set_info_rv<throw_file>
- {
- template <class E,class Tag1,class T1>
- friend E const & set_info( E const &, error_info<Tag1,T1> && );
- template <class E>
- static
- E const &
- set( E const & x, throw_file && y )
- {
- x.throw_file_=y.v_;
- return x;
- }
- };
- template <>
- class
- set_info_rv<throw_line>
- {
- template <class E,class Tag1,class T1>
- friend E const & set_info( E const &, error_info<Tag1,T1> && );
- template <class E>
- static
- E const &
- set( E const & x, throw_line && y )
- {
- x.throw_line_=y.v_;
- return x;
- }
- };
+ template <class T>
+ struct set_info_rv;
+ template <class Tag,class T>
+ struct
+ set_info_rv<error_info<Tag,T> >
+ {
+ template <class E,class Tag1,class T1>
+ friend E const & set_info( E const &, error_info<Tag1,T1> && );
+ template <class E>
+ static
+ E const &
+ set( E const & x, error_info<Tag,T> && v )
+ {
+ typedef error_info<Tag,T> error_info_tag_t;
+ shared_ptr<error_info_tag_t> p( new error_info_tag_t(std::move(v)) );
+ exception_detail::error_info_container * c=x.data_.get();
+ if( !c )
+ x.data_.adopt(c=new exception_detail::error_info_container_impl);
+ c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));
+ return x;
+ }
+ };
+ template <>
+ struct
+ set_info_rv<throw_function>
+ {
+ template <class E,class Tag1,class T1>
+ friend E const & set_info( E const &, error_info<Tag1,T1> && );
+ template <class E>
+ static
+ E const &
+ set( E const & x, throw_function && y )
+ {
+ x.throw_function_=y.v_;
+ return x;
+ }
+ };
+ template <>
+ struct
+ set_info_rv<throw_file>
+ {
+ template <class E,class Tag1,class T1>
+ friend E const & set_info( E const &, error_info<Tag1,T1> && );
+ template <class E>
+ static
+ E const &
+ set( E const & x, throw_file && y )
+ {
+ x.throw_file_=y.v_;
+ return x;
+ }
+ };
+ template <>
+ struct
+ set_info_rv<throw_line>
+ {
+ template <class E,class Tag1,class T1>
+ friend E const & set_info( E const &, error_info<Tag1,T1> && );
+ template <class E>
+ static
+ E const &
+ set( E const & x, throw_line && y )
+ {
+ x.throw_line_=y.v_;
+ return x;
+ }
+ };
template <class E,class Tag,class T>
inline
E const &
set_info( E const & x, error_info<Tag,T> && v )
{
- return set_info_rv<error_info<Tag,T> >::template set<E>(x,std::move(v));
+ return set_info_rv<error_info<Tag,T> >::template set<E>(x,std::move(v));
}
#endif
diff --git a/boost/fiber/algo/work_stealing.hpp b/boost/fiber/algo/work_stealing.hpp
new file mode 100644
index 0000000000..12364ece8c
--- /dev/null
+++ b/boost/fiber/algo/work_stealing.hpp
@@ -0,0 +1,82 @@
+
+// Copyright Oliver Kowalke 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_FIBERS_ALGO_WORK_STEALING_H
+#define BOOST_FIBERS_ALGO_WORK_STEALING_H
+
+#include <condition_variable>
+#include <chrono>
+#include <cstddef>
+#include <mutex>
+#include <vector>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/algo/algorithm.hpp>
+#include <boost/fiber/detail/context_spmc_queue.hpp>
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/scheduler.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace algo {
+
+class work_stealing : public algorithm {
+private:
+ typedef scheduler::ready_queue_t lqueue_t;
+
+ static std::vector< work_stealing * > schedulers_;
+
+ std::size_t idx_;
+ std::size_t max_idx_;
+ detail::context_spmc_queue rqueue_{};
+ lqueue_t lqueue_{};
+ std::mutex mtx_{};
+ std::condition_variable cnd_{};
+ bool flag_{ false };
+ bool suspend_;
+
+ static void init_( std::size_t max_idx);
+
+public:
+ work_stealing( std::size_t max_idx, std::size_t idx, bool suspend = false);
+
+ work_stealing( work_stealing const&) = delete;
+ work_stealing( work_stealing &&) = delete;
+
+ work_stealing & operator=( work_stealing const&) = delete;
+ work_stealing & operator=( work_stealing &&) = delete;
+
+ void awakened( context * ctx) noexcept;
+
+ context * pick_next() noexcept;
+
+ context * steal() noexcept {
+ return rqueue_.pop();
+ }
+
+ bool has_ready_fibers() const noexcept {
+ return ! rqueue_.empty() || ! lqueue_.empty();
+ }
+
+ void suspend_until( std::chrono::steady_clock::time_point const& time_point) noexcept;
+
+ void notify() noexcept;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_ALGO_WORK_STEALING_H
diff --git a/boost/fiber/all.hpp b/boost/fiber/all.hpp
index 21620a99b9..460df5295b 100644
--- a/boost/fiber/all.hpp
+++ b/boost/fiber/all.hpp
@@ -10,25 +10,29 @@
#include <boost/fiber/algo/algorithm.hpp>
#include <boost/fiber/algo/round_robin.hpp>
#include <boost/fiber/algo/shared_work.hpp>
+#include <boost/fiber/algo/work_stealing.hpp>
#include <boost/fiber/barrier.hpp>
-#include <boost/fiber/bounded_channel.hpp>
+#include <boost/fiber/buffered_channel.hpp>
+#include <boost/fiber/channel_op_status.hpp>
#include <boost/fiber/condition_variable.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/fiber.hpp>
#include <boost/fiber/fixedsize_stack.hpp>
-#include <boost/fiber/future.hpp>
#include <boost/fiber/fss.hpp>
+#include <boost/fiber/future.hpp>
#include <boost/fiber/mutex.hpp>
#include <boost/fiber/operations.hpp>
#include <boost/fiber/policy.hpp>
#include <boost/fiber/pooled_fixedsize_stack.hpp>
+#include <boost/fiber/properties.hpp>
#include <boost/fiber/protected_fixedsize_stack.hpp>
#include <boost/fiber/recursive_mutex.hpp>
#include <boost/fiber/recursive_timed_mutex.hpp>
#include <boost/fiber/scheduler.hpp>
#include <boost/fiber/segmented_stack.hpp>
#include <boost/fiber/timed_mutex.hpp>
-#include <boost/fiber/unbounded_channel.hpp>
+#include <boost/fiber/type.hpp>
+#include <boost/fiber/unbuffered_channel.hpp>
#endif // BOOST_FIBERS_H
diff --git a/boost/fiber/bounded_channel.hpp b/boost/fiber/bounded_channel.hpp
index 716080bd2d..ac257b4ff5 100644
--- a/boost/fiber/bounded_channel.hpp
+++ b/boost/fiber/bounded_channel.hpp
@@ -8,6 +8,8 @@
#ifndef BOOST_FIBERS_BOUNDED_CHANNEL_H
#define BOOST_FIBERS_BOUNDED_CHANNEL_H
+#warn "template bounded_channel is deprecated"
+
#include <algorithm>
#include <atomic>
#include <chrono>
diff --git a/boost/fiber/buffered_channel.hpp b/boost/fiber/buffered_channel.hpp
new file mode 100644
index 0000000000..25109a4976
--- /dev/null
+++ b/boost/fiber/buffered_channel.hpp
@@ -0,0 +1,589 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// based on Dmitry Vyukov's MPMC queue
+// (http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue)
+
+#ifndef BOOST_FIBERS_BUFFERED_CHANNEL_H
+#define BOOST_FIBERS_BUFFERED_CHANNEL_H
+
+#include <atomic>
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/channel_op_status.hpp>
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/convert.hpp>
+#include <boost/fiber/detail/spinlock.hpp>
+#include <boost/fiber/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+
+template< typename T >
+class buffered_channel {
+public:
+ typedef T value_type;
+
+private:
+ typedef typename std::aligned_storage< sizeof( T), alignof( T) >::type storage_type;
+ typedef context::wait_queue_t wait_queue_type;
+
+ struct alignas(cache_alignment) slot {
+ std::atomic< std::size_t > cycle{ 0 };
+ storage_type storage{};
+
+ slot() = default;
+ };
+
+ // procuder cacheline
+ alignas(cache_alignment) std::atomic< std::size_t > producer_idx_{ 0 };
+ // consumer cacheline
+ alignas(cache_alignment) std::atomic< std::size_t > consumer_idx_{ 0 };
+ // shared write cacheline
+ alignas(cache_alignment) std::atomic_bool closed_{ false };
+ mutable detail::spinlock splk_{};
+ wait_queue_type waiting_producers_{};
+ wait_queue_type waiting_consumers_{};
+ // shared read cacheline
+ alignas(cache_alignment) slot * slots_{ nullptr };
+ std::size_t capacity_;
+ char pad_[cacheline_length];
+
+ bool is_full_() {
+ std::size_t idx{ producer_idx_.load( std::memory_order_relaxed) };
+ return 0 > static_cast< std::intptr_t >( slots_[idx & (capacity_ - 1)].cycle.load( std::memory_order_acquire) ) - static_cast< std::intptr_t >( idx);
+ }
+
+ bool is_empty_() {
+ std::size_t idx{ consumer_idx_.load( std::memory_order_relaxed) };
+ return 0 > static_cast< std::intptr_t >( slots_[idx & (capacity_ - 1)].cycle.load( std::memory_order_acquire) ) - static_cast< std::intptr_t >( idx + 1);
+ }
+
+ template< typename ValueType >
+ channel_op_status try_push_( ValueType && value) {
+ slot * s{ nullptr };
+ std::size_t idx{ producer_idx_.load( std::memory_order_relaxed) };
+ for (;;) {
+ s = & slots_[idx & (capacity_ - 1)];
+ std::size_t cycle{ s->cycle.load( std::memory_order_acquire) };
+ std::intptr_t diff{ static_cast< std::intptr_t >( cycle) - static_cast< std::intptr_t >( idx) };
+ if ( 0 == diff) {
+ if ( producer_idx_.compare_exchange_weak( idx, idx + 1, std::memory_order_relaxed) ) {
+ break;
+ }
+ } else if ( 0 > diff) {
+ return channel_op_status::full;
+ } else {
+ idx = producer_idx_.load( std::memory_order_relaxed);
+ }
+ }
+ ::new ( static_cast< void * >( std::addressof( s->storage) ) ) value_type( std::forward< ValueType >( value) );
+ s->cycle.store( idx + 1, std::memory_order_release);
+ return channel_op_status::success;
+ }
+
+ channel_op_status try_value_pop_( slot *& s, std::size_t & idx) {
+ idx = consumer_idx_.load( std::memory_order_relaxed);
+ for (;;) {
+ s = & slots_[idx & (capacity_ - 1)];
+ std::size_t cycle = s->cycle.load( std::memory_order_acquire);
+ std::intptr_t diff{ static_cast< std::intptr_t >( cycle) - static_cast< std::intptr_t >( idx + 1) };
+ if ( 0 == diff) {
+ if ( consumer_idx_.compare_exchange_weak( idx, idx + 1, std::memory_order_relaxed) ) {
+ break;
+ }
+ } else if ( 0 > diff) {
+ return channel_op_status::empty;
+ } else {
+ idx = consumer_idx_.load( std::memory_order_relaxed);
+ }
+ }
+ // incrementing the slot cycle must be deferred till the value has been consumed
+ // slot cycle tells procuders that the cell can be re-used (store new value)
+ return channel_op_status::success;
+ }
+
+ channel_op_status try_pop_( value_type & value) {
+ slot * s{ nullptr };
+ std::size_t idx{ 0 };
+ channel_op_status status{ try_value_pop_( s, idx) };
+ if ( channel_op_status::success == status) {
+ value = std::move( * reinterpret_cast< value_type * >( std::addressof( s->storage) ) );
+ s->cycle.store( idx + capacity_, std::memory_order_release);
+ }
+ return status;
+ }
+
+public:
+ explicit buffered_channel( std::size_t capacity) :
+ capacity_{ capacity } {
+ if ( 0 == capacity_ || 0 != ( capacity_ & (capacity_ - 1) ) ) {
+ throw fiber_error( std::make_error_code( std::errc::invalid_argument),
+ "boost fiber: buffer capacity is invalid");
+ }
+ slots_ = new slot[capacity_]();
+ for ( std::size_t i = 0; i < capacity_; ++i) {
+ slots_[i].cycle.store( i, std::memory_order_relaxed);
+ }
+ }
+
+ ~buffered_channel() {
+ close();
+ for (;;) {
+ slot * s{ nullptr };
+ std::size_t idx{ 0 };
+ if ( channel_op_status::success == try_value_pop_( s, idx) ) {
+ reinterpret_cast< value_type * >( std::addressof( s->storage) )->~value_type();
+ s->cycle.store( idx + capacity_, std::memory_order_release);
+ } else {
+ break;
+ }
+ }
+ delete [] slots_;
+ }
+
+ buffered_channel( buffered_channel const&) = delete;
+ buffered_channel & operator=( buffered_channel const&) = delete;
+
+ bool is_closed() const noexcept {
+ return closed_.load( std::memory_order_acquire);
+ }
+
+ void close() noexcept {
+ context * ctx{ context::active() };
+ detail::spinlock_lock lk{ splk_ };
+ closed_.store( true, std::memory_order_release);
+ // notify all waiting producers
+ while ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ ctx->set_ready( producer_ctx);
+ }
+ // notify all waiting consumers
+ while ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ }
+
+ channel_op_status try_push( value_type const& value) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ return try_push_( value);
+ }
+
+ channel_op_status try_push( value_type && value) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ return try_push_( std::move( value) );
+ }
+
+ channel_op_status push( value_type const& value) {
+ context * ctx{ context::active() };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ channel_op_status status{ try_push_( value) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( consumer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::full == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_full_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ ctx->suspend( lk);
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ channel_op_status push( value_type && value) {
+ context * ctx{ context::active() };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ channel_op_status status{ try_push_( std::move( value) ) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( consumer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::full == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_full_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ ctx->suspend( lk);
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status push_wait_for( value_type const& value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return push_wait_until( value,
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status push_wait_for( value_type && value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return push_wait_until( std::forward< value_type >( value),
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status push_wait_until( value_type const& value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ channel_op_status status{ try_push_( value) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( consumer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::full == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_full_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status push_wait_until( value_type && value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ channel_op_status status{ try_push_( std::move( value) ) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( consumer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::full == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_full_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ channel_op_status try_pop( value_type & value) {
+ channel_op_status status{ try_pop_( value) };
+ if ( channel_op_status::success != status) {
+ if ( is_closed() ) {
+ status = channel_op_status::closed;
+ }
+ }
+ return status;
+ }
+
+ channel_op_status pop( value_type & value) {
+ context * ctx{ context::active() };
+ for (;;) {
+ channel_op_status status{ try_pop_( value) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( producer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::empty == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ ctx->suspend( lk);
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ value_type value_pop() {
+ context * ctx{ context::active() };
+ for (;;) {
+ slot * s{ nullptr };
+ std::size_t idx{ 0 };
+ channel_op_status status{ try_value_pop_( s, idx) };
+ if ( channel_op_status::success == status) {
+ value_type value{ std::move( * reinterpret_cast< value_type * >( std::addressof( s->storage) ) ) };
+ s->cycle.store( idx + capacity_, std::memory_order_release);
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( producer_ctx);
+ }
+ return std::move( value);
+ } else if ( channel_op_status::empty == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ throw fiber_error{
+ std::make_error_code( std::errc::operation_not_permitted),
+ "boost fiber: channel is closed" };
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ ctx->suspend( lk);
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ throw fiber_error{
+ std::make_error_code( std::errc::operation_not_permitted),
+ "boost fiber: channel is closed" };
+ }
+ }
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status pop_wait_for( value_type & value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return pop_wait_until( value,
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status pop_wait_until( value_type & value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ for (;;) {
+ channel_op_status status{ try_pop_( value) };
+ if ( channel_op_status::success == status) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ context::active()->set_ready( producer_ctx);
+ }
+ return status;
+ } else if ( channel_op_status::empty == status) {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ } else {
+ BOOST_ASSERT( channel_op_status::closed == status);
+ return status;
+ }
+ }
+ }
+
+ class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< value_type >::type > {
+ private:
+ typedef typename std::aligned_storage< sizeof( value_type), alignof( value_type) >::type storage_type;
+
+ buffered_channel * chan_{ nullptr };
+ storage_type storage_;
+
+ void increment_() {
+ BOOST_ASSERT( nullptr != chan_);
+ try {
+ ::new ( static_cast< void * >( std::addressof( storage_) ) ) value_type{ chan_->value_pop() };
+ } catch ( fiber_error const&) {
+ chan_ = nullptr;
+ }
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() noexcept = default;
+
+ explicit iterator( buffered_channel< T > * chan) noexcept :
+ chan_{ chan } {
+ increment_();
+ }
+
+ iterator( iterator const& other) noexcept :
+ chan_{ other.chan_ } {
+ }
+
+ iterator & operator=( iterator const& other) noexcept {
+ if ( this == & other) return * this;
+ chan_ = other.chan_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other) const noexcept {
+ return other.chan_ == chan_;
+ }
+
+ bool operator!=( iterator const& other) const noexcept {
+ return other.chan_ != chan_;
+ }
+
+ iterator & operator++() {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int) = delete;
+
+ reference_t operator*() noexcept {
+ return * reinterpret_cast< value_type * >( std::addressof( storage_) );
+ }
+
+ pointer_t operator->() noexcept {
+ return reinterpret_cast< value_type * >( std::addressof( storage_) );
+ }
+ };
+
+ friend class iterator;
+};
+
+template< typename T >
+typename buffered_channel< T >::iterator
+begin( buffered_channel< T > & chan) {
+ return typename buffered_channel< T >::iterator( & chan);
+}
+
+template< typename T >
+typename buffered_channel< T >::iterator
+end( buffered_channel< T > &) {
+ return typename buffered_channel< T >::iterator();
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_BUFFERED_CHANNEL_H
diff --git a/boost/fiber/channel_op_status.hpp b/boost/fiber/channel_op_status.hpp
index 78fd9bd6d0..785253ac43 100644
--- a/boost/fiber/channel_op_status.hpp
+++ b/boost/fiber/channel_op_status.hpp
@@ -3,8 +3,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_FIBERS_QUEUE_OP_STATUS_H
-#define BOOST_FIBERS_QUEUE_OP_STATUS_H
+#ifndef BOOST_FIBERS_CHANNEL_OP_STATUS_H
+#define BOOST_FIBERS_CHANNEL_OP_STATUS_H
#include <boost/config.hpp>
@@ -31,4 +31,4 @@ enum class channel_op_status {
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_FIBERS_QUEUE_OP_STATUS_H
+#endif // BOOST_FIBERS_CHANNEL_OP_STATUS_H
diff --git a/boost/fiber/condition_variable.hpp b/boost/fiber/condition_variable.hpp
index 03a91b03e7..0dca7ef6a0 100644
--- a/boost/fiber/condition_variable.hpp
+++ b/boost/fiber/condition_variable.hpp
@@ -30,7 +30,7 @@
#ifdef _MSC_VER
# pragma warning(push)
-# pragma warning(disable:4251)
+//# pragma warning(disable:4251)
#endif
namespace boost {
diff --git a/boost/fiber/context.hpp b/boost/fiber/context.hpp
index 40cef59d12..d873343538 100644
--- a/boost/fiber/context.hpp
+++ b/boost/fiber/context.hpp
@@ -157,13 +157,14 @@ private:
std::atomic< std::size_t > use_count_{ 0 };
std::atomic< unsigned int > flags_;
std::atomic< type > type_;
+ std::atomic< scheduler * > scheduler_{ nullptr };
#else
std::size_t use_count_{ 0 };
unsigned int flags_;
type type_;
+ scheduler * scheduler_{ nullptr };
#endif
launch policy_{ launch::post };
- scheduler * scheduler_{ nullptr };
#if (BOOST_EXECUTION_CONTEXT==1)
boost::context::execution_context ctx_;
#else
@@ -194,7 +195,7 @@ private:
#else
template< typename Fn, typename Tpl >
boost::context::execution_context< detail::data_t * >
- run_( boost::context::execution_context< detail::data_t * > ctx, Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept {
+ run_( boost::context::execution_context< detail::data_t * > && ctx, Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept {
{
// fn and tpl must be destroyed before calling set_terminated()
typename std::decay< Fn >::type fn = std::forward< Fn >( fn_);
@@ -219,6 +220,7 @@ public:
detail::terminated_hook terminated_hook_{};
detail::wait_hook wait_hook_{};
detail::worker_hook worker_hook_{};
+ std::atomic< context * > remote_nxt_{ nullptr };
std::chrono::steady_clock::time_point tp_{ (std::chrono::steady_clock::time_point::max)() };
typedef intrusive::list<
@@ -336,8 +338,8 @@ public:
ctx_{ std::allocator_arg, palloc, salloc,
detail::wrap(
[this]( typename std::decay< Fn >::type & fn, typename std::decay< Tpl >::type & tpl,
- boost::context::execution_context< detail::data_t * > ctx, detail::data_t * dp) mutable noexcept {
- return run_( std::move( ctx), std::move( fn), std::move( tpl), dp);
+ boost::context::execution_context< detail::data_t * > && ctx, detail::data_t * dp) mutable noexcept {
+ return run_( std::forward< boost::context::execution_context< detail::data_t * > >( ctx), std::move( fn), std::move( tpl), dp);
},
std::forward< Fn >( fn),
std::forward< Tpl >( tpl) )}
@@ -345,8 +347,8 @@ public:
# else
ctx_{ std::allocator_arg, palloc, salloc,
[this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl)]
- (boost::context::execution_context< detail::data_t * > ctx, detail::data_t * dp) mutable noexcept {
- return run_( std::move( ctx), std::move( fn), std::move( tpl), dp);
+ (boost::context::execution_context< detail::data_t * > && ctx, detail::data_t * dp) mutable noexcept {
+ return run_( std::forward< boost::context::execution_context< detail::data_t * > >( ctx), std::move( fn), std::move( tpl), dp);
}}
# endif
#endif
@@ -357,7 +359,13 @@ public:
virtual ~context();
- scheduler * get_scheduler() const noexcept;
+ scheduler * get_scheduler() const noexcept {
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ return scheduler_.load( std::memory_order_relaxed);
+#else
+ return scheduler_;
+#endif
+ }
id get_id() const noexcept;
diff --git a/boost/fiber/detail/config.hpp b/boost/fiber/detail/config.hpp
index 92a4c5fc3c..f65d48910d 100644
--- a/boost/fiber/detail/config.hpp
+++ b/boost/fiber/detail/config.hpp
@@ -7,7 +7,10 @@
#ifndef BOOST_FIBERS_DETAIL_CONFIG_H
#define BOOST_FIBERS_DETAIL_CONFIG_H
+#include <cstddef>
+
#include <boost/config.hpp>
+#include <boost/predef.h>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_FIBERS_DECL
@@ -35,4 +38,28 @@
# include <boost/config/auto_link.hpp>
#endif
+#if BOOST_OS_LINUX || BOOST_OS_WINDOWS
+# define BOOST_FIBERS_HAS_FUTEX
+#endif
+
+#if (!defined(BOOST_FIBERS_HAS_FUTEX) && \
+ (defined(BOOST_FIBERS_SPINLOCK_TTAS_FUTEX) || defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX)))
+# error "futex not supported on this platform"
+#endif
+
+#if !defined(BOOST_FIBERS_SPIN_MAX_COLLISIONS)
+# define BOOST_FIBERS_SPIN_MAX_COLLISIONS 16
+#endif
+
+#if !defined(BOOST_FIBERS_SPIN_MAX_TESTS)
+# define BOOST_FIBERS_SPIN_MAX_TESTS 100
+#endif
+
+// modern architectures have cachelines with 64byte length
+// ARM Cortex-A15 32/64byte, Cortex-A9 16/32/64bytes
+// MIPS 74K: 32byte, 4KEc: 16byte
+// ist shoudl be safe to use 64byte for all
+static constexpr std::size_t cache_alignment{ 64 };
+static constexpr std::size_t cacheline_length{ 64 };
+
#endif // BOOST_FIBERS_DETAIL_CONFIG_H
diff --git a/boost/fiber/detail/context_mpsc_queue.hpp b/boost/fiber/detail/context_mpsc_queue.hpp
new file mode 100644
index 0000000000..f7e664659c
--- /dev/null
+++ b/boost/fiber/detail/context_mpsc_queue.hpp
@@ -0,0 +1,98 @@
+
+// Copyright Dmitry Vyukov 2010-2011.
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// based on Dmitry Vyukov's intrusive MPSC queue
+// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
+// https://groups.google.com/forum/#!topic/lock-free/aFHvZhu1G-0
+
+#ifndef BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
+#define BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
+
+#include <atomic>
+#include <memory>
+#include <type_traits>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+// a MPSC queue
+// multiple threads push ready fibers (belonging to local scheduler)
+// (thread) local scheduler pops fibers
+class context_mpsc_queue {
+private:
+ // not default constructor for context - use aligned_storage instead
+ alignas(cache_alignment) std::aligned_storage< sizeof( context), alignof( context) >::type storage_{};
+ context * dummy_;
+ alignas(cache_alignment) std::atomic< context * > head_;
+ alignas(cache_alignment) context * tail_;
+ char pad_[cacheline_length];
+
+public:
+ context_mpsc_queue() :
+ dummy_{ reinterpret_cast< context * >( std::addressof( storage_) ) },
+ head_{ dummy_ },
+ tail_{ dummy_ } {
+ dummy_->remote_nxt_.store( nullptr, std::memory_order_release);
+ }
+
+ context_mpsc_queue( context_mpsc_queue const&) = delete;
+ context_mpsc_queue & operator=( context_mpsc_queue const&) = delete;
+
+ void push( context * ctx) noexcept {
+ BOOST_ASSERT( nullptr != ctx);
+ ctx->remote_nxt_.store( nullptr, std::memory_order_release);
+ context * prev = head_.exchange( ctx, std::memory_order_acq_rel);
+ prev->remote_nxt_.store( ctx, std::memory_order_release);
+ }
+
+ context * pop() noexcept {
+ context * tail = tail_;
+ context * next = tail->remote_nxt_.load( std::memory_order_acquire);
+ if ( dummy_ == tail) {
+ if ( nullptr == next) {
+ return nullptr;
+ }
+ tail_ = next;
+ tail = next;
+ next = next->remote_nxt_.load( std::memory_order_acquire);;
+ }
+ if ( nullptr != next) {
+ tail_ = next;
+ return tail;
+ }
+ context * head = head_.load( std::memory_order_acquire);
+ if ( tail != head) {
+ return nullptr;
+ }
+ push( dummy_);
+ next = tail->remote_nxt_.load( std::memory_order_acquire);
+ if ( nullptr != next) {
+ tail_= next;
+ return tail;
+ }
+ return nullptr;
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
diff --git a/boost/fiber/detail/context_spmc_queue.hpp b/boost/fiber/detail/context_spmc_queue.hpp
new file mode 100644
index 0000000000..6449e3658f
--- /dev/null
+++ b/boost/fiber/detail/context_spmc_queue.hpp
@@ -0,0 +1,158 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_DETAIL_CONTEXT_SPMC_QUEUE_H
+#define BOOST_FIBERS_DETAIL_CONTEXT_SPMC_QUEUE_H
+
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/context.hpp>
+
+// David Chase and Yossi Lev. Dynamic circular work-stealing deque.
+// In SPAA ’05: Proceedings of the seventeenth annual ACM symposium
+// on Parallelism in algorithms and architectures, pages 21–28,
+// New York, NY, USA, 2005. ACM.
+//
+// Nhat Minh Lê, Antoniu Pop, Albert Cohen, and Francesco Zappa Nardelli. 2013.
+// Correct and efficient work-stealing for weak memory models.
+// In Proceedings of the 18th ACM SIGPLAN symposium on Principles and practice
+// of parallel programming (PPoPP '13). ACM, New York, NY, USA, 69-80.
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class context_spmc_queue {
+private:
+ class array {
+ private:
+ typedef std::atomic< context * > atomic_type;
+ typedef std::aligned_storage<
+ sizeof( atomic_type), cache_alignment
+ >::type storage_type;
+
+ std::size_t size_;
+ storage_type * storage_;
+
+ public:
+ array( std::size_t size) :
+ size_{ size },
+ storage_{ new storage_type[size_] } {
+ for ( std::size_t i = 0; i < size_; ++i) {
+ ::new ( static_cast< void * >( std::addressof( storage_[i]) ) ) atomic_type{ nullptr };
+ }
+ }
+
+ ~array() {
+ for ( std::size_t i = 0; i < size_; ++i) {
+ reinterpret_cast< atomic_type * >( std::addressof( storage_[i]) )->~atomic_type();
+ }
+ delete [] storage_;
+ }
+
+ std::size_t size() const noexcept {
+ return size_;
+ }
+
+ void push( std::size_t bottom, context * ctx) noexcept {
+ reinterpret_cast< atomic_type * >(
+ std::addressof( storage_[bottom % size_]) )
+ ->store( ctx, std::memory_order_relaxed);
+ }
+
+ context * pop( std::size_t top) noexcept {
+ return reinterpret_cast< atomic_type * >(
+ std::addressof( storage_[top % size_]) )
+ ->load( std::memory_order_relaxed);
+ }
+
+ array * resize( std::size_t bottom, std::size_t top) {
+ std::unique_ptr< array > tmp{ new array{ 2 * size_ } };
+ for ( std::size_t i = top; i != bottom; ++i) {
+ tmp->push( i, pop( i) );
+ }
+ return tmp.release();
+ }
+ };
+
+ alignas(cache_alignment) std::atomic< std::size_t > top_{ 0 };
+ alignas(cache_alignment) std::atomic< std::size_t > bottom_{ 0 };
+ alignas(cache_alignment) std::atomic< array * > array_;
+ std::vector< array * > old_arrays_{};
+ char padding_[cacheline_length];
+
+public:
+ context_spmc_queue() :
+ array_{ new array{ 1024 } } {
+ old_arrays_.reserve( 32);
+ }
+
+ ~context_spmc_queue() {
+ for ( array * a : old_arrays_) {
+ delete a;
+ }
+ delete array_.load();
+ }
+
+ context_spmc_queue( context_spmc_queue const&) = delete;
+ context_spmc_queue & operator=( context_spmc_queue const&) = delete;
+
+ bool empty() const noexcept {
+ std::size_t bottom{ bottom_.load( std::memory_order_relaxed) };
+ std::size_t top{ top_.load( std::memory_order_relaxed) };
+ return bottom <= top;
+ }
+
+ void push( context * ctx) {
+ std::size_t bottom{ bottom_.load( std::memory_order_relaxed) };
+ std::size_t top{ top_.load( std::memory_order_acquire) };
+ array * a{ array_.load( std::memory_order_relaxed) };
+ if ( (a->size() - 1) < (bottom - top) ) {
+ // queue is full
+ // resize
+ array * tmp{ a->resize( bottom, top) };
+ old_arrays_.push_back( a);
+ std::swap( a, tmp);
+ array_.store( a, std::memory_order_relaxed);
+ }
+ a->push( bottom, ctx);
+ std::atomic_thread_fence( std::memory_order_release);
+ bottom_.store( bottom + 1, std::memory_order_relaxed);
+ }
+
+ context * pop() {
+ std::size_t top{ top_.load( std::memory_order_acquire) };
+ std::atomic_thread_fence( std::memory_order_seq_cst);
+ std::size_t bottom{ bottom_.load( std::memory_order_acquire) };
+ context * ctx{ nullptr };
+ if ( top < bottom) {
+ // queue is not empty
+ array * a{ array_.load( std::memory_order_consume) };
+ ctx = a->pop( top);
+ if ( ctx->is_context( type::pinned_context) ||
+ ! top_.compare_exchange_strong( top, top + 1,
+ std::memory_order_seq_cst,
+ std::memory_order_relaxed) ) {
+ // lose the race
+ return nullptr;
+ }
+ }
+ return ctx;
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_DETAIL_CONTEXT_SPMC_QUEUE_H
diff --git a/boost/fiber/detail/cpu_relax.hpp b/boost/fiber/detail/cpu_relax.hpp
new file mode 100644
index 0000000000..d00020a23b
--- /dev/null
+++ b/boost/fiber/detail/cpu_relax.hpp
@@ -0,0 +1,56 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_DETAIL_CPU_RELAX_H
+#define BOOST_FIBERS_DETAIL_CPU_RELAX_H
+
+#include <thread>
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#include <boost/fiber/detail/config.hpp>
+
+#if BOOST_COMP_MSVC
+# include <Windows.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+#if BOOST_ARCH_ARM
+# if BOOST_COMP_MSVC
+# define cpu_relax() YieldProcessor();
+# else
+# define cpu_relax() asm volatile ("yield" ::: "memory");
+# endif
+#elif BOOST_ARCH_MIPS
+# define cpu_relax() asm volatile ("pause" ::: "memory");
+#elif BOOST_ARCH_PPC
+# define cpu_relax() asm volatile ("or 27,27,27" ::: "memory");
+#elif BOOST_ARCH_X86
+# if BOOST_COMP_MSVC
+# define cpu_relax() YieldProcessor();
+# else
+# define cpu_relax() asm volatile ("pause" ::: "memory");
+# endif
+#else
+# warning "architecture does not support yield/pause mnemonic"
+# define cpu_relax() std::this_thread::yield();
+#endif
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_DETAIL_CPU_RELAX_H
diff --git a/boost/fiber/detail/data.hpp b/boost/fiber/detail/data.hpp
index a3e8a7e347..24e833a9e8 100644
--- a/boost/fiber/detail/data.hpp
+++ b/boost/fiber/detail/data.hpp
@@ -28,7 +28,7 @@ struct data_t {
spinlock_lock * lk{ nullptr };
context * ctx{ nullptr };
- constexpr data_t() noexcept = default;
+ data_t() noexcept = default;
explicit data_t( spinlock_lock * lk_) noexcept :
lk{ lk_ } {
diff --git a/boost/fiber/detail/futex.hpp b/boost/fiber/detail/futex.hpp
new file mode 100644
index 0000000000..4c966867c5
--- /dev/null
+++ b/boost/fiber/detail/futex.hpp
@@ -0,0 +1,61 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_DETAIL_FUTEX_H
+#define BOOST_FIBERS_DETAIL_FUTEX_H
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#include <boost/fiber/detail/config.hpp>
+
+#if BOOST_OS_LINUX
+extern "C" {
+#include <linux/futex.h>
+#include <sys/syscall.h>
+}
+#elif BOOST_OS_WINDOWS
+#include <Windows.h>
+#endif
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+#if BOOST_OS_LINUX
+inline
+int sys_futex( void * addr, std::int32_t op, std::int32_t x) {
+ return ::syscall( SYS_futex, addr, op, x, nullptr, nullptr, 0);
+}
+
+inline
+int futex_wake( std::atomic< std::int32_t > * addr) {
+ return 0 <= sys_futex( static_cast< void * >( addr), FUTEX_WAKE_PRIVATE, 1) ? 0 : -1;
+}
+
+inline
+int futex_wait( std::atomic< std::int32_t > * addr, std::int32_t x) {
+ return 0 <= sys_futex( static_cast< void * >( addr), FUTEX_WAIT_PRIVATE, x) ? 0 : -1;
+}
+#elif BOOST_OS_WINDOWS
+inline
+int futex_wake( std::atomic< std::int32_t > * addr) {
+ ::WakeByAddressSingle( static_cast< void * >( addr) );
+ return 0;
+}
+
+inline
+int futex_wait( std::atomic< std::int32_t > * addr, std::int32_t x) {
+ ::WaitOnAddress( static_cast< volatile void * >( addr), & x, sizeof( x), -1);
+ return 0;
+}
+#else
+# warn "no futex support on this platform"
+#endif
+
+}}}
+
+#endif // BOOST_FIBERS_DETAIL_FUTEX_H
diff --git a/boost/fiber/detail/spinlock.hpp b/boost/fiber/detail/spinlock.hpp
index e2af3a86c7..89a6d51a6f 100644
--- a/boost/fiber/detail/spinlock.hpp
+++ b/boost/fiber/detail/spinlock.hpp
@@ -3,40 +3,63 @@
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-//
-// based on boost::interprocess::sync::interprocess_spin::mutex
#ifndef BOOST_FIBERS_SPINLOCK_H
#define BOOST_FIBERS_SPINLOCK_H
-#include <mutex>
+#include <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
+#if !defined(BOOST_FIBERS_NO_ATOMICS)
+# include <mutex>
+# include <boost/fiber/detail/spinlock_ttas.hpp>
+# include <boost/fiber/detail/spinlock_ttas_adaptive.hpp>
+# if defined(BOOST_FIBERS_HAS_FUTEX)
+# include <boost/fiber/detail/spinlock_ttas_futex.hpp>
+# include <boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp>
+# endif
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
namespace boost {
namespace fibers {
namespace detail {
-struct non_spinlock {
- constexpr non_spinlock() noexcept {}
+#if defined(BOOST_FIBERS_NO_ATOMICS)
+struct spinlock {
+ constexpr spinlock() noexcept {}
void lock() noexcept {}
void unlock() noexcept {}
};
-struct non_lock {
- constexpr non_lock( non_spinlock) noexcept {}
+struct spinlock_lock {
+ constexpr spinlock_lock( spinlock &) noexcept {}
void lock() noexcept {}
void unlock() noexcept {}
};
-
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
-typedef std::mutex spinlock;
-using spinlock_lock = std::unique_lock< spinlock >;
#else
-typedef non_spinlock spinlock;
-using spinlock_lock = non_lock;
+# if defined(BOOST_FIBERS_SPINLOCK_STD_MUTEX)
+using spinlock = std::mutex;
+# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_FUTEX)
+using spinlock = spinlock_ttas_futex;
+# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX)
+using spinlock = spinlock_ttas_adaptive_futex;
+# elif defined(BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE)
+using spinlock = spinlock_ttas_adaptive;
+# else
+using spinlock = spinlock_ttas;
+# endif
+using spinlock_lock = std::unique_lock< spinlock >;
#endif
}}}
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
#endif // BOOST_FIBERS_SPINLOCK_H
diff --git a/boost/fiber/detail/spinlock_ttas.hpp b/boost/fiber/detail/spinlock_ttas.hpp
new file mode 100644
index 0000000000..d64630d84d
--- /dev/null
+++ b/boost/fiber/detail/spinlock_ttas.hpp
@@ -0,0 +1,112 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_SPINLOCK_TTAS_H
+#define BOOST_FIBERS_SPINLOCK_TTAS_H
+
+#include <atomic>
+#include <chrono>
+#include <random>
+#include <thread>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/cpu_relax.hpp>
+
+// based on informations from:
+// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
+// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class spinlock_ttas {
+private:
+ enum class spinlock_status {
+ locked = 0,
+ unlocked
+ };
+
+ // align shared variable 'state_' at cache line to prevent false sharing
+ alignas(cache_alignment) std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
+ // padding to avoid other data one the cacheline of shared variable 'state_'
+ char pad[cacheline_length];
+
+public:
+ spinlock_ttas() noexcept = default;
+
+ spinlock_ttas( spinlock_ttas const&) = delete;
+ spinlock_ttas & operator=( spinlock_ttas const&) = delete;
+
+ void lock() noexcept {
+ std::size_t collisions = 0 ;
+ for (;;) {
+ // avoid using multiple pause instructions for a delay of a specific cycle count
+ // the delay of cpu_relax() (pause on Intel) depends on the processor family
+ // the cycle count can not guaranteed from one system to the next
+ // -> check the shared variable 'state_' in between each cpu_relax() to prevent
+ // unnecessarily long delays on some systems
+ std::size_t tests = 0;
+ // test shared variable 'status_'
+ // first access to 'state_' -> chache miss
+ // sucessive acccess to 'state_' -> cache hit
+ // if 'state_' was released by other fiber
+ // cached 'state_' is invalidated -> cache miss
+ while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
+#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
+ if ( BOOST_FIBERS_SPIN_MAX_TESTS > tests) {
+ ++tests;
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ cpu_relax();
+ } else if ( BOOST_FIBERS_SPIN_MAX_TESTS + 20 > tests) {
+ ++tests;
+ // std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
+ // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
+ // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
+ // if and only if a thread of equal or greater priority is ready to run
+ static constexpr std::chrono::microseconds us0{ 0 };
+ std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+ }
+#else
+ std::this_thread::yield();
+#endif
+ }
+ // test-and-set shared variable 'status_'
+ // everytime 'status_' is signaled over the bus, even if the test failes
+ if ( spinlock_status::locked == state_.exchange( spinlock_status::locked, std::memory_order_acquire) ) {
+ // spinlock now contended
+ // utilize 'Binary Exponential Backoff' algorithm
+ // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
+ static thread_local std::minstd_rand generator;
+ const std::size_t z =
+ std::uniform_int_distribution< std::size_t >{ 0, static_cast< std::size_t >( 1) << collisions }( generator);
+ ++collisions;
+ for ( std::size_t i = 0; i < z; ++i) {
+ cpu_relax();
+ }
+ } else {
+ // success, thread has acquired the lock
+ break;
+ }
+ }
+ }
+
+ void unlock() noexcept {
+ state_.store( spinlock_status::unlocked, std::memory_order_release);
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPINLOCK_TTAS_H
diff --git a/boost/fiber/detail/spinlock_ttas_adaptive.hpp b/boost/fiber/detail/spinlock_ttas_adaptive.hpp
new file mode 100644
index 0000000000..c6a9a57d79
--- /dev/null
+++ b/boost/fiber/detail/spinlock_ttas_adaptive.hpp
@@ -0,0 +1,117 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_H
+#define BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_H
+
+#include <atomic>
+#include <chrono>
+#include <cmath>
+#include <random>
+#include <thread>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/cpu_relax.hpp>
+
+// based on informations from:
+// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
+// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class spinlock_ttas_adaptive {
+private:
+ enum class spinlock_status {
+ locked = 0,
+ unlocked
+ };
+
+ // align shared variable 'state_' at cache line to prevent false sharing
+ alignas(cache_alignment) std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
+ std::atomic< std::size_t > tests_{ 0 };
+ // padding to avoid other data one the cacheline of shared variable 'state_'
+ char pad[cacheline_length];
+
+public:
+ spinlock_ttas_adaptive() noexcept = default;
+
+ spinlock_ttas_adaptive( spinlock_ttas_adaptive const&) = delete;
+ spinlock_ttas_adaptive & operator=( spinlock_ttas_adaptive const&) = delete;
+
+ void lock() noexcept {
+ std::size_t collisions = 0 ;
+ for (;;) {
+ std::size_t tests = 0;
+ const std::size_t prev_tests = tests_.load( std::memory_order_relaxed);
+ const std::size_t max_tests = (std::min)( static_cast< std::size_t >( BOOST_FIBERS_SPIN_MAX_TESTS), 2 * prev_tests + 10);
+ // avoid using multiple pause instructions for a delay of a specific cycle count
+ // the delay of cpu_relax() (pause on Intel) depends on the processor family
+ // the cycle count can not guaranteed from one system to the next
+ // -> check the shared variable 'state_' in between each cpu_relax() to prevent
+ // unnecessarily long delays on some systems
+ // test shared variable 'status_'
+ // first access to 'state_' -> chache miss
+ // sucessive acccess to 'state_' -> cache hit
+ // if 'state_' was released by other fiber
+ // cached 'state_' is invalidated -> cache miss
+ while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
+#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
+ if ( max_tests > tests) {
+ ++tests;
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ cpu_relax();
+ } else if ( BOOST_FIBERS_SPIN_MAX_TESTS + 20 > tests) {
+ ++tests;
+ // std::this_thread::sleep_for( 0us) has a fairly long instruction path length,
+ // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles
+ // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice
+ // if and only if a thread of equal or greater priority is ready to run
+ static constexpr std::chrono::microseconds us0{ 0 };
+ std::this_thread::sleep_for( us0);
+ } else {
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+ }
+#else
+ std::this_thread::yield();
+#endif
+ }
+ // test-and-set shared variable 'status_'
+ // everytime 'status_' is signaled over the bus, even if the test failes
+ if ( spinlock_status::locked == state_.exchange( spinlock_status::locked, std::memory_order_acquire) ) {
+ // spinlock now contended
+ // utilize 'Binary Exponential Backoff' algorithm
+ // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
+ static thread_local std::minstd_rand generator;
+ const std::size_t z =
+ std::uniform_int_distribution< std::size_t >{ 0, static_cast< std::size_t >( 1) << collisions }( generator);
+ ++collisions;
+ for ( std::size_t i = 0; i < z; ++i) {
+ cpu_relax();
+ }
+ } else {
+ tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ // success, thread has acquired the lock
+ break;
+ }
+ }
+ }
+
+ void unlock() noexcept {
+ state_.store( spinlock_status::unlocked, std::memory_order_release);
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_H
diff --git a/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
new file mode 100644
index 0000000000..fbd6a0e4d2
--- /dev/null
+++ b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
@@ -0,0 +1,111 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX_H
+#define BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX_H
+
+#include <atomic>
+#include <cmath>
+#include <random>
+#include <thread>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/cpu_relax.hpp>
+#include <boost/fiber/detail/futex.hpp>
+
+// based on informations from:
+// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
+// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class spinlock_ttas_adaptive_futex {
+private:
+ // align shared variable 'value_' at cache line to prevent false sharing
+ alignas(cache_alignment) std::atomic< std::int32_t > value_{ 0 };
+ std::atomic< std::int32_t > tests_{ 0 };
+ // padding to avoid other data one the cacheline of shared variable 'value_'
+ char pad_[cacheline_length];
+
+public:
+ spinlock_ttas_adaptive_futex() noexcept = default;
+
+ spinlock_ttas_adaptive_futex( spinlock_ttas_adaptive_futex const&) = delete;
+ spinlock_ttas_adaptive_futex & operator=( spinlock_ttas_adaptive_futex const&) = delete;
+
+ void lock() noexcept {
+ std::int32_t collisions = 0, tests = 0, expected = 0;
+ const std::int32_t prev_tests = tests_.load( std::memory_order_relaxed);
+ const std::int32_t max_tests = (std::min)( static_cast< std::int32_t >( BOOST_FIBERS_SPIN_MAX_TESTS), 2 * prev_tests + 10);
+ // after max. spins or collisions suspend via futex
+ while ( max_tests > tests && BOOST_FIBERS_SPIN_MAX_COLLISIONS > collisions) {
+ // avoid using multiple pause instructions for a delay of a specific cycle count
+ // the delay of cpu_relax() (pause on Intel) depends on the processor family
+ // the cycle count can not guaranteed from one system to the next
+ // -> check the shared variable 'value_' in between each cpu_relax() to prevent
+ // unnecessarily long delays on some systems
+ // test shared variable 'status_'
+ // first access to 'value_' -> chache miss
+ // sucessive acccess to 'value_' -> cache hit
+ // if 'value_' was released by other fiber
+ // cached 'value_' is invalidated -> cache miss
+ if ( 0 != ( expected = value_.load( std::memory_order_relaxed) ) ) {
+ ++tests;
+#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ cpu_relax();
+#else
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+#endif
+ } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire, std::memory_order_release) ) {
+ // spinlock now contended
+ // utilize 'Binary Exponential Backoff' algorithm
+ // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
+ static thread_local std::minstd_rand generator;
+ const std::int32_t z = std::uniform_int_distribution< std::int32_t >{
+ 0, static_cast< std::int32_t >( 1) << collisions }( generator);
+ ++collisions;
+ for ( std::int32_t i = 0; i < z; ++i) {
+ cpu_relax();
+ }
+ } else {
+ // success, lock acquired
+ tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ return;
+ }
+ }
+ // failure, lock not acquired
+ // pause via futex
+ if ( 2 != expected) {
+ expected = value_.exchange( 2, std::memory_order_acquire);
+ }
+ while ( 0 != expected) {
+ futex_wait( & value_, 2);
+ expected = value_.exchange( 2, std::memory_order_acquire);
+ }
+ // success, lock acquired
+ tests_.store( prev_tests + (tests - prev_tests) / 8, std::memory_order_relaxed);
+ }
+
+ void unlock() noexcept {
+ if ( 1 != value_.fetch_sub( 1, std::memory_order_acquire) ) {
+ value_.store( 0, std::memory_order_release);
+ futex_wake( & value_);
+ }
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX_H
diff --git a/boost/fiber/detail/spinlock_ttas_futex.hpp b/boost/fiber/detail/spinlock_ttas_futex.hpp
new file mode 100644
index 0000000000..b11e63b587
--- /dev/null
+++ b/boost/fiber/detail/spinlock_ttas_futex.hpp
@@ -0,0 +1,104 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_spinlock_ttas_futex_FUTEX_H
+#define BOOST_FIBERS_spinlock_ttas_futex_FUTEX_H
+
+#include <atomic>
+#include <random>
+#include <thread>
+
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/cpu_relax.hpp>
+#include <boost/fiber/detail/futex.hpp>
+
+// based on informations from:
+// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
+// https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class spinlock_ttas_futex {
+private:
+ // align shared variable 'value_' at cache line to prevent false sharing
+ alignas(cache_alignment) std::atomic< std::int32_t > value_{ 0 };
+ // padding to avoid other data one the cacheline of shared variable 'value_'
+ char pad_[cacheline_length];
+
+public:
+ spinlock_ttas_futex() noexcept = default;
+
+ spinlock_ttas_futex( spinlock_ttas_futex const&) = delete;
+ spinlock_ttas_futex & operator=( spinlock_ttas_futex const&) = delete;
+
+ void lock() noexcept {
+ std::int32_t collisions = 0, tests = 0, expected = 0;
+ // after max. spins or collisions suspend via futex
+ while ( BOOST_FIBERS_SPIN_MAX_TESTS > tests && BOOST_FIBERS_SPIN_MAX_COLLISIONS > collisions) {
+ // avoid using multiple pause instructions for a delay of a specific cycle count
+ // the delay of cpu_relax() (pause on Intel) depends on the processor family
+ // the cycle count can not guaranteed from one system to the next
+ // -> check the shared variable 'value_' in between each cpu_relax() to prevent
+ // unnecessarily long delays on some systems
+ // test shared variable 'status_'
+ // first access to 'value_' -> chache miss
+ // sucessive acccess to 'value_' -> cache hit
+ // if 'value_' was released by other fiber
+ // cached 'value_' is invalidated -> cache miss
+ if ( 0 != ( expected = value_.load( std::memory_order_relaxed) ) ) {
+ ++tests;
+#if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
+ // give CPU a hint that this thread is in a "spin-wait" loop
+ // delays the next instruction's execution for a finite period of time (depends on processor family)
+ // the CPU is not under demand, parts of the pipeline are no longer being used
+ // -> reduces the power consumed by the CPU
+ cpu_relax();
+#else
+ // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
+ // but only to another thread on the same processor
+ // instead of constant checking, a thread only checks if no other useful work is pending
+ std::this_thread::yield();
+#endif
+ } else if ( ! value_.compare_exchange_strong( expected, 1, std::memory_order_acquire, std::memory_order_release) ) {
+ // spinlock now contended
+ // utilize 'Binary Exponential Backoff' algorithm
+ // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG)
+ static thread_local std::minstd_rand generator;
+ const std::int32_t z = std::uniform_int_distribution< std::int32_t >{
+ 0, static_cast< std::int32_t >( 1) << collisions }( generator);
+ ++collisions;
+ for ( std::int32_t i = 0; i < z; ++i) {
+ cpu_relax();
+ }
+ } else {
+ // success, lock acquired
+ return;
+ }
+ }
+ // failure, lock not acquired
+ // pause via futex
+ if ( 2 != expected) {
+ expected = value_.exchange( 2, std::memory_order_acquire);
+ }
+ while ( 0 != expected) {
+ futex_wait( & value_, 2);
+ expected = value_.exchange( 2, std::memory_order_acquire);
+ }
+ }
+
+ void unlock() noexcept {
+ if ( 1 != value_.fetch_sub( 1, std::memory_order_acquire) ) {
+ value_.store( 0, std::memory_order_release);
+ futex_wake( & value_);
+ }
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_spinlock_ttas_futex_FUTEX_H
diff --git a/boost/fiber/detail/wrap.hpp b/boost/fiber/detail/wrap.hpp
index 850763b4c8..0369e61ee6 100644
--- a/boost/fiber/detail/wrap.hpp
+++ b/boost/fiber/detail/wrap.hpp
@@ -87,10 +87,13 @@ public:
wrapper & operator=( wrapper && other) = default;
boost::context::execution_context< data_t * >
- operator()( boost::context::execution_context< data_t * > ctx, data_t * dp) {
+ operator()( boost::context::execution_context< data_t * > && ctx, data_t * dp) {
return boost::context::detail::invoke(
std::move( fn1_),
- fn2_, tpl_, std::move( ctx), dp);
+ fn2_,
+ tpl_,
+ std::forward< boost::context::execution_context< data_t * > >( ctx),
+ dp);
}
};
diff --git a/boost/fiber/fiber.hpp b/boost/fiber/fiber.hpp
index db161d3772..0fbc84ad12 100644
--- a/boost/fiber/fiber.hpp
+++ b/boost/fiber/fiber.hpp
@@ -49,7 +49,7 @@ private:
public:
typedef context::id id;
- constexpr fiber() noexcept = default;
+ fiber() noexcept = default;
template< typename Fn,
typename ... Args,
diff --git a/boost/fiber/future/async.hpp b/boost/fiber/future/async.hpp
index f3adbc60b4..d969d19ce3 100644
--- a/boost/fiber/future/async.hpp
+++ b/boost/fiber/future/async.hpp
@@ -80,7 +80,8 @@ async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Arg
packaged_task< result_t( typename std::decay< Args >::type ... ) > pt{
std::allocator_arg, salloc, std::forward< Fn >( fn) };
future< result_t > f{ pt.get_future() };
- fiber{ policy, std::move( pt), std::forward< Args >( args) ... }.detach();
+ fiber{ policy, std::allocator_arg, salloc,
+ std::move( pt), std::forward< Args >( args) ... }.detach();
return f;
}
diff --git a/boost/fiber/future/detail/shared_state.hpp b/boost/fiber/future/detail/shared_state.hpp
index 9c1b347fbf..5ec6858cf3 100644
--- a/boost/fiber/future/detail/shared_state.hpp
+++ b/boost/fiber/future/detail/shared_state.hpp
@@ -192,7 +192,7 @@ public:
virtual ~shared_state() {
if ( ready_ && ! except_) {
- reinterpret_cast< R * >( & storage_)->~R();
+ reinterpret_cast< R * >( std::addressof( storage_) )->~R();
}
}
diff --git a/boost/fiber/future/future.hpp b/boost/fiber/future/future.hpp
index 9d91f3a1b7..d92820eb58 100644
--- a/boost/fiber/future/future.hpp
+++ b/boost/fiber/future/future.hpp
@@ -28,7 +28,7 @@ struct future_base {
ptr_t state_{};
- constexpr future_base() noexcept = default;
+ future_base() noexcept = default;
explicit future_base( ptr_t const& p) noexcept :
state_{ p } {
@@ -119,7 +119,7 @@ private:
}
public:
- constexpr future() noexcept = default;
+ future() noexcept = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
@@ -167,7 +167,7 @@ private:
}
public:
- constexpr future() noexcept = default;
+ future() noexcept = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
@@ -215,7 +215,7 @@ private:
}
public:
- constexpr future() noexcept = default;
+ future() noexcept = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
@@ -262,7 +262,7 @@ private:
}
public:
- constexpr shared_future() noexcept = default;
+ shared_future() noexcept = default;
~shared_future() = default;
@@ -319,7 +319,7 @@ private:
}
public:
- constexpr shared_future() noexcept = default;
+ shared_future() noexcept = default;
~shared_future() = default;
@@ -376,7 +376,7 @@ private:
}
public:
- constexpr shared_future() noexcept = default;
+ shared_future() noexcept = default;
~shared_future() = default;
diff --git a/boost/fiber/scheduler.hpp b/boost/fiber/scheduler.hpp
index 0b61f01d85..4503bc0b5f 100644
--- a/boost/fiber/scheduler.hpp
+++ b/boost/fiber/scheduler.hpp
@@ -21,6 +21,7 @@
#include <boost/fiber/algo/algorithm.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/context_mpsc_queue.hpp>
#include <boost/fiber/detail/data.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -50,8 +51,7 @@ public:
context, detail::ready_hook, & context::ready_hook_ >,
intrusive::constant_time_size< false > > ready_queue_t;
private:
- typedef std::vector< context * > remote_ready_queue_t;
- typedef intrusive::set<
+ typedef intrusive::multiset<
context,
intrusive::member_hook<
context, detail::sleep_hook, & context::sleep_hook_ >,
@@ -77,20 +77,23 @@ private:
worker_queue_t worker_queue_{};
// terminated-queue contains context' which have been terminated
terminated_queue_t terminated_queue_{};
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
// remote ready-queue contains context' signaled by schedulers
// running in other threads
- remote_ready_queue_t remote_ready_queue_{};
- // sleep-queue cotnains context' whic hahve been called
+ detail::context_mpsc_queue remote_ready_queue_{};
+ // sleep-queue contains context' which have been called
+#endif
// scheduler::wait_until()
sleep_queue_t sleep_queue_{};
bool shutdown_{ false };
- std::mutex remote_ready_mtx_{};
context * get_next_() noexcept;
void release_terminated_() noexcept;
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
void remote_ready2ready_() noexcept;
+#endif
void sleep2ready_() noexcept;
@@ -104,7 +107,9 @@ public:
void set_ready( context *) noexcept;
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
void set_remote_ready( context *) noexcept;
+#endif
#if (BOOST_EXECUTION_CONTEXT==1)
void dispatch() noexcept;
diff --git a/boost/fiber/unbounded_channel.hpp b/boost/fiber/unbounded_channel.hpp
index 58c966080f..6de5a6f5f0 100644
--- a/boost/fiber/unbounded_channel.hpp
+++ b/boost/fiber/unbounded_channel.hpp
@@ -8,6 +8,8 @@
#ifndef BOOST_FIBERS_UNBOUNDED_CHANNEL_H
#define BOOST_FIBERS_UNBOUNDED_CHANNEL_H
+#warn "template unbounded_channel is deprecated"
+
#include <atomic>
#include <algorithm>
#include <chrono>
diff --git a/boost/fiber/unbuffered_channel.hpp b/boost/fiber/unbuffered_channel.hpp
new file mode 100644
index 0000000000..582d9ae5a7
--- /dev/null
+++ b/boost/fiber/unbuffered_channel.hpp
@@ -0,0 +1,540 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIBERS_UNBUFFERED_CHANNEL_H
+#define BOOST_FIBERS_UNBUFFERED_CHANNEL_H
+
+#include <atomic>
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/channel_op_status.hpp>
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/convert.hpp>
+#include <boost/fiber/detail/spinlock.hpp>
+#include <boost/fiber/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+
+template< typename T >
+class unbuffered_channel {
+public:
+ typedef T value_type;
+
+private:
+ typedef context::wait_queue_t wait_queue_type;
+
+ struct alignas(cache_alignment) slot {
+ value_type value;
+ context * ctx;
+
+ slot( value_type const& value_, context * ctx_) :
+ value{ value_ },
+ ctx{ ctx_ } {
+ }
+
+ slot( value_type && value_, context * ctx_) :
+ value{ std::move( value_) },
+ ctx{ ctx_ } {
+ }
+ };
+
+ // shared cacheline
+ alignas(cache_alignment) std::atomic< slot * > slot_{ nullptr };
+ // shared cacheline
+ alignas(cache_alignment) std::atomic_bool closed_{ false };
+ mutable detail::spinlock splk_{};
+ wait_queue_type waiting_producers_{};
+ wait_queue_type waiting_consumers_{};
+ char pad_[cacheline_length];
+
+ bool is_empty_() {
+ return nullptr == slot_.load( std::memory_order_acquire);
+ }
+
+ bool try_push_( slot * own_slot) {
+ for (;;) {
+ slot * s{ slot_.load( std::memory_order_acquire) };
+ if ( nullptr == s) {
+ if ( ! slot_.compare_exchange_strong( s, own_slot, std::memory_order_acq_rel) ) {
+ continue;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ slot * try_pop_() {
+ slot * nil_slot{ nullptr };
+ for (;;) {
+ slot * s{ slot_.load( std::memory_order_acquire) };
+ if ( nullptr != s) {
+ if ( ! slot_.compare_exchange_strong( s, nil_slot, std::memory_order_acq_rel) ) {
+ continue;}
+ }
+ return s;
+ }
+ }
+
+public:
+ unbuffered_channel() = default;
+
+ ~unbuffered_channel() {
+ close();
+ slot * s{ nullptr };
+ if ( nullptr != ( s = try_pop_() ) ) {
+ BOOST_ASSERT( nullptr != s);
+ BOOST_ASSERT( nullptr != s->ctx);
+ // value will be destructed in the context of the waiting fiber
+ context::active()->set_ready( s->ctx);
+ }
+ }
+
+ unbuffered_channel( unbuffered_channel const&) = delete;
+ unbuffered_channel & operator=( unbuffered_channel const&) = delete;
+
+ bool is_closed() const noexcept {
+ return closed_.load( std::memory_order_acquire);
+ }
+
+ void close() noexcept {
+ context * ctx{ context::active() };
+ detail::spinlock_lock lk{ splk_ };
+ closed_.store( true, std::memory_order_release);
+ // notify all waiting producers
+ while ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ ctx->set_ready( producer_ctx);
+ }
+ // notify all waiting consumers
+ while ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ }
+
+ channel_op_status push( value_type const& value) {
+ context * ctx{ context::active() };
+ slot s{ value, ctx };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( try_push_( & s) ) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ // suspend till value has been consumed
+ ctx->suspend( lk);
+ // resumed, value has been consumed
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ ctx->suspend( lk);
+ // resumed, slot mabye free
+ }
+ }
+ }
+
+ channel_op_status push( value_type && value) {
+ context * ctx{ context::active() };
+ slot s{ std::move( value), ctx };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( try_push_( & s) ) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ // suspend till value has been consumed
+ ctx->suspend( lk);
+ // resumed, value has been consumed
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ ctx->suspend( lk);
+ // resumed, slot mabye free
+ }
+ }
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status push_wait_for( value_type const& value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return push_wait_until( value,
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status push_wait_for( value_type && value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return push_wait_until( std::forward< value_type >( value),
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status push_wait_until( value_type const& value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ slot s{ value, ctx };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( try_push_( & s) ) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // clear slot
+ slot * nil_slot{ nullptr }, * own_slot{ & s };
+ slot_.compare_exchange_strong( own_slot, nil_slot, std::memory_order_acq_rel);
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ // resumed, value has not been consumed
+ return channel_op_status::timeout;
+ }
+ // resumed, value has been consumed
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ // resumed, slot maybe free
+ }
+ }
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status push_wait_until( value_type && value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ slot s{ std::move( value), ctx };
+ for (;;) {
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( try_push_( & s) ) {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx{ & waiting_consumers_.front() };
+ waiting_consumers_.pop_front();
+ ctx->set_ready( consumer_ctx);
+ }
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // clear slot
+ slot * nil_slot{ nullptr }, * own_slot{ & s };
+ slot_.compare_exchange_strong( own_slot, nil_slot, std::memory_order_acq_rel);
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ // resumed, value has not been consumed
+ return channel_op_status::timeout;
+ }
+ // resumed, value has been consumed
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ // resumed, slot maybe free
+ }
+ }
+ }
+
+ channel_op_status pop( value_type & value) {
+ context * ctx{ context::active() };
+ slot * s{ nullptr };
+ for (;;) {
+ if ( nullptr != ( s = try_pop_() ) ) {
+ {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( producer_ctx);
+ }
+ }
+ // consume value
+ value = std::move( s->value);
+ // resume suspended producer
+ ctx->set_ready( s->ctx);
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ ctx->suspend( lk);
+ // resumed, slot mabye set
+ }
+ }
+ }
+
+ value_type value_pop() {
+ context * ctx{ context::active() };
+ slot * s{ nullptr };
+ for (;;) {
+ if ( nullptr != ( s = try_pop_() ) ) {
+ {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( producer_ctx);
+ }
+ }
+ // consume value
+ value_type value{ std::move( s->value) };
+ // resume suspended producer
+ ctx->set_ready( s->ctx);
+ return std::move( value);
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ throw fiber_error{
+ std::make_error_code( std::errc::operation_not_permitted),
+ "boost fiber: channel is closed" };
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ ctx->suspend( lk);
+ // resumed, slot mabye set
+ }
+ }
+ }
+
+ template< typename Rep, typename Period >
+ channel_op_status pop_wait_for( value_type & value,
+ std::chrono::duration< Rep, Period > const& timeout_duration) {
+ return pop_wait_until( value,
+ std::chrono::steady_clock::now() + timeout_duration);
+ }
+
+ template< typename Clock, typename Duration >
+ channel_op_status pop_wait_until( value_type & value,
+ std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
+ context * ctx{ context::active() };
+ slot * s{ nullptr };
+ for (;;) {
+ if ( nullptr != ( s = try_pop_() ) ) {
+ {
+ detail::spinlock_lock lk{ splk_ };
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx{ & waiting_producers_.front() };
+ waiting_producers_.pop_front();
+ lk.unlock();
+ ctx->set_ready( producer_ctx);
+ }
+ }
+ // consume value
+ value = std::move( s->value);
+ // resume suspended producer
+ ctx->set_ready( s->ctx);
+ return channel_op_status::success;
+ } else {
+ BOOST_ASSERT( ! ctx->wait_is_linked() );
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed() ) {
+ return channel_op_status::closed;
+ }
+ if ( ! is_empty_() ) {
+ continue;
+ }
+ ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ if ( ! ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ ctx->wait_unlink();
+ return channel_op_status::timeout;
+ }
+ }
+ }
+ }
+
+ class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< value_type >::type > {
+ private:
+ typedef typename std::aligned_storage< sizeof( value_type), alignof( value_type) >::type storage_type;
+
+ unbuffered_channel * chan_{ nullptr };
+ storage_type storage_;
+
+ void increment_() {
+ BOOST_ASSERT( nullptr != chan_);
+ try {
+ ::new ( static_cast< void * >( std::addressof( storage_) ) ) value_type{ chan_->value_pop() };
+ } catch ( fiber_error const&) {
+ chan_ = nullptr;
+ }
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() noexcept = default;
+
+ explicit iterator( unbuffered_channel< T > * chan) noexcept :
+ chan_{ chan } {
+ increment_();
+ }
+
+ iterator( iterator const& other) noexcept :
+ chan_{ other.chan_ } {
+ }
+
+ iterator & operator=( iterator const& other) noexcept {
+ if ( this == & other) return * this;
+ chan_ = other.chan_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other) const noexcept {
+ return other.chan_ == chan_;
+ }
+
+ bool operator!=( iterator const& other) const noexcept {
+ return other.chan_ != chan_;
+ }
+
+ iterator & operator++() {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int) = delete;
+
+ reference_t operator*() noexcept {
+ return * reinterpret_cast< value_type * >( std::addressof( storage_) );
+ }
+
+ pointer_t operator->() noexcept {
+ return reinterpret_cast< value_type * >( std::addressof( storage_) );
+ }
+ };
+
+ friend class iterator;
+};
+
+template< typename T >
+typename unbuffered_channel< T >::iterator
+begin( unbuffered_channel< T > & chan) {
+ return typename unbuffered_channel< T >::iterator( & chan);
+}
+
+template< typename T >
+typename unbuffered_channel< T >::iterator
+end( unbuffered_channel< T > &) {
+ return typename unbuffered_channel< T >::iterator();
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_UNBUFFERED_CHANNEL_H
diff --git a/boost/filesystem/operations.hpp b/boost/filesystem/operations.hpp
index 47bc07476b..b0ea42a308 100644
--- a/boost/filesystem/operations.hpp
+++ b/boost/filesystem/operations.hpp
@@ -921,8 +921,8 @@ namespace detail
friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it,
system::error_code* ec);
- // shared_ptr provides shallow-copy semantics required for InputIterators.
- // m_imp.get()==0 indicates the end iterator.
+ // shared_ptr provides the shallow-copy semantics required for single pass iterators
+ // (i.e. InputIterators). The end iterator is indicated by !m_imp || !m_imp->handle
boost::shared_ptr< detail::dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
@@ -939,7 +939,11 @@ namespace detail
void increment() { detail::directory_iterator_increment(*this, 0); }
bool equal(const directory_iterator& rhs) const
- { return m_imp == rhs.m_imp; }
+ {
+ return m_imp == rhs.m_imp
+ || (!m_imp && rhs.m_imp && !rhs.m_imp->handle)
+ || (!rhs.m_imp && m_imp && !m_imp->handle);
+ }
}; // directory_iterator
@@ -1029,41 +1033,43 @@ namespace filesystem
// taking symlinks and options into account.
if ((m_options & symlink_option::_detail_no_push) == symlink_option::_detail_no_push)
+ {
m_options &= ~symlink_option::_detail_no_push;
+ return false;
+ }
- else
+ file_status symlink_stat;
+
+ // if we are not recursing into symlinks, we are going to have to know if the
+ // stack top is a symlink, so get symlink_status and verify no error occurred
+ if ((m_options & symlink_option::recurse) != symlink_option::recurse)
{
- // Logic for following predicate was contributed by Daniel Aarno to handle cyclic
- // symlinks correctly and efficiently, fixing ticket #5652.
- // if (((m_options & symlink_option::recurse) == symlink_option::recurse
- // || !is_symlink(m_stack.top()->symlink_status()))
- // && is_directory(m_stack.top()->status())) ...
- // The predicate code has since been rewritten to pass error_code arguments,
- // per ticket #5653.
+ symlink_stat = m_stack.top()->symlink_status(ec);
+ if (ec)
+ return false;
+ }
- file_status symlink_stat;
+ // Logic for following predicate was contributed by Daniel Aarno to handle cyclic
+ // symlinks correctly and efficiently, fixing ticket #5652.
+ // if (((m_options & symlink_option::recurse) == symlink_option::recurse
+ // || !is_symlink(m_stack.top()->symlink_status()))
+ // && is_directory(m_stack.top()->status())) ...
+ // The predicate code has since been rewritten to pass error_code arguments,
+ // per ticket #5653.
- if ((m_options & symlink_option::recurse) != symlink_option::recurse)
- {
- symlink_stat = m_stack.top()->symlink_status(ec);
- if (ec)
- return false;
- }
+ if ((m_options & symlink_option::recurse) == symlink_option::recurse
+ || !is_symlink(symlink_stat))
+ {
+ file_status stat = m_stack.top()->status(ec);
+ if (ec || !is_directory(stat))
+ return false;
- if ((m_options & symlink_option::recurse) == symlink_option::recurse
- || !is_symlink(symlink_stat))
+ directory_iterator next(m_stack.top()->path(), ec);
+ if (!ec && next != directory_iterator())
{
- file_status stat = m_stack.top()->status(ec);
- if (ec || !is_directory(stat))
- return false;
-
- directory_iterator next(m_stack.top()->path(), ec);
- if (!ec && next != directory_iterator())
- {
- m_stack.push(next);
- ++m_level;
- return true;
- }
+ m_stack.push(next);
+ ++m_level;
+ return true;
}
}
return false;
@@ -1254,8 +1260,9 @@ namespace filesystem
private:
- // shared_ptr provides shallow-copy semantics required for InputIterators.
- // m_imp.get()==0 indicates the end iterator.
+ // shared_ptr provides the shallow-copy semantics required for single pass iterators
+ // (i.e. InputIterators).
+ // The end iterator is indicated by !m_imp || m_imp->m_stack.empty()
boost::shared_ptr< detail::recur_dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
@@ -1281,7 +1288,11 @@ namespace filesystem
}
bool equal(const recursive_directory_iterator& rhs) const
- { return m_imp == rhs.m_imp; }
+ {
+ return m_imp == rhs.m_imp
+ || (!m_imp && rhs.m_imp && rhs.m_imp->m_stack.empty())
+ || (!rhs.m_imp && m_imp && m_imp->m_stack.empty()) ;
+ }
}; // recursive directory iterator
diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp
index af5bfcc8c2..65e27b17da 100644
--- a/boost/filesystem/path.hpp
+++ b/boost/filesystem/path.hpp
@@ -62,10 +62,14 @@ namespace filesystem
# ifdef BOOST_WINDOWS_API
typedef wchar_t value_type;
+ BOOST_STATIC_CONSTEXPR value_type separator = L'/';
BOOST_STATIC_CONSTEXPR value_type preferred_separator = L'\\';
+ BOOST_STATIC_CONSTEXPR value_type dot = L'.';
# else
typedef char value_type;
+ BOOST_STATIC_CONSTEXPR value_type separator = '/';
BOOST_STATIC_CONSTEXPR value_type preferred_separator = '/';
+ BOOST_STATIC_CONSTEXPR value_type dot = '.';
# endif
typedef std::basic_string<value_type> string_type;
typedef std::codecvt<wchar_t, char,
@@ -455,7 +459,7 @@ namespace filesystem
// Experimental generic function returning generic formatted path (i.e. separators
// are forward slashes). Motivation: simpler than a family of generic_*string
// functions.
- path generic() const
+ path generic_path() const
{
# ifdef BOOST_WINDOWS_API
path tmp;
@@ -509,6 +513,8 @@ namespace filesystem
// ----- query -----
bool empty() const BOOST_NOEXCEPT{ return m_pathname.empty(); }
+ bool filename_is_dot() const;
+ bool filename_is_dot_dot() const;
bool has_root_path() const { return has_root_directory() || has_root_name(); }
bool has_root_name() const { return !root_name().empty(); }
bool has_root_directory() const { return !root_directory().empty(); }
@@ -570,6 +576,7 @@ namespace filesystem
path& remove_leaf() { return remove_filename(); }
path leaf() const { return filename(); }
path branch_path() const { return parent_path(); }
+ path generic() const { return generic_path(); }
bool has_leaf() const { return !m_pathname.empty(); }
bool has_branch_path() const { return !parent_path().empty(); }
bool is_complete() const { return is_absolute(); }
@@ -737,10 +744,6 @@ namespace filesystem
}; // path::reverse_iterator
- inline path::reverse_iterator path::rbegin() const { return reverse_iterator(end()); }
- inline path::reverse_iterator path::rend() const { return reverse_iterator(begin()); }
-
-
//------------------------------------------------------------------------------------//
// //
// non-member functions //
@@ -809,7 +812,7 @@ namespace filesystem
p = str;
return is;
}
-
+
// name_checks
// These functions are holdovers from version 1. It isn't clear they have much
@@ -821,6 +824,54 @@ namespace filesystem
BOOST_FILESYSTEM_DECL bool portable_directory_name(const std::string & name);
BOOST_FILESYSTEM_DECL bool portable_file_name(const std::string & name);
BOOST_FILESYSTEM_DECL bool native(const std::string & name);
+
+ namespace detail
+ {
+ // For POSIX, is_directory_separator() and is_element_separator() are identical since
+ // a forward slash is the only valid directory separator and also the only valid
+ // element separator. For Windows, forward slash and back slash are the possible
+ // directory separators, but colon (example: "c:foo") is also an element separator.
+
+ inline bool is_directory_separator(path::value_type c) BOOST_NOEXCEPT
+ {
+ return c == path::separator
+# ifdef BOOST_WINDOWS_API
+ || c == path::preferred_separator
+# endif
+ ;
+ }
+ inline bool is_element_separator(path::value_type c) BOOST_NOEXCEPT
+ {
+ return c == path::separator
+# ifdef BOOST_WINDOWS_API
+ || c == path::preferred_separator || c == L':'
+# endif
+ ;
+ }
+ } // namespace detail
+
+ //------------------------------------------------------------------------------------//
+ // class path miscellaneous function implementations //
+ //------------------------------------------------------------------------------------//
+
+ inline path::reverse_iterator path::rbegin() const { return reverse_iterator(end()); }
+ inline path::reverse_iterator path::rend() const { return reverse_iterator(begin()); }
+
+ inline bool path::filename_is_dot() const
+ {
+ // implicit dot is tricky, so actually call filename(); see path::filename() example
+ // in reference.html
+ path p(filename());
+ return p.size() == 1 && *p.c_str() == dot;
+ }
+
+ inline bool path::filename_is_dot_dot() const
+ {
+ return size() >= 2 && m_pathname[size()-1] == dot && m_pathname[size()-2] == dot
+ && (m_pathname.size() == 2 || detail::is_element_separator(m_pathname[size()-3]));
+ // use detail::is_element_separator() rather than detail::is_directory_separator
+ // to deal with "c:.." edge case on Windows when ':' acts as a separator
+ }
//--------------------------------------------------------------------------------------//
// class path member template implementation //
diff --git a/boost/format/alt_sstream_impl.hpp b/boost/format/alt_sstream_impl.hpp
index 9975e4f96b..998f8b2e55 100644
--- a/boost/format/alt_sstream_impl.hpp
+++ b/boost/format/alt_sstream_impl.hpp
@@ -145,7 +145,7 @@ namespace boost {
typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
basic_altstringbuf<Ch, Tr, Alloc>::
seekpos (pos_type pos, ::std::ios_base::openmode which) {
- off_type off = off_type(pos); // operation guaranteed by 27.4.3.2 table 88
+ off_type off = off_type(pos); // operation guaranteed by fpos.operations table 127
if(pptr() != NULL && putend_ < pptr())
putend_ = pptr();
if(off != off_type(-1)) {
@@ -173,7 +173,7 @@ namespace boost {
return (pos_type(off));
}
else {
- BOOST_ASSERT(0); // 27.4.3.2 allows undefined-behaviour here
+ BOOST_ASSERT(0); // fpos.operations allows undefined-behaviour here
return pos_type(off_type(-1));
}
}
diff --git a/boost/functional/hash/detail/hash_float.hpp b/boost/functional/hash/detail/hash_float.hpp
index eb9264f737..9fb8168459 100644
--- a/boost/functional/hash/detail/hash_float.hpp
+++ b/boost/functional/hash/detail/hash_float.hpp
@@ -179,7 +179,7 @@ namespace boost
hash_float_combine(seed, part);
}
- hash_float_combine(seed, exp);
+ hash_float_combine(seed, static_cast<std::size_t>(exp));
return seed;
}
diff --git a/boost/functional/hash/hash.hpp b/boost/functional/hash/hash.hpp
index 0a8ceeb474..5bba40892d 100644
--- a/boost/functional/hash/hash.hpp
+++ b/boost/functional/hash/hash.hpp
@@ -168,10 +168,10 @@ namespace boost
template <class T>
inline std::size_t hash_value_signed(T val)
{
- const int size_t_bits = std::numeric_limits<std::size_t>::digits;
+ const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
const int length = (std::numeric_limits<T>::digits - 1)
- / size_t_bits;
+ / static_cast<int>(size_t_bits);
std::size_t seed = 0;
T positive = val < 0 ? -1 - val : val;
@@ -189,10 +189,10 @@ namespace boost
template <class T>
inline std::size_t hash_value_unsigned(T val)
{
- const int size_t_bits = std::numeric_limits<std::size_t>::digits;
+ const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
// ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
const int length = (std::numeric_limits<T>::digits - 1)
- / size_t_bits;
+ / static_cast<int>(size_t_bits);
std::size_t seed = 0;
@@ -236,7 +236,7 @@ namespace boost
inline void hash_combine_impl(boost::uint64_t& h,
boost::uint64_t k)
{
- const uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
+ const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
const int r = 47;
k *= m;
@@ -456,7 +456,7 @@ namespace boost
BOOST_HASH_SPECIALIZE(long double)
BOOST_HASH_SPECIALIZE_REF(std::string)
-#if !defined(BOOST_NO_STD_WSTRING)
+#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_HASH_SPECIALIZE_REF(std::wstring)
#endif
diff --git a/boost/fusion/adapted/std_array.hpp b/boost/fusion/adapted/std_array.hpp
new file mode 100644
index 0000000000..64ae6460c7
--- /dev/null
+++ b/boost/fusion/adapted/std_array.hpp
@@ -0,0 +1,23 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY__01062013_1700)
+#define BOOST_FUSION_STD_ARRAY__01062013_1700
+
+#include <boost/fusion/adapted/std_array/std_array_iterator.hpp>
+#include <boost/fusion/adapted/std_array/tag_of.hpp>
+#include <boost/fusion/adapted/std_array/detail/is_view_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/category_of_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/begin_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/end_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/size_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/at_impl.hpp>
+#include <boost/fusion/adapted/std_array/detail/value_at_impl.hpp>
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/array_size.hpp b/boost/fusion/adapted/std_array/detail/array_size.hpp
new file mode 100644
index 0000000000..2f83940465
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/array_size.hpp
@@ -0,0 +1,25 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_ARRAY_SIZE_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_ARRAY_SIZE_01062013_1700
+
+#include <cstddef>
+#include <type_traits>
+
+namespace boost { namespace fusion
+{
+ namespace extension
+ {
+ template<class T>
+ struct std_array_size;
+
+ template<template<typename, std::size_t> class Array, typename T, std::size_t N>
+ struct std_array_size<Array<T, N>> : std::integral_constant<std::size_t, N> {};
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/at_impl.hpp b/boost/fusion/adapted/std_array/detail/at_impl.hpp
new file mode 100644
index 0000000000..6086264a91
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/at_impl.hpp
@@ -0,0 +1,45 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_AT_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_AT_IMPL_01062013_1700
+
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename T>
+ struct at_impl;
+
+ template<>
+ struct at_impl<std_array_tag>
+ {
+ template<typename Sequence, typename N>
+ struct apply
+ {
+ typedef typename mpl::if_<
+ is_const<Sequence>,
+ typename Sequence::const_reference,
+ typename Sequence::reference>::type type;
+
+ static type
+ call(Sequence& seq)
+ {
+ return seq[N::value];
+ }
+ };
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/begin_impl.hpp b/boost/fusion/adapted/std_array/detail/begin_impl.hpp
new file mode 100644
index 0000000000..c84082e34e
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/begin_impl.hpp
@@ -0,0 +1,41 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_BEGIN_OF_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_BEGIN_OF_IMPL_01062013_1700
+
+#include <boost/fusion/adapted/std_array/std_array_iterator.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename T>
+ struct begin_impl;
+
+ template <>
+ struct begin_impl<std_array_tag>
+ {
+ template <typename Sequence>
+ struct apply
+ {
+ typedef std_array_iterator<Sequence, 0> type;
+
+ static type
+ call(Sequence& v)
+ {
+ return type(v);
+ }
+ };
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/category_of_impl.hpp b/boost/fusion/adapted/std_array/detail/category_of_impl.hpp
new file mode 100644
index 0000000000..b5fa09350c
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/category_of_impl.hpp
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_CATEGORY_OF_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_CATEGORY_OF_IMPL_01062013_1700
+
+#include <boost/config/no_tr1/utility.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+ struct random_access_traversal_tag;
+
+ namespace extension
+ {
+ template<typename T>
+ struct category_of_impl;
+
+ template<>
+ struct category_of_impl<std_array_tag>
+ {
+ template<typename T>
+ struct apply
+ {
+ typedef random_access_traversal_tag type;
+ };
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/end_impl.hpp b/boost/fusion/adapted/std_array/detail/end_impl.hpp
new file mode 100644
index 0000000000..b7b789ef5c
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/end_impl.hpp
@@ -0,0 +1,45 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_END_OF_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_END_OF_IMPL_01062013_1700
+
+#include <boost/fusion/adapted/std_array/std_array_iterator.hpp>
+#include <boost/fusion/adapted/std_array/detail/array_size.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template <typename Tag>
+ struct end_impl;
+
+ template <>
+ struct end_impl<std_array_tag>
+ {
+ template <typename Sequence>
+ struct apply
+ {
+ typedef typename remove_const<Sequence>::type seq_type;
+ static int const size = std_array_size<seq_type>::value;
+ typedef std_array_iterator<Sequence, size> type;
+
+ static type
+ call(Sequence& v)
+ {
+ return type(v);
+ }
+ };
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp b/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp
new file mode 100644
index 0000000000..8308e838c3
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_IS_SEQUENCE_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_IS_SEQUENCE_IMPL_01062013_1700
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename Tag>
+ struct is_sequence_impl;
+
+ template<>
+ struct is_sequence_impl<std_array_tag>
+ {
+ template<typename Sequence>
+ struct apply : mpl::true_ {};
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/is_view_impl.hpp b/boost/fusion/adapted/std_array/detail/is_view_impl.hpp
new file mode 100644
index 0000000000..89cd04cf2b
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/is_view_impl.hpp
@@ -0,0 +1,33 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_IS_VIEW_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_IS_VIEW_IMPL_01062013_1700
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace fusion
+{
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename Tag>
+ struct is_view_impl;
+
+ template<>
+ struct is_view_impl<std_array_tag>
+ {
+ template<typename T>
+ struct apply : mpl::false_
+ {};
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/size_impl.hpp b/boost/fusion/adapted/std_array/detail/size_impl.hpp
new file mode 100644
index 0000000000..7df51b2a5e
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/size_impl.hpp
@@ -0,0 +1,41 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_SIZE_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_SIZE_IMPL_01062013_1700
+
+#include <boost/fusion/adapted/std_array/detail/array_size.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename T>
+ struct size_impl;
+
+ template<>
+ struct size_impl<std_array_tag>
+ {
+ template<typename Sequence>
+ struct apply
+ : mpl::int_
+ <
+ std_array_size
+ <
+ typename remove_const<Sequence>::type
+ >::value
+ >
+ {};
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/detail/value_at_impl.hpp b/boost/fusion/adapted/std_array/detail/value_at_impl.hpp
new file mode 100644
index 0000000000..3d7871a7d2
--- /dev/null
+++ b/boost/fusion/adapted/std_array/detail/value_at_impl.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_VALUE_AT_IMPL_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_VALUE_AT_IMPL_01062013_1700
+
+namespace boost { namespace fusion {
+
+ struct std_array_tag;
+
+ namespace extension
+ {
+ template<typename T>
+ struct value_at_impl;
+
+ template <>
+ struct value_at_impl<std_array_tag>
+ {
+ template <typename Sequence, typename N>
+ struct apply
+ {
+ typedef typename Sequence::value_type type;
+ };
+ };
+ }
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/std_array_iterator.hpp b/boost/fusion/adapted/std_array/std_array_iterator.hpp
new file mode 100644
index 0000000000..29584512b0
--- /dev/null
+++ b/boost/fusion/adapted/std_array/std_array_iterator.hpp
@@ -0,0 +1,109 @@
+/*=============================================================================
+ Copyright (c) 2013 Mateusz Loskot
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_ARRAY_ITERATOR_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_ARRAY_ITERATOR_01062013_1700
+
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/minus.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/fusion/iterator/iterator_facade.hpp>
+#include <boost/fusion/adapted/std_array/detail/array_size.hpp>
+
+namespace boost { namespace fusion
+{
+ struct random_access_traversal_tag;
+
+ template <typename Array, int Pos>
+ struct std_array_iterator
+ : iterator_facade<std_array_iterator<Array, Pos>, random_access_traversal_tag>
+ {
+ BOOST_MPL_ASSERT_RELATION(Pos, >=, 0);
+ BOOST_MPL_ASSERT_RELATION(Pos, <=, std::tuple_size<Array>::value);
+
+ typedef mpl::int_<Pos> index;
+ typedef Array array_type;
+
+ std_array_iterator(Array& a)
+ : array(a) {}
+
+ Array& array;
+
+ template <typename Iterator>
+ struct value_of
+ {
+ typedef typename Iterator::array_type array_type;
+ typedef typename array_type::value_type type;
+ };
+
+ template <typename Iterator>
+ struct deref
+ {
+ typedef typename Iterator::array_type array_type;
+ typedef typename
+ mpl::if_<
+ is_const<array_type>
+ , typename array_type::const_reference
+ , typename array_type::reference
+ >::type
+ type;
+
+ static type
+ call(Iterator const & it)
+ {
+ return it.array[Iterator::index::value];
+ }
+ };
+
+ template <typename Iterator, typename N>
+ struct advance
+ {
+ typedef typename Iterator::index index;
+ typedef typename Iterator::array_type array_type;
+ typedef std_array_iterator<array_type, index::value + N::value> type;
+
+ static type
+ call(Iterator const& i)
+ {
+ return type(i.array);
+ }
+ };
+
+ template <typename Iterator>
+ struct next : advance<Iterator, mpl::int_<1> > {};
+
+ template <typename Iterator>
+ struct prior : advance<Iterator, mpl::int_<-1> > {};
+
+ template <typename I1, typename I2>
+ struct distance : mpl::minus<typename I2::index, typename I1::index>
+ {
+ typedef typename
+ mpl::minus<
+ typename I2::index, typename I1::index
+ >::type
+ type;
+
+ static type
+ call(I1 const&, I2 const&)
+ {
+ return type();
+ }
+ };
+
+ private:
+
+ std_array_iterator<Array, Pos>& operator=(std_array_iterator<Array, Pos> const&);
+ };
+}}
+
+#endif
diff --git a/boost/fusion/adapted/std_array/tag_of.hpp b/boost/fusion/adapted/std_array/tag_of.hpp
new file mode 100644
index 0000000000..543c5bb461
--- /dev/null
+++ b/boost/fusion/adapted/std_array/tag_of.hpp
@@ -0,0 +1,52 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2005-2006 Dan Marsden
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#if !defined(BOOST_FUSION_STD_ARRAY_TAG_OF_01062013_1700)
+#define BOOST_FUSION_STD_ARRAY_TAG_OF_01062013_1700
+
+#include <boost/fusion/support/tag_of_fwd.hpp>
+#include <array>
+#include <cstddef>
+
+namespace boost { namespace fusion
+{
+ struct std_array_tag;
+ struct fusion_sequence_tag;
+
+ namespace traits
+ {
+ template<typename T, std::size_t N>
+#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS)
+ struct tag_of<std::array<T,N>, void >
+#else
+ struct tag_of<std::array<T,N> >
+#endif
+ {
+ typedef std_array_tag type;
+ };
+ }
+}}
+
+namespace boost { namespace mpl
+{
+ template<typename>
+ struct sequence_tag;
+
+ template<typename T, std::size_t N>
+ struct sequence_tag<std::array<T,N> >
+ {
+ typedef fusion::fusion_sequence_tag type;
+ };
+
+ template<typename T, std::size_t N>
+ struct sequence_tag<std::array<T,N> const>
+ {
+ typedef fusion::fusion_sequence_tag type;
+ };
+}}
+
+#endif
diff --git a/boost/fusion/adapted/struct/detail/define_struct.hpp b/boost/fusion/adapted/struct/detail/define_struct.hpp
index ab483f0252..cb52ddff9f 100644
--- a/boost/fusion/adapted/struct/detail/define_struct.hpp
+++ b/boost/fusion/adapted/struct/detail/define_struct.hpp
@@ -10,6 +10,7 @@
#include <boost/fusion/support/config.hpp>
#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/next.hpp>
@@ -39,6 +40,8 @@
#define BOOST_FUSION_DEFINE_STRUCT_FILLER_0_END
#define BOOST_FUSION_DEFINE_STRUCT_FILLER_1_END
+#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I( \
R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
@@ -46,6 +49,54 @@
BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)( \
other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE))
+#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED \
+ NAME(self_type const& other_self) \
+ : BOOST_PP_SEQ_FOR_EACH_I_R( \
+ 1, \
+ BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I, \
+ ATTRIBUTE_TUPLE_SIZE, \
+ ATTRIBUTES_SEQ) \
+ {}
+
+// Use templated version instead.
+#define BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_FILLER_I( \
+ R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \
+ \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)= \
+ other.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE);
+
+#define BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED \
+ self_type& operator=(self_type const& other) \
+ { \
+ BOOST_PP_SEQ_FOR_EACH_I_R( \
+ 1, \
+ BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_FILLER_I, \
+ ATTRIBUTE_TUPLE_SIZE, \
+ ATTRIBUTES_SEQ) \
+ \
+ return *this; \
+ }
+
+#else // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
+#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED NAME(self_type const&) = default;
+
+#define BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED self_type& operator=(self_type const&) = default;
+
+#endif // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
#define BOOST_FUSION_DEFINE_STRUCT_ASSIGN_FILLER_I( \
R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \
\
@@ -85,6 +136,81 @@
return *this; \
}
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR(NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
+
+#else // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) \
+ || BOOST_WORKAROUND(BOOST_GCC, < 40500) \
+ || BOOST_WORKAROUND(BOOST_MSVC, == 1800)
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR_FILLER_I( \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
+ \
+ BOOST_PP_COMMA_IF(I) \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)(std::move( \
+ other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)))
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED \
+ NAME(self_type&& other_self) \
+ : BOOST_PP_SEQ_FOR_EACH_I_R( \
+ 1, \
+ BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR_FILLER_I, \
+ ATTRIBUTE_TUPLE_SIZE, \
+ ATTRIBUTES_SEQ) \
+ {}
+
+#else // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED NAME(self_type&&) = default;
+
+#endif // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
+#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) \
+ || BOOST_WORKAROUND(BOOST_GCC, < 40600) \
+ || BOOST_WORKAROUND(BOOST_MSVC, == 1800)
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_FILLER_I( \
+ R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \
+ \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)=std::move( \
+ other.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE));
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED \
+ self_type& operator=(self_type&& other) \
+ { \
+ BOOST_PP_SEQ_FOR_EACH_I_R( \
+ 1, \
+ BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_FILLER_I, \
+ ATTRIBUTE_TUPLE_SIZE, \
+ ATTRIBUTES_SEQ) \
+ \
+ return *this; \
+ }
+
+#else // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
+#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ \
+ BOOST_FUSION_GPU_ENABLED self_type& operator=(self_type&&) = default;
+
+#endif // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
#define BOOST_FUSION_DEFINE_STRUCT_ATTR_I(R, ATTRIBUTE_TUPLE_SIZE, ATTRIBUTE) \
\
BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,0,ATTRIBUTE) \
@@ -135,14 +261,10 @@
ATTRIBUTES_SEQ) \
{} \
\
- BOOST_FUSION_GPU_ENABLED \
- NAME(self_type const& other_self) \
- : BOOST_PP_SEQ_FOR_EACH_I_R( \
- 1, \
- BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I, \
- ATTRIBUTE_TUPLE_SIZE, \
- ATTRIBUTES_SEQ) \
- {} \
+ BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
template<typename Seq> \
BOOST_FUSION_GPU_ENABLED \
@@ -160,6 +282,10 @@
ATTRIBUTES_SEQ) \
{} \
\
+ BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
+ BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
BOOST_FUSION_DEFINE_STRUCT_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_STRUCT_CTOR_1( \
@@ -282,20 +408,7 @@
NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_EMPTY_STRUCT_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
- \
- template<typename Seq> \
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \
- NAME(Seq const&) \
- {} \
- \
- template<typename Seq> \
- BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED \
- self_type& \
- operator=(Seq const& seq) \
- { \
- return *this; \
- }
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_STRUCT_IMPL( \
NAMESPACE_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
@@ -327,10 +440,7 @@
ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_EMPTY_TPL_STRUCT_IMPL( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
- \
- BOOST_FUSION_DEFINE_EMPTY_STRUCT_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_TPL_STRUCT_IMPL( \
TEMPLATE_PARAMS_SEQ, \
diff --git a/boost/fusion/container/deque/detail/keyed_element.hpp b/boost/fusion/container/deque/detail/keyed_element.hpp
index 24b5979d2d..15b686671d 100644
--- a/boost/fusion/container/deque/detail/keyed_element.hpp
+++ b/boost/fusion/container/deque/detail/keyed_element.hpp
@@ -59,7 +59,7 @@ namespace boost { namespace fusion { namespace detail
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
keyed_element(keyed_element&& rhs)
- : Rest(BOOST_FUSION_FWD_ELEM(Rest, rhs.forward_base()))
+ : Rest(rhs.forward_base())
, value_(BOOST_FUSION_FWD_ELEM(Value, rhs.value_))
{}
#endif
@@ -90,7 +90,7 @@ namespace boost { namespace fusion { namespace detail
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
Rest&& forward_base() BOOST_NOEXCEPT
{
- return BOOST_FUSION_FWD_ELEM(Rest, *static_cast<Rest*>(this));
+ return std::move(*static_cast<Rest*>(this));
}
#endif
@@ -116,7 +116,7 @@ namespace boost { namespace fusion { namespace detail
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
keyed_element(Value&& value, Rest&& rest)
- : Rest(BOOST_FUSION_FWD_ELEM(Rest, rest))
+ : Rest(std::move(rest))
, value_(BOOST_FUSION_FWD_ELEM(Value, value))
{}
#endif
@@ -147,8 +147,8 @@ namespace boost { namespace fusion { namespace detail
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
keyed_element& operator=(keyed_element&& rhs)
{
- base::operator=(std::forward<keyed_element>(rhs));
- value_ = BOOST_FUSION_FWD_ELEM(Value, rhs.value_);
+ base::operator=(rhs.forward_base());
+ value_ = std::move(rhs.value_);
return *this;
}
#endif
diff --git a/boost/fusion/container/vector/detail/config.hpp b/boost/fusion/container/vector/detail/config.hpp
index 84f4605d2e..2a7aea64a8 100644
--- a/boost/fusion/container/vector/detail/config.hpp
+++ b/boost/fusion/container/vector/detail/config.hpp
@@ -15,6 +15,8 @@
|| defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \
|| defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \
|| defined(BOOST_NO_CXX11_DECLTYPE)) \
+ || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \
+ || defined(BOOST_FUSION_DISABLE_VARIADIC_VECTOR) \
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
# if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
# undef BOOST_FUSION_HAS_VARIADIC_VECTOR
diff --git a/boost/fusion/container/vector/vector.hpp b/boost/fusion/container/vector/vector.hpp
index 65bffd0b69..62d2445eca 100644
--- a/boost/fusion/container/vector/vector.hpp
+++ b/boost/fusion/container/vector/vector.hpp
@@ -24,23 +24,21 @@
///////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/is_sequence.hpp>
-#include <boost/fusion/support/void.hpp>
-#include <boost/fusion/support/detail/enabler.hpp>
+#include <boost/fusion/support/detail/and.hpp>
#include <boost/fusion/support/detail/index_sequence.hpp>
#include <boost/fusion/container/vector/detail/at_impl.hpp>
#include <boost/fusion/container/vector/detail/value_at_impl.hpp>
#include <boost/fusion/container/vector/detail/begin_impl.hpp>
#include <boost/fusion/container/vector/detail/end_impl.hpp>
-#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
+#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/iterator/advance.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/int.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <cstddef>
#include <utility>
@@ -53,52 +51,48 @@ namespace boost { namespace fusion
namespace vector_detail
{
struct each_elem {};
- struct copy_or_move {};
- template <typename I> struct from_sequence {};
- template <typename Sequence>
- struct make_indices_from_seq
- : detail::make_index_sequence<
- fusion::result_of::size<typename remove_reference<Sequence>::type>::value
+ template <
+ typename This, typename T, typename T_, std::size_t Size, bool IsSeq
+ >
+ struct can_convert_impl : false_type {};
+
+ template <typename This, typename T, typename Sequence, std::size_t Size>
+ struct can_convert_impl<This, T, Sequence, Size, true> : true_type {};
+
+ template <typename This, typename Sequence, typename T>
+ struct can_convert_impl<This, Sequence, T, 1, true>
+ : integral_constant<
+ bool
+ , !is_convertible<
+ Sequence
+ , typename fusion::extension::value_at_impl<vector_tag>::
+ template apply< This, mpl::int_<0> >::type
+ >::value
>
{};
- template <typename T>
- struct pure : remove_cv<typename remove_reference<T>::type> {};
-
- template <typename Sequence, typename This, int = result_of::size<This>::value>
- struct is_convertible_to_first
- : boost::is_convertible<Sequence, typename result_of::value_at_c<This, 0>::type>
- {};
-
- template <typename Sequence, typename This>
- struct is_convertible_to_first<Sequence, This, 0>
- : mpl::false_
+ template <typename This, typename T, typename T_, std::size_t Size>
+ struct can_convert
+ : can_convert_impl<
+ This, T, T_, Size, traits::is_sequence<T_>::value
+ >
{};
- template <typename This, typename ...T>
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- inline each_elem
- dispatch(T const&...) BOOST_NOEXCEPT { return each_elem(); }
-
- template <typename This>
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- inline copy_or_move
- dispatch(This const&) BOOST_NOEXCEPT { return copy_or_move(); }
+ template <typename T, bool IsSeq, std::size_t Size>
+ struct is_longer_sequence_impl : false_type {};
- template <typename This, typename Sequence>
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- inline from_sequence<
- typename lazy_enable_if_c<
- (traits::is_sequence<typename remove_reference<Sequence>::type>::value &&
- !is_same<This, typename pure<Sequence>::type>::value &&
- !is_convertible_to_first<Sequence, This>::value)
- , make_indices_from_seq<Sequence>
- >::type
- >
- dispatch(Sequence&&) BOOST_NOEXCEPT
- { return from_sequence<typename make_indices_from_seq<Sequence>::type>(); }
+ template <typename Sequence, std::size_t Size>
+ struct is_longer_sequence_impl<Sequence, true, Size>
+ : integral_constant<
+ bool, (fusion::result_of::size<Sequence>::value >= Size)
+ >
+ {};
+ template<typename T, std::size_t Size>
+ struct is_longer_sequence
+ : is_longer_sequence_impl<T, traits::is_sequence<T>::value, Size>
+ {};
// forward_at_c allows to access Nth element even if ForwardSequence
// since fusion::at_c requires RandomAccessSequence.
@@ -163,22 +157,17 @@ namespace boost { namespace fusion
return *this;
}
- template <typename U>
+ template <
+ typename U
+ , typename = typename boost::disable_if<
+ is_base_of<store, typename remove_reference<U>::type>
+ >::type
+ >
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- store(U&& rhs
- , typename disable_if<is_same<typename pure<U>::type, store>, detail::enabler_>::type = detail::enabler)
+ store(U&& rhs)
: elem(std::forward<U>(rhs))
{}
- template <typename U>
- BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- typename disable_if<is_same<typename pure<U>::type, store>, store&>::type
- operator=(U&& rhs)
- {
- elem = std::forward<U>(rhs);
- return *this;
- }
-
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
T & get() { return elem; }
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
@@ -206,21 +195,17 @@ namespace boost { namespace fusion
vector_data()
{}
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- vector_data(copy_or_move, vector_data const& rhs)
- : store<I, T>(static_cast<store<I, T> const&>(rhs))...
- {}
-
- BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- vector_data(copy_or_move, vector_data&& rhs)
- : store<I, T>(std::forward<store<I, T> >(rhs))...
- {}
-
- template <typename Sequence>
+ template <
+ typename Sequence
+ , typename Sequence_ = typename remove_reference<Sequence>::type
+ , typename = typename boost::enable_if<
+ can_convert<vector_data, Sequence, Sequence_, sizeof...(I)>
+ >::type
+ >
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
- vector_data(from_sequence<detail::index_sequence<I...> >, Sequence&& rhs)
- : store<I, T>(forward_at_c<I>(rhs))...
+ vector_data(each_elem, Sequence&& rhs)
+ : store<I, T>(forward_at_c<I>(std::forward<Sequence>(rhs)))...
{}
template <typename ...U>
@@ -233,6 +218,14 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
void
+ assign_sequence(Sequence&& seq)
+ {
+ assign(std::forward<Sequence>(seq), detail::index_sequence<I...>());
+ }
+
+ template <typename Sequence>
+ BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
+ void
assign(Sequence&&, detail::index_sequence<>) {}
template <typename Sequence, std::size_t N, std::size_t ...M>
@@ -294,15 +287,36 @@ namespace boost { namespace fusion
vector()
{}
- // rvalue-references is required here in order to forward any arguments to
- // base: vector(T const&...) doesn't work with trailing void_ and
- // vector(U const&...) cannot forward any arguments to base.
- template <typename... U>
+ template <
+ typename... U
+ , typename = typename boost::enable_if_c<(
+ sizeof...(U) >= 1 &&
+ fusion::detail::and_<is_convertible<U, T>...>::value &&
+ !fusion::detail::and_<
+ is_base_of<vector, typename remove_reference<U>::type>...
+ >::value
+ )>::type
+ >
// XXX: constexpr become error due to pull-request #79, booooo!!
// In the (near) future release, should be fixed.
/* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED
- vector(U&&... u)
- : base(vector_detail::dispatch<vector>(std::forward<U>(u)...), std::forward<U>(u)...)
+ explicit vector(U&&... u)
+ : base(vector_detail::each_elem(), std::forward<U>(u)...)
+ {}
+
+ template <
+ typename Sequence
+ , typename Sequence_ = typename remove_reference<Sequence>::type
+ , typename = typename boost::enable_if_c<(
+ !is_base_of<vector, Sequence_>::value &&
+ vector_detail::is_longer_sequence<
+ Sequence_, sizeof...(T)
+ >::value
+ )>::type
+ >
+ BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
+ vector(Sequence&& seq)
+ : base(vector_detail::each_elem(), std::forward<Sequence>(seq))
{}
template <typename Sequence>
@@ -310,10 +324,7 @@ namespace boost { namespace fusion
vector&
operator=(Sequence&& rhs)
{
- typedef typename
- vector_detail::make_indices_from_seq<Sequence>::type
- indices;
- base::assign(std::forward<Sequence>(rhs), indices());
+ base::assign_sequence(std::forward<Sequence>(rhs));
return *this;
}
};
diff --git a/boost/fusion/support/detail/and.hpp b/boost/fusion/support/detail/and.hpp
new file mode 100644
index 0000000000..1b310dda36
--- /dev/null
+++ b/boost/fusion/support/detail/and.hpp
@@ -0,0 +1,39 @@
+/*=============================================================================
+ Copyright (c) 2016 Lee Clagett
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#ifndef FUSION_AND_07152016_1625
+#define FUSION_AND_07152016_1625
+
+#include <boost/config.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#error fusion::detail::and_ requires variadic templates
+#endif
+
+namespace boost { namespace fusion { namespace detail {
+ template<typename ...Cond>
+ struct and_impl : false_type {};
+
+ template<typename ...T>
+ struct and_impl<integral_constant<T, true>...> : true_type {};
+
+ // This specialization is necessary to avoid MSVC-12 variadics bug.
+ template<bool ...Cond>
+ struct and_impl1 : and_impl<integral_constant<bool, Cond>...> {};
+
+ /* fusion::detail::and_ differs from mpl::and_ in the following ways:
+ - The empty set is valid and returns true
+ - A single element set is valid and returns the identity
+ - There is no upper bound on the set size
+ - The conditions are evaluated at once, and are not short-circuited. This
+ reduces instantations when returning true; the implementation is not
+ recursive. */
+ template<typename ...Cond>
+ struct and_ : and_impl1<Cond::value...> {};
+}}}
+
+#endif // FUSION_AND_07152016_1625
diff --git a/boost/fusion/tuple/tuple.hpp b/boost/fusion/tuple/tuple.hpp
index 6ee21f56a0..07014c6c29 100644
--- a/boost/fusion/tuple/tuple.hpp
+++ b/boost/fusion/tuple/tuple.hpp
@@ -20,12 +20,15 @@
///////////////////////////////////////////////////////////////////////////////
// C++11 interface
///////////////////////////////////////////////////////////////////////////////
+#include <boost/core/enable_if.hpp>
#include <boost/fusion/container/vector/vector.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/sequence/intrinsic/value_at.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/sequence/comparison.hpp>
#include <boost/fusion/sequence/io.hpp>
+#include <boost/fusion/support/detail/and.hpp>
+#include <boost/type_traits/is_convertible.hpp>
#include <utility>
namespace boost { namespace fusion
@@ -39,23 +42,49 @@ namespace boost { namespace fusion
tuple()
: base_type() {}
- template <typename ...U>
+ template <
+ typename ...U
+ , typename = typename boost::enable_if_c<
+ sizeof...(U) >= sizeof...(T)
+ >::type
+ >
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
tuple(tuple<U...> const& other)
: base_type(other) {}
- template <typename ...U>
+ template <
+ typename ...U
+ , typename = typename boost::enable_if_c<
+ sizeof...(U) >= sizeof...(T)
+ >::type
+ >
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
tuple(tuple<U...>&& other)
: base_type(std::move(other)) {}
- template <typename ...U>
+ template <
+ typename ...U
+ , typename = typename boost::enable_if_c<(
+ fusion::detail::and_<is_convertible<U, T>...>::value &&
+ sizeof...(U) >= 1
+ )>::type
+ >
/*BOOST_CONSTEXPR*/ BOOST_FUSION_GPU_ENABLED
explicit
tuple(U&&... args)
: base_type(std::forward<U>(args)...) {}
- template <typename U>
+ template<typename U1, typename U2>
+ BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
+ tuple(std::pair<U1, U2> const& other)
+ : base_type(other.first, other.second) {}
+
+ template<typename U1, typename U2>
+ BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
+ tuple(std::pair<U1, U2>&& other)
+ : base_type(std::move(other.first), std::move(other.second)) {}
+
+ template<typename U>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
tuple& operator=(U&& rhs)
{
diff --git a/boost/fusion/view/zip_view/zip_view.hpp b/boost/fusion/view/zip_view/zip_view.hpp
index cf6f6d2716..b03272015d 100644
--- a/boost/fusion/view/zip_view/zip_view.hpp
+++ b/boost/fusion/view/zip_view/zip_view.hpp
@@ -126,7 +126,7 @@ namespace boost { namespace fusion {
zip_view(
const Sequences& seqs)
: sequences_(seqs)
- {};
+ {}
sequences sequences_;
};
diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp
index 8948bf6afd..7e0d1691ed 100644
--- a/boost/geometry/algorithms/detail/azimuth.hpp
+++ b/boost/geometry/algorithms/detail/azimuth.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016.
+// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,7 +22,8 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
{
@@ -49,7 +50,7 @@ struct azimuth<ReturnType, geographic_tag>
template <typename P1, typename P2, typename Spheroid>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
{
- return geometry::detail::vincenty_inverse<ReturnType, false, true>().apply
+ return geometry::formula::vincenty_inverse<ReturnType, false, true>().apply
( get_as_radian<0>(p1), get_as_radian<1>(p1),
get_as_radian<0>(p2), get_as_radian<1>(p2),
spheroid ).azimuth;
diff --git a/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp b/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp
new file mode 100644
index 0000000000..df62a1f2f6
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp
@@ -0,0 +1,100 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
+
+#include <set>
+
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay { namespace sort_by_side
+{
+
+struct ring_with_direction
+{
+ ring_identifier ring_id;
+ direction_type direction;
+ bool only_turn_on_ring;
+
+
+ inline bool operator<(ring_with_direction const& other) const
+ {
+ return this->ring_id != other.ring_id
+ ? this->ring_id < other.ring_id
+ : this->direction < other.direction;
+ }
+
+ ring_with_direction()
+ : direction(dir_unknown)
+ , only_turn_on_ring(false)
+ {}
+};
+
+struct rank_with_rings
+{
+ std::size_t rank;
+ std::set<ring_with_direction> rings;
+
+ rank_with_rings()
+ : rank(0)
+ {
+ }
+
+ inline bool all_to() const
+ {
+ for (std::set<ring_with_direction>::const_iterator it = rings.begin();
+ it != rings.end(); ++it)
+ {
+ if (it->direction == sort_by_side::dir_from)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+template <typename Sbs>
+inline void aggregate_operations(Sbs const& sbs, std::vector<rank_with_rings>& aggregation)
+{
+ aggregation.clear();
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ typename Sbs::rp const& ranked_point = sbs.m_ranked_points[i];
+
+ if (aggregation.empty() || aggregation.back().rank != ranked_point.rank)
+ {
+ rank_with_rings current;
+ current.rank = ranked_point.rank;
+ aggregation.push_back(current);
+ }
+
+ ring_with_direction rwd;
+ segment_identifier const& sid = ranked_point.seg_id;
+ rwd.ring_id = ring_identifier(sid.source_index, sid.multi_index, sid.ring_index);
+ rwd.direction = ranked_point.direction;
+ rwd.only_turn_on_ring = ranked_point.only_turn_on_ring;
+
+
+ aggregation.back().rings.insert(rwd);
+ }
+}
+
+
+}}} // namespace detail::overlay::sort_by_side
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
index cc55414870..2643415343 100644
--- a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
@@ -38,6 +38,7 @@ struct enrichment_info
, count_left(0)
, count_right(0)
, zone(-1)
+ , only_turn_on_ring(false)
{}
// vertex to which is free travel after this IP,
@@ -57,6 +58,7 @@ struct enrichment_info
std::size_t count_left;
std::size_t count_right;
signed_size_type zone; // open zone, in cluster
+ bool only_turn_on_ring; // True if it is the only turn on a ring (for clusters)
};
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 110e1be2f1..400ed3b881 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -14,6 +14,7 @@
#include <map>
#include <vector>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
@@ -198,7 +199,9 @@ inline signed_size_type add_turn_to_cluster(Turn const& turn,
// Both operations.seg_id/fraction were already part of any cluster, and
// these clusters are not the same. Merge of two clusters is necessary
+#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
std::cout << " TODO: merge " << cid0 << " and " << cid1 << std::endl;
+#endif
return cid0;
}
@@ -314,11 +317,13 @@ inline void assign_cluster_to_turns(Turns& turns,
typename ClusterPerSegment::const_iterator it = cluster_per_segment.find(seg_frac);
if (it != cluster_per_segment.end())
{
+#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
if (turn.cluster_id != -1
&& turn.cluster_id != it->second)
{
std::cout << " CONFLICT " << std::endl;
}
+#endif
turn.cluster_id = it->second;
clusters[turn.cluster_id].turn_indices.insert(turn_index);
}
@@ -392,6 +397,8 @@ inline bool is_ie_turn(segment_identifier const& ext_seg_0,
bool const same_multi1 = ! Reverse1
&& ext_seg_1.multi_index == other_seg_1.multi_index;
+ boost::ignore_unused(same_multi1);
+
return same_multi0
&& same_multi1
&& ! is_interior<Reverse0>(ext_seg_0)
@@ -680,6 +687,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
sbs.apply(turn_point);
sbs.find_open();
+ sbs.assign_zones(for_operation);
// Unset the startable flag for all 'closed' zones
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
@@ -706,7 +714,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
}
}
- cinfo.open_count = sbs.open_count(turns);
+ cinfo.open_count = sbs.open_count(for_operation);
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
index 91b0f8ae24..bbba623eee 100644
--- a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -37,10 +37,12 @@ struct ranked_point
, count_left(0)
, count_right(0)
, operation(operation_none)
+ , only_turn_on_ring(false)
{}
- ranked_point(const Point& p, signed_size_type ti, signed_size_type oi,
- direction_type d, operation_type op, segment_identifier sid)
+ template <typename Op>
+ ranked_point(const Point& p, signed_size_type ti, int oi,
+ direction_type d, Op op)
: point(p)
, rank(0)
, zone(-1)
@@ -49,20 +51,22 @@ struct ranked_point
, direction(d)
, count_left(0)
, count_right(0)
- , operation(op)
- , seg_id(sid)
+ , operation(op.operation)
+ , seg_id(op.seg_id)
+ , only_turn_on_ring(op.enriched.only_turn_on_ring)
{}
Point point;
std::size_t rank;
signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones
signed_size_type turn_index;
- signed_size_type operation_index;
+ int operation_index; // 0,1
direction_type direction;
std::size_t count_left;
std::size_t count_right;
operation_type operation;
segment_identifier seg_id;
+ bool only_turn_on_ring;
};
struct less_by_turn_index
@@ -181,11 +185,36 @@ private :
Point m_p1, m_p2;
};
+// Sorts vectors in counter clockwise order (by default)
template <bool Reverse1, bool Reverse2, typename Point, typename Compare>
struct side_sorter
{
typedef ranked_point<Point> rp;
+private :
+ struct include_union
+ {
+ inline bool operator()(rp const& ranked_point) const
+ {
+ // New candidate if there are no polygons on left side,
+ // but there are on right side
+ return ranked_point.count_left == 0
+ && ranked_point.count_right > 0;
+ }
+ };
+
+ struct include_intersection
+ {
+ inline bool operator()(rp const& ranked_point) const
+ {
+ // New candidate if there are two polygons on right side,
+ // and less on the left side
+ return ranked_point.count_left < 2
+ && ranked_point.count_right >= 2;
+ }
+ };
+
+public :
inline void set_origin(Point const& origin)
{
m_origin = origin;
@@ -202,8 +231,8 @@ struct side_sorter
op.seg_id, point1, point2, point3);
Point const& point_to = op.fraction.is_one() ? point3 : point2;
- m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op.operation, op.seg_id));
- m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op.operation, op.seg_id));
+ m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op));
+ m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op));
if (is_origin)
{
@@ -292,8 +321,6 @@ struct side_sorter
&segment_identifier::source_index
>(handled);
}
-
- assign_zones();
}
void reverse()
@@ -303,7 +330,7 @@ struct side_sorter
return;
}
- int const last = 1 + m_ranked_points.back().rank;
+ std::size_t const last = 1 + m_ranked_points.back().rank;
// Move iterator after rank==0
bool has_first = false;
@@ -334,13 +361,18 @@ struct side_sorter
}
}
+//private :
+
+ typedef std::vector<rp> container_type;
+ container_type m_ranked_points;
+ Point m_origin;
+
+private :
+
//! Check how many open spaces there are
- template <typename Turns>
- std::size_t open_count(Turns const& turns) const
+ template <typename Include>
+ inline std::size_t open_count(Include const& include_functor) const
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type turn_operation_type;
-
std::size_t result = 0;
std::size_t last_rank = 0;
for (std::size_t i = 0; i < m_ranked_points.size(); i++)
@@ -348,31 +380,16 @@ struct side_sorter
rp const& ranked_point = m_ranked_points[i];
if (ranked_point.rank > last_rank
- && ranked_point.direction == sort_by_side::dir_to)
+ && ranked_point.direction == sort_by_side::dir_to
+ && include_functor(ranked_point))
{
- // TODO: take count-left / count_right from rank itself
- turn_type const& ranked_turn = turns[ranked_point.turn_index];
- turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index];
- if (ranked_op.enriched.count_left == 0
- && ranked_op.enriched.count_right > 0)
- {
- result++;
- last_rank = ranked_point.rank;
- }
+ result++;
+ last_rank = ranked_point.rank;
}
}
return result;
}
-//protected :
-
- typedef std::vector<rp> container_type;
- container_type m_ranked_points;
- Point m_origin;
-
-private :
-
-
std::size_t move(std::size_t index) const
{
std::size_t const result = index + 1;
@@ -458,7 +475,8 @@ private :
}
//! Find closed zones and assign it
- void assign_zones()
+ template <typename Include>
+ std::size_t assign_zones(Include const& include_functor)
{
// Find a starting point (the first rank after an outgoing rank
// with no polygons on the left side)
@@ -473,8 +491,7 @@ private :
max_rank = ranked_point.rank;
}
if (ranked_point.direction == sort_by_side::dir_to
- && ranked_point.count_left == 0
- && ranked_point.count_right > 0)
+ && include_functor(ranked_point))
{
start_rank = ranked_point.rank + 1;
}
@@ -510,8 +527,7 @@ private :
}
if (ranked_point.direction == sort_by_side::dir_to
- && ranked_point.count_left == 0
- && ranked_point.count_right > 0)
+ && include_functor(ranked_point))
{
rank_at_next_zone = ranked_point.rank + 1;
if (rank_at_next_zone > max_rank)
@@ -525,8 +541,25 @@ private :
ranked_point.zone = zone_id;
}
+ return zone_id;
}
+public :
+ inline std::size_t open_count(operation_type for_operation) const
+ {
+ return for_operation == operation_union
+ ? open_count(include_union())
+ : open_count(include_intersection())
+ ;
+ }
+
+ inline std::size_t assign_zones(operation_type for_operation)
+ {
+ return for_operation == operation_union
+ ? assign_zones(include_union())
+ : assign_zones(include_intersection())
+ ;
+ }
};
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index 1156644bc3..5adc0fcf69 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -13,6 +13,7 @@
#include <boost/range.hpp>
+#include <boost/geometry/algorithms/detail/overlay/aggregate_operations.hpp>
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/core/access.hpp>
@@ -152,8 +153,8 @@ struct traversal
}
}
- inline bool is_visited(turn_type const& turn, turn_operation_type const& op,
- signed_size_type turn_index, int op_index) const
+ inline bool is_visited(turn_type const& , turn_operation_type const& op,
+ signed_size_type , int) const
{
return op.visited.visited();
}
@@ -162,39 +163,30 @@ struct traversal
segment_identifier const& seg_id1,
segment_identifier const& seg_id2) const
{
- if (target_operation == operation_intersection)
+ // For uu/ii, only switch sources if indicated
+ turn_type const& turn = m_turns[turn_index];
+
+ if (OverlayType == overlay_buffer)
{
- // For intersections always switch sources
- return seg_id1.source_index != seg_id2.source_index;
+ // Buffer does not use source_index (always 0)
+ return turn.switch_source
+ ? seg_id1.multi_index != seg_id2.multi_index
+ : seg_id1.multi_index == seg_id2.multi_index;
}
- else if (target_operation == operation_union)
- {
- // For uu, only switch sources if indicated
- turn_type const& turn = m_turns[turn_index];
-
- if (OverlayType == overlay_buffer)
- {
- // Buffer does not use source_index (always 0)
- return turn.switch_source
- ? seg_id1.multi_index != seg_id2.multi_index
- : seg_id1.multi_index == seg_id2.multi_index;
- }
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
- if (turn.switch_source == 1)
- {
- std::cout << "Switch source at " << turn_index << std::endl;
- }
- else
- {
- std::cout << "DON'T SWITCH SOURCES at " << turn_index << std::endl;
- }
-#endif
- return turn.switch_source
- ? seg_id1.source_index != seg_id2.source_index
- : seg_id1.source_index == seg_id2.source_index;
+ if (turn.switch_source)
+ {
+ std::cout << "Switch source at " << turn_index << std::endl;
}
- return false;
+ else
+ {
+ std::cout << "DON'T SWITCH SOURCES at " << turn_index << std::endl;
+ }
+#endif
+ return turn.switch_source
+ ? seg_id1.source_index != seg_id2.source_index
+ : seg_id1.source_index == seg_id2.source_index;
}
inline
@@ -273,10 +265,6 @@ struct traversal
segment_identifier const& seg_id,
int& selected_op_index) const
{
- // For "ii", take the other one (alternate)
- // UNLESS the other one is already visited
- // For "uu", take the same one (see above);
-
bool result = false;
for (int i = 0; i < 2; i++)
@@ -347,13 +335,10 @@ struct traversal
return true;
}
- inline bool select_from_cluster(signed_size_type& turn_index,
+ inline bool select_from_cluster_union(signed_size_type& turn_index,
int& op_index, signed_size_type start_turn_index,
sbs_type const& sbs, bool is_touching) const
{
- bool const is_union = target_operation == operation_union;
- bool const is_intersection = target_operation == operation_intersection;
-
std::size_t selected_rank = 0;
std::size_t min_rank = 0;
bool result = false;
@@ -386,11 +371,8 @@ struct traversal
&& (ranked_point.rank > min_rank
|| ranked_turn.both(operation_continue)))
{
- if ((is_union
- && ranked_op.enriched.count_left == 0
+ if (ranked_op.enriched.count_left == 0
&& ranked_op.enriched.count_right > 0)
- || (is_intersection
- && ranked_op.enriched.count_right == 2))
{
if (result && ranked_point.turn_index != start_turn_index)
{
@@ -401,16 +383,6 @@ struct traversal
turn_index = ranked_point.turn_index;
op_index = ranked_point.operation_index;
- if (is_intersection
- && ranked_turn.both(operation_intersection)
- && ranked_op.visited.finalized())
- {
- // Override:
- // For a ii turn, even though one operation might be selected,
- // it should take the other one if the first one is used in a completed ring
- op_index = 1 - ranked_point.operation_index;
- }
-
result = true;
selected_rank = ranked_point.rank;
}
@@ -423,10 +395,94 @@ struct traversal
return result;
}
+ inline bool analyze_cluster_intersection(signed_size_type& turn_index,
+ int& op_index,
+ sbs_type const& sbs) const
+ {
+ std::vector<sort_by_side::rank_with_rings> aggregation;
+ sort_by_side::aggregate_operations(sbs, aggregation);
+
+ std::size_t selected_rank = 0;
+
+ for (std::size_t i = 0; i < aggregation.size(); i++)
+ {
+ sort_by_side::rank_with_rings const& rwr = aggregation[i];
+
+ if (i > 1
+ && i - 1 == selected_rank
+ && rwr.rings.size() == 1)
+ {
+ sort_by_side::ring_with_direction const& rwd = *rwr.rings.begin();
+
+ if (rwd.only_turn_on_ring)
+ {
+ // Find if this arriving ring was leaving previously
+ sort_by_side::ring_with_direction leaving = rwd;
+ leaving.direction = sort_by_side::dir_to;
+
+ sort_by_side::rank_with_rings const& previous = aggregation[i - 1];
+
+ if (previous.rings.size() == 1
+ && previous.rings.count(leaving) == 1)
+ {
+ // It arrives back - if this is one of the selected, unselect it
+ selected_rank = 0;
+ }
+ }
+ }
+
+ if (rwr.all_to())
+ {
+ if (selected_rank == 0)
+ {
+ // Take the first (= right) where segments leave,
+ // having the polygon on the right side
+ selected_rank = rwr.rank;
+ }
+ }
+ }
+
+ if (selected_rank > 0)
+ {
+ std::size_t selected_index = sbs.m_ranked_points.size();
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
+
+ if (ranked_point.rank == selected_rank)
+ {
+ turn_type const& ranked_turn = m_turns[ranked_point.turn_index];
+ turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index];
+
+ if (ranked_op.visited.finalized())
+ {
+ // This direction is already traveled before, the same
+ // cannot be traveled again
+ return false;
+ }
+
+ // Take the last turn from this rank
+ selected_index = i;
+ }
+ }
+
+ if (selected_index < sbs.m_ranked_points.size())
+ {
+ typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[selected_index];
+ turn_index = ranked_point.turn_index;
+ op_index = ranked_point.operation_index;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
inline bool select_turn_from_cluster(signed_size_type& turn_index,
int& op_index, bool& is_touching,
signed_size_type start_turn_index,
- segment_identifier const& previous_seg_id) const
+ segment_identifier const& previous_seg_id,
+ bool is_start) const
{
bool const is_union = target_operation == operation_union;
@@ -488,30 +544,76 @@ struct traversal
sbs.apply(turn.point);
-#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
- is_touching = is_union && cinfo.open_count > 1;
- if (is_touching)
+ bool result = false;
+
+ if (is_union)
{
- if (cinfo.switch_source)
+ #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
+ is_touching = cinfo.open_count > 1;
+ if (is_touching)
{
- is_touching = false;
- std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl;
+ if (cinfo.switch_source)
+ {
+ is_touching = false;
+ std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl;
+ }
+ else
+ {
+ std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl;
+ }
}
- else
+ #else
+ is_touching = cinfo.open_count > 1 && ! cinfo.switch_source;
+ #endif
+
+ if (is_touching)
{
- std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl;
+ sbs.reverse();
}
+
+ result = select_from_cluster_union(turn_index, op_index, start_turn_index, sbs,
+ is_touching);
}
-#else
- is_touching = is_union && cinfo.open_count > 1 && ! cinfo.switch_source;
-#endif
- if (is_touching)
+ else
{
- sbs.reverse();
+ if (is_start
+ && turn.both(operation_intersection)
+ && turn.operations[op_index].enriched.only_turn_on_ring)
+ {
+ // For an ii (usually interior ring), only turn on ring,
+ // reverse to take first exit
+ sbs.reverse();
+ }
+
+ result = analyze_cluster_intersection(turn_index, op_index, sbs);
}
+ return result;
+ }
- return select_from_cluster(turn_index, op_index, start_turn_index, sbs,
- is_touching);
+ inline bool analyze_ii_intersection(signed_size_type& turn_index, int& op_index,
+ turn_type const& current_turn,
+ segment_identifier const& previous_seg_id)
+ {
+ sbs_type sbs;
+
+ // Add this turn to the sort-by-side sorter
+ bool has_origin = false;
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type const& op = current_turn.operations[i];
+ bool const is_origin = op.seg_id.source_index
+ == previous_seg_id.source_index;
+ has_origin = has_origin || is_origin;
+ sbs.add(op, turn_index, i, m_geometry1, m_geometry2, is_origin);
+ }
+
+ if (! has_origin)
+ {
+ return false;
+ }
+
+ sbs.apply(current_turn.point);
+ return analyze_cluster_intersection(turn_index, op_index, sbs);
}
inline void change_index_for_self_turn(signed_size_type& to_vertex_index,
@@ -607,7 +709,7 @@ struct traversal
return true;
}
- bool select_turn(signed_size_type start_turn_index,
+ bool select_turn(signed_size_type start_turn_index, int start_op_index,
signed_size_type& turn_index,
int& op_index,
bool& is_touching,
@@ -616,10 +718,37 @@ struct traversal
segment_identifier const& previous_seg_id,
bool is_start)
{
- if (m_turns[turn_index].cluster_id >= 0)
+ turn_type const& current_turn = m_turns[turn_index];
+
+ if (target_operation == operation_intersection)
+ {
+ bool const back_at_start_cluster
+ = current_turn.cluster_id >= 0
+ && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
+
+ if (turn_index == start_turn_index || back_at_start_cluster)
+ {
+ // Intersection can always be finished if returning
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
+ }
+
+ if (current_turn.cluster_id < 0
+ && current_turn.both(operation_intersection))
+ {
+ if (analyze_ii_intersection(turn_index, op_index, current_turn,
+ previous_seg_id))
+ {
+ return true;
+ }
+ }
+ }
+
+ if (current_turn.cluster_id >= 0)
{
if (! select_turn_from_cluster(turn_index, op_index, is_touching,
- start_turn_index, previous_seg_id))
+ start_turn_index, previous_seg_id, is_start))
{
return false;
}
@@ -631,8 +760,6 @@ struct traversal
}
else
{
- turn_type const& current_turn = m_turns[turn_index];
-
op_index = starting_operation_index(current_turn);
if (op_index == -1)
{
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
index 104bd6b8e7..e0dfee19a8 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
@@ -64,9 +64,7 @@ struct traversal_ring_creator
, m_clusters(clusters)
, m_robust_policy(robust_policy)
, m_visitor(visitor)
- , m_has_uu(false)
{
-
}
template <typename Ring>
@@ -123,7 +121,8 @@ struct traversal_ring_creator
}
bool is_touching = false;
- if (! m_trav.select_turn(start_turn_index, turn_index, op_index,
+ if (! m_trav.select_turn(start_turn_index, start_op_index,
+ turn_index, op_index,
is_touching,
previous_op_index, previous_turn_index, previous_seg_id,
is_start))
@@ -189,6 +188,18 @@ struct traversal_ring_creator
return traverse_error_none;
}
+ if (start_turn.cluster_id >= 0)
+ {
+ turn_type const& turn = m_turns[current_turn_index];
+ if (turn.cluster_id == start_turn.cluster_id)
+ {
+ turn_operation_type& op = m_turns[start_turn_index].operations[current_op_index];
+ op.visited.set_finished();
+ m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish (cluster)");
+ return traverse_error_none;
+ }
+ }
+
std::size_t const max_iterations = 2 + 2 * m_turns.size();
for (std::size_t i = 0; i <= max_iterations; i++)
{
@@ -276,49 +287,21 @@ struct traversal_ring_creator
template <typename Rings>
void iterate(Rings& rings, std::size_t& finalized_ring_size,
- typename Backtrack::state_type& state,
- int pass)
+ typename Backtrack::state_type& state)
{
- if (pass == 1)
- {
- if (target_operation == operation_intersection)
- {
- // Second pass currently only used for uu
- return;
- }
- if (! m_has_uu)
- {
- // There is no uu found in first pass
- return;
- }
- }
-
- // Iterate through all unvisited points
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
- turn_type const& start_turn = m_turns[turn_index];
+ turn_type const& turn = m_turns[turn_index];
- if (start_turn.discarded || start_turn.blocked())
+ if (turn.discarded || turn.blocked())
{
// Skip discarded and blocked turns
continue;
}
- if (target_operation == operation_union)
- {
- if (start_turn.both(operation_union))
- {
- // Start with a uu-turn only in the second pass
- m_has_uu = true;
- if (pass == 0)
- {
- continue;
- }
- }
- }
for (int op_index = 0; op_index < 2; op_index++)
{
- traverse_with_operation(start_turn, turn_index, op_index,
+ traverse_with_operation(turn, turn_index, op_index,
rings, finalized_ring_size, state);
}
}
@@ -333,10 +316,6 @@ private:
Clusters const& m_clusters;
RobustPolicy const& m_robust_policy;
Visitor& m_visitor;
-
- // Next member is only used for operation union
- bool m_has_uu;
-
};
}} // namespace detail::overlay
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
index 9381c66e0e..183131c74b 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
@@ -71,8 +71,8 @@ struct traversal_switch_detector
{
if (turn.cluster_id == -1)
{
- // If it is a uu-turn (non clustered), it is never same zone
- return ! turn.both(operation_union);
+ // If it is a uu/ii-turn (non clustered), it is never same zone
+ return ! (turn.both(operation_union) || turn.both(operation_intersection));
}
// It is a cluster, check zones of both operations
@@ -110,11 +110,11 @@ struct traversal_switch_detector
for (set_iterator sit = ring_turn_indices.begin();
sit != ring_turn_indices.end(); ++sit)
{
- int const turn_index = *sit;
+ signed_size_type const turn_index = *sit;
turn_type const& turn = m_turns[turn_index];
if (! connects_same_zone(turn))
{
- // This is a non clustered uu-turn, or a cluster connecting different 'zones'
+ // This is a non clustered uu/ii-turn, or a cluster connecting different 'zones'
continue;
}
@@ -132,6 +132,56 @@ struct traversal_switch_detector
}
}
+ void check_turns_per_ring(ring_identifier const& ring_id,
+ std::set<signed_size_type> const& ring_turn_indices)
+ {
+ bool only_turn_on_ring = true;
+ if (ring_turn_indices.size() > 1)
+ {
+ // More turns on this ring. Only leave only_turn_on_ring true
+ // if they are all of the same cluster
+ int cluster_id = -1;
+ for (set_iterator sit = ring_turn_indices.begin();
+ sit != ring_turn_indices.end(); ++sit)
+ {
+ turn_type const& turn = m_turns[*sit];
+ if (turn.cluster_id == -1)
+ {
+ // Unclustered turn - and there are 2 or more turns
+ // so the ring has different turns
+ only_turn_on_ring = false;
+ break;
+ }
+
+ // Clustered turn, check if it is the first or same as previous
+ if (cluster_id == -1)
+ {
+ cluster_id = turn.cluster_id;
+ }
+ else if (turn.cluster_id != cluster_id)
+ {
+ only_turn_on_ring = false;
+ break;
+ }
+ }
+ }
+
+ // Assign result to matching operation (a turn is always on two rings)
+ for (set_iterator sit = ring_turn_indices.begin();
+ sit != ring_turn_indices.end(); ++sit)
+ {
+ turn_type& turn = m_turns[*sit];
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type& op = turn.operations[i];
+ if (ring_id_by_seg_id(op.seg_id) == ring_id)
+ {
+ op.enriched.only_turn_on_ring = only_turn_on_ring;
+ }
+ }
+ }
+ }
+
void propagate_region(ring_identifier const& ring_id, int region_id)
{
std::map<ring_identifier, std::set<signed_size_type> >::const_iterator it = m_turns_per_ring.find(ring_id);
@@ -168,6 +218,7 @@ struct traversal_switch_detector
= m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)
{
create_region(it->first, it->second);
+ check_turns_per_ring(it->first, it->second);
}
// Now that all regions are filled, assign switch_source property
@@ -204,7 +255,7 @@ struct traversal_switch_detector
cinfo.switch_source = regions.size() == 1;
}
- // Iterate through all uu turns (non-clustered)
+ // Iterate through all uu/ii turns (non-clustered)
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
turn_type& turn = m_turns[turn_index];
@@ -212,9 +263,9 @@ struct traversal_switch_detector
if (turn.discarded
|| turn.blocked()
|| turn.cluster_id >= 0
- || ! turn.both(operation_union))
+ || ! (turn.both(operation_union) || turn.both(operation_intersection)))
{
- // Skip discarded, blocked, non-uu and clustered turns
+ // Skip discarded, blocked, non-uu/ii and clustered turns
continue;
}
@@ -242,9 +293,10 @@ struct traversal_switch_detector
{
turn_type const& turn = m_turns[turn_index];
- if (turn.both(operation_union) && turn.cluster_id < 0)
+ if ((turn.both(operation_union) || turn.both(operation_intersection))
+ && turn.cluster_id < 0)
{
- std::cout << "UU SWITCH RESULT "
+ std::cout << "UU/II SWITCH RESULT "
<< turn_index << " -> "
<< turn.switch_source << std::endl;
}
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index 2d2933ebdd..f01e50eb03 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -97,10 +97,7 @@ public :
typename Backtrack::state_type state;
- for (int pass = 0; pass < 2; pass++)
- {
- trav.iterate(rings, finalized_ring_size, state, pass);
- }
+ trav.iterate(rings, finalized_ring_size, state);
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index 73f266a04a..e09af126c6 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -13,6 +13,7 @@
#include <boost/array.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
@@ -88,7 +89,7 @@ struct turn_info
Point point;
method_type method;
- int cluster_id;
+ signed_size_type cluster_id; // For multiple turns on same location, >= 0. Else -1
bool discarded;
bool colocated;
bool switch_source; // For u/u turns which can either switch or not
diff --git a/boost/geometry/algorithms/detail/result_inverse.hpp b/boost/geometry/algorithms/detail/result_inverse.hpp
deleted file mode 100644
index 01a1997e49..0000000000
--- a/boost/geometry/algorithms/detail/result_inverse.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Boost.Geometry
-
-// Copyright (c) 2015 Oracle and/or its affiliates.
-
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
-
-
-#include <boost/math/constants/constants.hpp>
-
-#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/core/srs.hpp>
-
-#include <boost/geometry/util/math.hpp>
-
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
-
-namespace boost { namespace geometry { namespace detail
-{
-
-template <typename T>
-struct result_inverse
-{
- void set(T const& d, T const& a)
- {
- distance = d;
- azimuth = a;
- }
-
- T distance;
- T azimuth;
-};
-
-}}} // namespace boost::geometry::detail
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/thomas_inverse.hpp b/boost/geometry/algorithms/detail/thomas_inverse.hpp
deleted file mode 100644
index 96b237e054..0000000000
--- a/boost/geometry/algorithms/detail/thomas_inverse.hpp
+++ /dev/null
@@ -1,191 +0,0 @@
-// Boost.Geometry
-
-// Copyright (c) 2015 Oracle and/or its affiliates.
-
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
-
-
-#include <boost/math/constants/constants.hpp>
-
-#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/core/srs.hpp>
-
-#include <boost/geometry/util/condition.hpp>
-#include <boost/geometry/util/math.hpp>
-
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-#include <boost/geometry/algorithms/detail/result_inverse.hpp>
-
-namespace boost { namespace geometry { namespace detail
-{
-
-/*!
-\brief The solution of the inverse problem of geodesics on latlong coordinates,
- Forsyth-Andoyer-Lambert type approximation with second order terms.
-\author See
- - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
- http://www.dtic.mil/docs/citations/AD0627893
- - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
- http://www.dtic.mil/docs/citations/AD703541
-*/
-template <typename CT, bool EnableDistance, bool EnableAzimuth>
-struct thomas_inverse
-{
- typedef result_inverse<CT> result_type;
-
- template <typename T1, typename T2, typename Spheroid>
- static inline result_type apply(T1 const& lon1,
- T1 const& lat1,
- T2 const& lon2,
- T2 const& lat2,
- Spheroid const& spheroid)
- {
- result_type result;
-
- // coordinates in radians
-
- if ( math::equals(lon1, lon2)
- && math::equals(lat1, lat2) )
- {
- result.set(CT(0), CT(0));
- return result;
- }
-
- CT const f = detail::flattening<CT>(spheroid);
- CT const one_minus_f = CT(1) - f;
-
-// CT const tan_theta1 = one_minus_f * tan(lat1);
-// CT const tan_theta2 = one_minus_f * tan(lat2);
-// CT const theta1 = atan(tan_theta1);
-// CT const theta2 = atan(tan_theta2);
-
- CT const pi_half = math::pi<CT>() / CT(2);
- CT const theta1 = math::equals(lat1, pi_half) ? lat1 :
- math::equals(lat1, -pi_half) ? lat1 :
- atan(one_minus_f * tan(lat1));
- CT const theta2 = math::equals(lat2, pi_half) ? lat2 :
- math::equals(lat2, -pi_half) ? lat2 :
- atan(one_minus_f * tan(lat2));
-
- CT const theta_m = (theta1 + theta2) / CT(2);
- CT const d_theta_m = (theta2 - theta1) / CT(2);
- CT const d_lambda = lon2 - lon1;
- CT const d_lambda_m = d_lambda / CT(2);
-
- CT const sin_theta_m = sin(theta_m);
- CT const cos_theta_m = cos(theta_m);
- CT const sin_d_theta_m = sin(d_theta_m);
- CT const cos_d_theta_m = cos(d_theta_m);
- CT const sin2_theta_m = math::sqr(sin_theta_m);
- CT const cos2_theta_m = math::sqr(cos_theta_m);
- CT const sin2_d_theta_m = math::sqr(sin_d_theta_m);
- CT const cos2_d_theta_m = math::sqr(cos_d_theta_m);
- CT const sin_d_lambda_m = sin(d_lambda_m);
- CT const sin2_d_lambda_m = math::sqr(sin_d_lambda_m);
-
- CT const H = cos2_theta_m - sin2_d_theta_m;
- CT const L = sin2_d_theta_m + H * sin2_d_lambda_m;
- CT const cos_d = CT(1) - CT(2) * L;
- CT const d = acos(cos_d);
- CT const sin_d = sin(d);
-
- CT const one_minus_L = CT(1) - L;
-
- if ( math::equals(sin_d, CT(0))
- || math::equals(L, CT(0))
- || math::equals(one_minus_L, CT(0)) )
- {
- result.set(CT(0), CT(0));
- return result;
- }
-
- CT const U = CT(2) * sin2_theta_m * cos2_d_theta_m / one_minus_L;
- CT const V = CT(2) * sin2_d_theta_m * cos2_theta_m / L;
- CT const X = U + V;
- CT const Y = U - V;
- CT const T = d / sin_d;
- //CT const D = CT(4) * math::sqr(T);
- //CT const E = CT(2) * cos_d;
- //CT const A = D * E;
- //CT const B = CT(2) * D;
- //CT const C = T - (A - E) / CT(2);
-
- if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
- {
- //CT const n1 = X * (A + C*X);
- //CT const n2 = Y * (B + E*Y);
- //CT const n3 = D*X*Y;
-
- //CT const f_sqr = math::sqr(f);
- //CT const f_sqr_per_64 = f_sqr / CT(64);
-
- CT const delta1d = f * (T*X-Y) / CT(4);
- //CT const delta2d = f_sqr_per_64 * (n1 - n2 + n3);
-
- CT const a = get_radius<0>(spheroid);
-
- result.distance = a * sin_d * (T - delta1d);
- //double S2 = a * sin_d * (T - delta1d + delta2d);
- }
- else
- {
- result.distance = CT(0);
- }
-
- if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
- {
- // NOTE: if both cos_latX == 0 then below we'd have 0 * INF
- // it's a situation when the endpoints are on the poles +-90 deg
- // in this case the azimuth could either be 0 or +-pi
- // but above always 0 is returned
-
- // may also be used to calculate distance21
- //CT const D = CT(4) * math::sqr(T);
- CT const E = CT(2) * cos_d;
- //CT const A = D * E;
- //CT const B = CT(2) * D;
- // may also be used to calculate distance21
- CT const f_sqr = math::sqr(f);
- CT const f_sqr_per_64 = f_sqr / CT(64);
-
- CT const F = CT(2)*Y-E*(CT(4)-X);
- //CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+CT(4))*Y;
- CT const G = f*T/CT(2) + f_sqr_per_64;
- CT const tan_d_lambda = tan(d_lambda);
- CT const Q = -(F*G*tan_d_lambda) / CT(4);
-
- CT const d_lambda_p = (d_lambda + Q) / CT(2);
- CT const tan_d_lambda_p = tan(d_lambda_p);
-
- CT const v = atan2(cos_d_theta_m, sin_theta_m * tan_d_lambda_p);
- CT const u = atan2(-sin_d_theta_m, cos_theta_m * tan_d_lambda_p);
-
- CT const pi = math::pi<CT>();
- CT alpha1 = v + u;
- if ( alpha1 > pi )
- {
- alpha1 -= CT(2) * pi;
- }
-
- result.azimuth = alpha1;
- }
- else
- {
- result.azimuth = CT(0);
- }
-
- return result;
- }
-};
-
-}}} // namespace boost::geometry::detail
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
diff --git a/boost/geometry/extensions/algorithms/inverse.hpp b/boost/geometry/extensions/algorithms/inverse.hpp
deleted file mode 100644
index 44f415be42..0000000000
--- a/boost/geometry/extensions/algorithms/inverse.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-//
-// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP
-
-#include <boost/geometry.hpp>
-
-namespace boost { namespace geometry
-{
-
-// TODO: this is shared with sectionalize, move to somewhere else (assign?)
-template <typename Box, typename Value>
-inline void enlarge_box(Box& box, Value value)
-{
- geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value);
- geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value);
- geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value);
- geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value);
-}
-
-// TODO: when this might be moved outside extensions it should of course
-// input/output a Geometry, instead of a WKT
-template <typename Geometry, typename Value>
-inline std::string inverse(std::string const& wkt, Value margin)
-{
- Geometry geometry;
- read_wkt(wkt, geometry);
-
- geometry::correct(geometry);
-
- geometry::model::box<typename point_type<Geometry>::type> env;
- geometry::envelope(geometry, env);
-
- // Make its envelope a bit larger
- enlarge_box(env, margin);
-
- Geometry env_as_polygon;
- geometry::convert(env, env_as_polygon);
-
- Geometry inversed_result;
- geometry::difference(env_as_polygon, geometry, inversed_result);
-
- std::ostringstream out;
-
- out << geometry::wkt(inversed_result);
- return out.str();
-}
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/andoyer_inverse.hpp b/boost/geometry/formulas/andoyer_inverse.hpp
index 66ad6446e9..57b5ab5384 100644
--- a/boost/geometry/algorithms/detail/andoyer_inverse.hpp
+++ b/boost/geometry/formulas/andoyer_inverse.hpp
@@ -8,8 +8,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
+#ifndef BOOST_GEOMETRY_FORMULAS_ANDOYER_INVERSE_HPP
+#define BOOST_GEOMETRY_FORMULAS_ANDOYER_INVERSE_HPP
#include <boost/math/constants/constants.hpp>
@@ -21,10 +21,12 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
-#include <boost/geometry/algorithms/detail/result_inverse.hpp>
+#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/result_inverse.hpp>
-namespace boost { namespace geometry { namespace detail
+
+namespace boost { namespace geometry { namespace formula
{
/*!
@@ -36,10 +38,22 @@ namespace boost { namespace geometry { namespace detail
- Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
http://www.dtic.mil/docs/citations/AD703541
*/
-
-template <typename CT, bool EnableDistance, bool EnableAzimuth>
-struct andoyer_inverse
+template <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+>
+class andoyer_inverse
{
+ static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
+ static const bool CalcAzimuths = EnableAzimuth || EnableReverseAzimuth || CalcQuantities;
+ static const bool CalcFwdAzimuth = EnableAzimuth || CalcQuantities;
+ static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities;
+
+public:
typedef result_inverse<CT> result_type;
template <typename T1, typename T2, typename Spheroid>
@@ -49,20 +63,20 @@ struct andoyer_inverse
T2 const& lat2,
Spheroid const& spheroid)
{
- CT const c0 = CT(0);
- CT const c1 = CT(1);
- CT const pi = math::pi<CT>();
-
result_type result;
// coordinates in radians
if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) )
{
- result.set(c0, c0);
return result;
}
+ CT const c0 = CT(0);
+ CT const c1 = CT(1);
+ CT const pi = math::pi<CT>();
+ CT const f = detail::flattening<CT>(spheroid);
+
CT const dlon = lon2 - lon1;
CT const sin_dlon = sin(dlon);
CT const cos_dlon = cos(dlon);
@@ -84,8 +98,6 @@ struct andoyer_inverse
CT const d = acos(cos_d); // [0, pi]
CT const sin_d = sin(d); // [-1, 1]
- CT const f = detail::flattening<CT>(spheroid);
-
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
CT const K = math::sqr(sin_lat1-sin_lat2);
@@ -109,12 +121,8 @@ struct andoyer_inverse
result.distance = a * (d + dd);
}
- else
- {
- result.distance = c0;
- }
- if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
+ if ( BOOST_GEOMETRY_CONDITION(CalcAzimuths) )
{
// sin_d = 0 <=> antipodal points
if (math::equals(sin_d, c0))
@@ -122,10 +130,7 @@ struct andoyer_inverse
// T = inf
// dA = inf
// azimuth = -inf
- if (lat1 <= lat2)
- result.azimuth = c0;
- else
- result.azimuth = pi;
+ result.azimuth = lat1 <= lat2 ? c0 : pi;
}
else
{
@@ -142,64 +147,101 @@ struct andoyer_inverse
U = (f/ c2)*math::sqr(cos_lat1)*sin_2A;
}
+ CT B = c0;
CT V = c0;
if ( ! math::equals(cos_lat1, c0) )
{
CT const tan_lat1 = sin_lat1/cos_lat1;
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
- CT const B = atan2(sin_dlon, N);
+ B = atan2(sin_dlon, N);
CT const sin_2B = sin(c2*B);
V = (f/ c2)*math::sqr(cos_lat2)*sin_2B;
}
CT const T = d / sin_d;
- CT const dA = V*T-U;
-
- result.azimuth = A - dA;
// even with sin_d == 0 checked above if the second point
// is somewhere in the antipodal area T may still be great
- // therefore dA may be great and the resulting azimuth
- // may be some more or less arbitrary angle
- if (A >= c0) // A indicates Eastern hemisphere
+ // therefore dA and dB may be great and the resulting azimuths
+ // may be some more or less arbitrary angles
+
+ if (BOOST_GEOMETRY_CONDITION(CalcFwdAzimuth))
{
- if (dA >= c0) // A altered towards 0
- {
- if ((result.azimuth) < c0)
- result.azimuth = c0;
- }
- else // dA < 0, A altered towards pi
- {
- if (result.azimuth > pi)
- result.azimuth = pi;
- }
+ CT const dA = V*T - U;
+ result.azimuth = A - dA;
+ normalize_azimuth(result.azimuth, A, dA);
}
- else // A indicates Western hemisphere
+
+ if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth))
{
- if (dA <= c0) // A altered towards 0
- {
- if (result.azimuth > c0)
- result.azimuth = c0;
- }
- else // dA > 0, A altered towards -pi
+ CT const dB = -U*T + V;
+ result.reverse_azimuth = pi - B - dB;
+ if (result.reverse_azimuth > pi)
{
- CT const minus_pi = -pi;
- if ((result.azimuth) < minus_pi)
- result.azimuth = minus_pi;
+ result.reverse_azimuth -= 2 * pi;
}
+ normalize_azimuth(result.reverse_azimuth, B, dB);
}
}
}
- else
+
+ if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
{
- result.azimuth = c0;
+ typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 1> quantities;
+ quantities::apply(dlon, sin_lat1, cos_lat1, sin_lat2, cos_lat2,
+ result.azimuth, result.reverse_azimuth,
+ get_radius<2>(spheroid), f,
+ result.reduced_length, result.geodesic_scale);
}
return result;
}
+
+private:
+ static inline void normalize_azimuth(CT & azimuth, CT const& A, CT const& dA)
+ {
+ CT const c0 = 0;
+
+ if (A >= c0) // A indicates Eastern hemisphere
+ {
+ if (dA >= c0) // A altered towards 0
+ {
+ if (azimuth < c0)
+ {
+ azimuth = c0;
+ }
+ }
+ else // dA < 0, A altered towards pi
+ {
+ CT const pi = math::pi<CT>();
+ if (azimuth > pi)
+ {
+ azimuth = pi;
+ }
+ }
+ }
+ else // A indicates Western hemisphere
+ {
+ if (dA <= c0) // A altered towards 0
+ {
+ if (azimuth > c0)
+ {
+ azimuth = c0;
+ }
+ }
+ else // dA > 0, A altered towards -pi
+ {
+ CT const minus_pi = -math::pi<CT>();
+ if (azimuth < minus_pi)
+ {
+ azimuth = minus_pi;
+ }
+ }
+ }
+ }
};
-}}} // namespace boost::geometry::detail
+}}} // namespace boost::geometry::formula
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
+#endif // BOOST_GEOMETRY_FORMULAS_ANDOYER_INVERSE_HPP
diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp
new file mode 100644
index 0000000000..9a92f14e18
--- /dev/null
+++ b/boost/geometry/formulas/differential_quantities.hpp
@@ -0,0 +1,300 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP
+#define BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP
+
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief The solution of a part of the inverse problem - differential quantities.
+\author See
+- Charles F.F Karney, Algorithms for geodesics, 2011
+https://arxiv.org/pdf/1109.4448.pdf
+*/
+template <
+ typename CT,
+ bool EnableReducedLength,
+ bool EnableGeodesicScale,
+ unsigned int Order = 2,
+ bool ApproxF = true
+>
+class differential_quantities
+{
+public:
+ static inline void apply(CT const& lon1, CT const& lat1,
+ CT const& lon2, CT const& lat2,
+ CT const& azimuth, CT const& reverse_azimuth,
+ CT const& b, CT const& f,
+ CT & reduced_length, CT & geodesic_scale)
+ {
+ CT const dlon = lon2 - lon1;
+ CT const sin_lat1 = sin(lat1);
+ CT const cos_lat1 = cos(lat1);
+ CT const sin_lat2 = sin(lat2);
+ CT const cos_lat2 = cos(lat2);
+
+ apply(dlon, sin_lat1, cos_lat1, sin_lat2, cos_lat2,
+ azimuth, reverse_azimuth,
+ b, f,
+ reduced_length, geodesic_scale);
+ }
+
+ static inline void apply(CT const& dlon,
+ CT const& sin_lat1, CT const& cos_lat1,
+ CT const& sin_lat2, CT const& cos_lat2,
+ CT const& azimuth, CT const& reverse_azimuth,
+ CT const& b, CT const& f,
+ CT & reduced_length, CT & geodesic_scale)
+ {
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const one_minus_f = c1 - f;
+
+ CT const sin_bet1 = one_minus_f * sin_lat1;
+ CT const sin_bet2 = one_minus_f * sin_lat2;
+
+ // equator
+ if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0))
+ {
+ CT const sig_12 = math::abs(dlon) / one_minus_f;
+ if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
+ {
+ CT m12 = sin(sig_12) * b;
+ reduced_length = m12;
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale))
+ {
+ CT M12 = cos(sig_12);
+ geodesic_scale = M12;
+ }
+ }
+ else
+ {
+ CT const c2 = 2;
+ CT const e2 = f * (c2 - f);
+ CT const ep2 = e2 / math::sqr(one_minus_f);
+
+ CT const cos_bet1 = cos_lat1;
+ CT const cos_bet2 = cos_lat2;
+
+ CT const sin_alp1 = sin(azimuth);
+ CT const cos_alp1 = cos(azimuth);
+ //CT const sin_alp2 = sin(reverse_azimuth);
+ CT const cos_alp2 = cos(reverse_azimuth);
+
+ CT sin_sig1 = sin_bet1;
+ CT cos_sig1 = cos_alp1 * cos_bet1;
+ CT sin_sig2 = sin_bet2;
+ CT cos_sig2 = cos_alp2 * cos_bet2;
+
+ normalize(sin_sig1, cos_sig1);
+ normalize(sin_sig2, cos_sig2);
+
+ CT const sin_alp0 = sin_alp1 * cos_bet1;
+ CT const cos_alp0_sqr = c1 - math::sqr(sin_alp0);
+
+ CT const J12 = BOOST_GEOMETRY_CONDITION(ApproxF) ?
+ J12_f(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f) :
+ J12_ep_sqr(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, ep2) ;
+
+ CT const dn1 = math::sqrt(c1 + e2 * math::sqr(sin_lat1));
+ CT const dn2 = math::sqrt(c1 + e2 * math::sqr(sin_lat2));
+
+ if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
+ {
+ CT const m12_b = dn2 * (cos_sig1 * sin_sig2)
+ - dn1 * (sin_sig1 * cos_sig2)
+ - cos_sig1 * cos_sig2 * J12;
+ CT const m12 = m12_b * b;
+
+ reduced_length = m12;
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale))
+ {
+ CT const cos_sig12 = cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2;
+ CT const t = ep2 * (cos_bet1 - cos_bet2) * (cos_bet1 + cos_bet2) / (dn1 + dn2);
+ CT const M12 = cos_sig12 + (t * sin_sig2 - cos_sig2 * J12) * sin_sig1 / dn1;
+
+ geodesic_scale = M12;
+ }
+ }
+ }
+
+private:
+ /*! Approximation of J12, expanded into taylor series in f
+ Maxima script:
+ ep2: f * (2-f) / ((1-f)^2);
+ k2: ca02 * ep2;
+ assume(f < 1);
+ assume(sig > 0);
+ I1(sig):= integrate(sqrt(1 + k2 * sin(s)^2), s, 0, sig);
+ I2(sig):= integrate(1/sqrt(1 + k2 * sin(s)^2), s, 0, sig);
+ J(sig):= I1(sig) - I2(sig);
+ S: taylor(J(sig), f, 0, 3);
+ S1: factor( 2*integrate(sin(s)^2,s,0,sig)*ca02*f );
+ S2: factor( ((integrate(-6*ca02^2*sin(s)^4+6*ca02*sin(s)^2,s,0,sig)+integrate(-2*ca02^2*sin(s)^4+6*ca02*sin(s)^2,s,0,sig))*f^2)/4 );
+ S3: factor( ((integrate(30*ca02^3*sin(s)^6-54*ca02^2*sin(s)^4+24*ca02*sin(s)^2,s,0,sig)+integrate(6*ca02^3*sin(s)^6-18*ca02^2*sin(s)^4+24*ca02*sin(s)^2,s,0,sig))*f^3)/12 );
+ */
+ static inline CT J12_f(CT const& sin_sig1, CT const& cos_sig1,
+ CT const& sin_sig2, CT const& cos_sig2,
+ CT const& cos_alp0_sqr, CT const& f)
+ {
+ if (Order == 0)
+ {
+ return 0;
+ }
+
+ CT const c2 = 2;
+
+ CT const sig_12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2,
+ cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2);
+ CT const sin_2sig1 = c2 * cos_sig1 * sin_sig1; // sin(2sig1)
+ CT const sin_2sig2 = c2 * cos_sig2 * sin_sig2; // sin(2sig2)
+ CT const sin_2sig_12 = sin_2sig2 - sin_2sig1;
+ CT const L1 = sig_12 - sin_2sig_12 / c2;
+
+ if (Order == 1)
+ {
+ return cos_alp0_sqr * f * L1;
+ }
+
+ CT const sin_4sig1 = c2 * sin_2sig1 * (math::sqr(cos_sig1) - math::sqr(sin_sig1)); // sin(4sig1)
+ CT const sin_4sig2 = c2 * sin_2sig2 * (math::sqr(cos_sig2) - math::sqr(sin_sig2)); // sin(4sig2)
+ CT const sin_4sig_12 = sin_4sig2 - sin_4sig1;
+
+ CT const c8 = 8;
+ CT const c12 = 12;
+ CT const c16 = 16;
+ CT const c24 = 24;
+
+ CT const L2 = -( cos_alp0_sqr * sin_4sig_12
+ + (-c8 * cos_alp0_sqr + c12) * sin_2sig_12
+ + (c12 * cos_alp0_sqr - c24) * sig_12)
+ / c16;
+
+ if (Order == 2)
+ {
+ return cos_alp0_sqr * f * (L1 + f * L2);
+ }
+
+ CT const c4 = 4;
+ CT const c9 = 9;
+ CT const c48 = 48;
+ CT const c60 = 60;
+ CT const c64 = 64;
+ CT const c96 = 96;
+ CT const c128 = 128;
+ CT const c144 = 144;
+
+ CT const cos_alp0_quad = math::sqr(cos_alp0_sqr);
+ CT const sin3_2sig1 = math::sqr(sin_2sig1) * sin_2sig1;
+ CT const sin3_2sig2 = math::sqr(sin_2sig2) * sin_2sig2;
+ CT const sin3_2sig_12 = sin3_2sig2 - sin3_2sig1;
+
+ CT const A = (c9 * cos_alp0_quad - c12 * cos_alp0_sqr) * sin_4sig_12;
+ CT const B = c4 * cos_alp0_quad * sin3_2sig_12;
+ CT const C = (-c48 * cos_alp0_quad + c96 * cos_alp0_sqr - c64) * sin_2sig_12;
+ CT const D = (c60 * cos_alp0_quad - c144 * cos_alp0_sqr + c128) * sig_12;
+
+ CT const L3 = (A + B + C + D) / c64;
+
+ // Order 3 and higher
+ return cos_alp0_sqr * f * (L1 + f * (L2 + f * L3));
+ }
+
+ /*! Approximation of J12, expanded into taylor series in e'^2
+ Maxima script:
+ k2: ca02 * ep2;
+ assume(sig > 0);
+ I1(sig):= integrate(sqrt(1 + k2 * sin(s)^2), s, 0, sig);
+ I2(sig):= integrate(1/sqrt(1 + k2 * sin(s)^2), s, 0, sig);
+ J(sig):= I1(sig) - I2(sig);
+ S: taylor(J(sig), ep2, 0, 3);
+ S1: factor( integrate(sin(s)^2,s,0,sig)*ca02*ep2 );
+ S2: factor( (integrate(sin(s)^4,s,0,sig)*ca02^2*ep2^2)/2 );
+ S3: factor( (3*integrate(sin(s)^6,s,0,sig)*ca02^3*ep2^3)/8 );
+ */
+ static inline CT J12_ep_sqr(CT const& sin_sig1, CT const& cos_sig1,
+ CT const& sin_sig2, CT const& cos_sig2,
+ CT const& cos_alp0_sqr, CT const& ep_sqr)
+ {
+ if (Order == 0)
+ {
+ return 0;
+ }
+
+ CT const c2 = 2;
+ CT const c4 = 4;
+
+ CT const c2a0ep2 = cos_alp0_sqr * ep_sqr;
+
+ CT const sig_12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2,
+ cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2); // sig2 - sig1
+ CT const sin_2sig1 = c2 * cos_sig1 * sin_sig1; // sin(2sig1)
+ CT const sin_2sig2 = c2 * cos_sig2 * sin_sig2; // sin(2sig2)
+ CT const sin_2sig_12 = sin_2sig2 - sin_2sig1;
+
+ CT const L1 = (c2 * sig_12 - sin_2sig_12) / c4;
+
+ if (Order == 1)
+ {
+ return c2a0ep2 * L1;
+ }
+
+ CT const c8 = 8;
+ CT const c64 = 64;
+
+ CT const sin_4sig1 = c2 * sin_2sig1 * (math::sqr(cos_sig1) - math::sqr(sin_sig1)); // sin(4sig1)
+ CT const sin_4sig2 = c2 * sin_2sig2 * (math::sqr(cos_sig2) - math::sqr(sin_sig2)); // sin(4sig2)
+ CT const sin_4sig_12 = sin_4sig2 - sin_4sig1;
+
+ CT const L2 = (sin_4sig_12 - c8 * sin_2sig_12 + 12 * sig_12) / c64;
+
+ if (Order == 2)
+ {
+ return c2a0ep2 * (L1 + c2a0ep2 * L2);
+ }
+
+ CT const sin3_2sig1 = math::sqr(sin_2sig1) * sin_2sig1;
+ CT const sin3_2sig2 = math::sqr(sin_2sig2) * sin_2sig2;
+ CT const sin3_2sig_12 = sin3_2sig2 - sin3_2sig1;
+
+ CT const c9 = 9;
+ CT const c48 = 48;
+ CT const c60 = 60;
+ CT const c512 = 512;
+
+ CT const L3 = (c9 * sin_4sig_12 + c4 * sin3_2sig_12 - c48 * sin_2sig_12 + c60 * sig_12) / c512;
+
+ // Order 3 and higher
+ return c2a0ep2 * (L1 + c2a0ep2 * (L2 + c2a0ep2 * L3));
+ }
+
+ static inline void normalize(CT & x, CT & y)
+ {
+ CT const len = math::sqrt(math::sqr(x) + math::sqr(y));
+ x /= len;
+ y /= len;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP
diff --git a/boost/geometry/formulas/gnomonic_intersection.hpp b/boost/geometry/formulas/gnomonic_intersection.hpp
new file mode 100644
index 0000000000..7e1b7bcdab
--- /dev/null
+++ b/boost/geometry/formulas/gnomonic_intersection.hpp
@@ -0,0 +1,148 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP
+#define BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+
+#include <boost/geometry/arithmetic/cross_product.hpp>
+#include <boost/geometry/formulas/gnomonic_spheroid.hpp>
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief The intersection of two geodesics using spheroidal gnomonic projection
+ as proposed by Karney.
+\author See
+ - Charles F.F Karney, Algorithms for geodesics, 2011
+ https://arxiv.org/pdf/1109.4448.pdf
+ - GeographicLib forum thread: Intersection between two geodesic lines
+ https://sourceforge.net/p/geographiclib/discussion/1026621/thread/21aaff9f/
+*/
+template
+<
+ typename CT,
+ template <typename, bool, bool, bool, bool, bool> class Inverse,
+ template <typename, bool, bool, bool, bool> class Direct
+>
+class gnomonic_intersection
+{
+public:
+ template <typename T1, typename T2, typename Spheroid>
+ static inline bool apply(T1 const& lona1, T1 const& lata1,
+ T1 const& lona2, T1 const& lata2,
+ T2 const& lonb1, T2 const& latb1,
+ T2 const& lonb2, T2 const& latb2,
+ CT & lon, CT & lat,
+ Spheroid const& spheroid)
+ {
+ CT const lon_a1 = lona1;
+ CT const lat_a1 = lata1;
+ CT const lon_a2 = lona2;
+ CT const lat_a2 = lata2;
+ CT const lon_b1 = lonb1;
+ CT const lat_b1 = latb1;
+ CT const lon_b2 = lonb2;
+ CT const lat_b2 = latb2;
+
+ return apply(lon_a1, lat_a1, lon_a2, lat_a2, lon_b1, lat_b1, lon_b2, lat_b2, lon, lat, spheroid);
+ }
+
+ template <typename Spheroid>
+ static inline bool apply(CT const& lona1, CT const& lata1,
+ CT const& lona2, CT const& lata2,
+ CT const& lonb1, CT const& latb1,
+ CT const& lonb2, CT const& latb2,
+ CT & lon, CT & lat,
+ Spheroid const& spheroid)
+ {
+ typedef gnomonic_spheroid<CT, Inverse, Direct> gnom_t;
+
+ lon = (lona1 + lona2 + lonb1 + lonb2) / 4;
+ lat = (lata1 + lata2 + latb1 + latb2) / 4;
+ // TODO: consider normalizing lon
+
+ for (int i = 0; i < 10; ++i)
+ {
+ CT xa1, ya1, xa2, ya2;
+ CT xb1, yb1, xb2, yb2;
+ CT x, y;
+ double lat1, lon1;
+
+ bool ok = gnom_t::forward(lon, lat, lona1, lata1, xa1, ya1, spheroid)
+ && gnom_t::forward(lon, lat, lona2, lata2, xa2, ya2, spheroid)
+ && gnom_t::forward(lon, lat, lonb1, latb1, xb1, yb1, spheroid)
+ && gnom_t::forward(lon, lat, lonb2, latb2, xb2, yb2, spheroid)
+ && intersect(xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2, x, y)
+ && gnom_t::inverse(lon, lat, x, y, lon1, lat1, spheroid);
+
+ if (! ok)
+ {
+ return false;
+ }
+
+ if (math::equals(lat1, lat) && math::equals(lon1, lon))
+ {
+ break;
+ }
+
+ lat = lat1;
+ lon = lon1;
+ }
+
+ // NOTE: true is also returned if the number of iterations is too great
+ // which means that the accuracy of the result is low
+ return true;
+ }
+
+private:
+ static inline bool intersect(CT const& xa1, CT const& ya1, CT const& xa2, CT const& ya2,
+ CT const& xb1, CT const& yb1, CT const& xb2, CT const& yb2,
+ CT & x, CT & y)
+ {
+ typedef model::point<CT, 3, cs::cartesian> v3d_t;
+
+ CT const c0 = 0;
+ CT const c1 = 1;
+
+ v3d_t const va1(xa1, ya1, c1);
+ v3d_t const va2(xa2, ya2, c1);
+ v3d_t const vb1(xb1, yb1, c1);
+ v3d_t const vb2(xb2, yb2, c1);
+
+ v3d_t const la = cross_product(va1, va2);
+ v3d_t const lb = cross_product(vb1, vb2);
+ v3d_t const p = cross_product(la, lb);
+
+ CT const z = get<2>(p);
+
+ if (math::equals(z, c0))
+ {
+ // degenerated or collinear segments
+ return false;
+ }
+
+ x = get<0>(p) / z;
+ y = get<1>(p) / z;
+
+ return true;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP
diff --git a/boost/geometry/formulas/gnomonic_spheroid.hpp b/boost/geometry/formulas/gnomonic_spheroid.hpp
new file mode 100644
index 0000000000..3457397b0f
--- /dev/null
+++ b/boost/geometry/formulas/gnomonic_spheroid.hpp
@@ -0,0 +1,126 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
+#define BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
+
+
+#include <boost/geometry/core/radius.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/thomas_inverse.hpp>
+#include <boost/geometry/formulas/vincenty_direct.hpp>
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Gnomonic projection on spheroid (ellipsoid of revolution).
+\author See
+- Charles F.F Karney, Algorithms for geodesics, 2011
+https://arxiv.org/pdf/1109.4448.pdf
+*/
+template <
+ typename CT,
+ template <typename, bool, bool, bool, bool ,bool> class Inverse,
+ template <typename, bool, bool, bool, bool> class Direct
+>
+class gnomonic_spheroid
+{
+ typedef Inverse<CT, false, true, true, true, true> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+
+ typedef Direct<CT, false, false, true, true> direct_quantities_type;
+ typedef Direct<CT, true, false, false, false> direct_coordinates_type;
+ typedef typename direct_coordinates_type::result_type direct_result;
+
+public:
+ template <typename Spheroid>
+ static inline bool forward(CT const& lon0, CT const& lat0,
+ CT const& lon, CT const& lat,
+ CT & x, CT & y,
+ Spheroid const& spheroid)
+ {
+ inverse_result i_res = inverse_type::apply(lon0, lat0, lon, lat, spheroid);
+ CT const& m = i_res.reduced_length;
+ CT const& M = i_res.geodesic_scale;
+
+ if (math::smaller_or_equals(M, CT(0)))
+ {
+ return false;
+ }
+
+ CT rho = m / M;
+ x = sin(i_res.azimuth) * rho;
+ y = cos(i_res.azimuth) * rho;
+
+ return true;
+ }
+
+ template <typename Spheroid>
+ static inline bool inverse(CT const& lon0, CT const& lat0,
+ CT const& x, CT const& y,
+ CT & lon, CT & lat,
+ Spheroid const& spheroid)
+ {
+ CT const a = get_radius<0>(spheroid);
+ CT const ds_threshold = a * std::numeric_limits<CT>::epsilon(); // TODO: 0 for non-fundamental type
+
+ CT const azimuth = atan2(x, y);
+ CT const rho = math::sqrt(math::sqr(x) + math::sqr(y)); // use hypot?
+ CT distance = a * atan(rho / a);
+
+ bool found = false;
+ for (int i = 0 ; i < 10 ; ++i)
+ {
+ direct_result d_res = direct_quantities_type::apply(lon0, lat0, distance, azimuth, spheroid);
+ CT const& m = d_res.reduced_length;
+ CT const& M = d_res.geodesic_scale;
+
+ if (math::smaller_or_equals(M, CT(0)))
+ {
+ // found = false;
+ return found;
+ }
+
+ CT const drho = m / M - rho; // rho = m / M
+ CT const ds = drho * math::sqr(M); // drho/ds = 1/M^2
+ distance -= ds;
+
+ // ds_threshold may be 0
+ if (math::abs(ds) <= ds_threshold)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ direct_result d_res = direct_coordinates_type::apply(lon0, lat0, distance, azimuth, spheroid);
+ lon = d_res.lon2;
+ lat = d_res.lat2;
+ }
+
+ return found;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_GNOMONIC_SPHEROID_HPP
diff --git a/boost/geometry/formulas/result_direct.hpp b/boost/geometry/formulas/result_direct.hpp
new file mode 100644
index 0000000000..8461d8ac9b
--- /dev/null
+++ b/boost/geometry/formulas/result_direct.hpp
@@ -0,0 +1,39 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_RESULT_DIRECT_HPP
+#define BOOST_GEOMETRY_FORMULAS_RESULT_DIRECT_HPP
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+template <typename T>
+struct result_direct
+{
+ result_direct()
+ : lon2(0)
+ , lat2(0)
+ , reverse_azimuth(0)
+ , reduced_length(0)
+ , geodesic_scale(1)
+ {}
+
+ T lon2;
+ T lat2;
+ T reverse_azimuth;
+ T reduced_length;
+ T geodesic_scale;
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_RESULT_DIRECT_HPP
diff --git a/boost/geometry/formulas/result_inverse.hpp b/boost/geometry/formulas/result_inverse.hpp
new file mode 100644
index 0000000000..b6faae6eaa
--- /dev/null
+++ b/boost/geometry/formulas/result_inverse.hpp
@@ -0,0 +1,39 @@
+// Boost.Geometry
+
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_RESULT_INVERSE_HPP
+#define BOOST_GEOMETRY_FORMULAS_RESULT_INVERSE_HPP
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+template <typename T>
+struct result_inverse
+{
+ result_inverse()
+ : distance(0)
+ , azimuth(0)
+ , reverse_azimuth(0)
+ , reduced_length(0)
+ , geodesic_scale(1)
+ {}
+
+ T distance;
+ T azimuth;
+ T reverse_azimuth;
+ T reduced_length;
+ T geodesic_scale;
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_RESULT_INVERSE_HPP
diff --git a/boost/geometry/formulas/sjoberg_intersection.hpp b/boost/geometry/formulas/sjoberg_intersection.hpp
new file mode 100644
index 0000000000..03bd4bc97e
--- /dev/null
+++ b/boost/geometry/formulas/sjoberg_intersection.hpp
@@ -0,0 +1,385 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP
+#define BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief The intersection of two geodesics as proposed by Sjoberg.
+\author See
+ - [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002
+ http://link.springer.com/article/10.1007/s00190-001-0230-9
+ - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
+ http://link.springer.com/article/10.1007/s00190-007-0204-7
+*/
+template
+<
+ typename CT,
+ template <typename, bool, bool, bool, bool, bool> class Inverse,
+ unsigned int Order = 4
+>
+class sjoberg_intersection
+{
+ typedef Inverse<CT, false, true, false, false, false> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+
+public:
+ template <typename T1, typename T2, typename Spheroid>
+ static inline bool apply(T1 const& lona1, T1 const& lata1,
+ T1 const& lona2, T1 const& lata2,
+ T2 const& lonb1, T2 const& latb1,
+ T2 const& lonb2, T2 const& latb2,
+ CT & lon, CT & lat,
+ Spheroid const& spheroid)
+ {
+ CT const lon_a1 = lona1;
+ CT const lat_a1 = lata1;
+ CT const lon_a2 = lona2;
+ CT const lat_a2 = lata2;
+ CT const lon_b1 = lonb1;
+ CT const lat_b1 = latb1;
+ CT const lon_b2 = lonb2;
+ CT const lat_b2 = latb2;
+
+ CT const alpha1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid).azimuth;
+ CT const alpha2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid).azimuth;
+
+ return apply(lon_a1, lat_a1, alpha1, lon_b1, lat_b1, alpha2, lon, lat, spheroid);
+ }
+
+ template <typename Spheroid>
+ static inline bool apply(CT const& lon1, CT const& lat1, CT const& alpha1,
+ CT const& lon2, CT const& lat2, CT const& alpha2,
+ CT & lon, CT & lat,
+ Spheroid const& spheroid)
+ {
+ // coordinates in radians
+
+ // TODO - handle special cases like degenerated segments, equator, poles, etc.
+
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+ CT const f = detail::flattening<CT>(spheroid);
+ CT const one_minus_f = c1 - f;
+ CT const e_sqr = f * (c2 - f);
+
+ CT const sin_alpha1 = sin(alpha1);
+ CT const sin_alpha2 = sin(alpha2);
+
+ CT const tan_beta1 = one_minus_f * tan(lat1);
+ CT const tan_beta2 = one_minus_f * tan(lat2);
+ CT const beta1 = atan(tan_beta1);
+ CT const beta2 = atan(tan_beta2);
+ CT const cos_beta1 = cos(beta1);
+ CT const cos_beta2 = cos(beta2);
+ CT const sin_beta1 = sin(beta1);
+ CT const sin_beta2 = sin(beta2);
+
+ // Clairaut constants (lower-case in the paper)
+ int const sign_C1 = math::abs(alpha1) <= pi_half ? 1 : -1;
+ int const sign_C2 = math::abs(alpha2) <= pi_half ? 1 : -1;
+ // Cj = 1 if on equator
+ CT const C1 = sign_C1 * cos_beta1 * sin_alpha1;
+ CT const C2 = sign_C2 * cos_beta2 * sin_alpha2;
+
+ CT const sqrt_1_C1_sqr = math::sqrt(c1 - math::sqr(C1));
+ CT const sqrt_1_C2_sqr = math::sqrt(c1 - math::sqr(C2));
+
+ // handle special case: segments on the equator
+ bool const on_equator1 = math::equals(sqrt_1_C1_sqr, c0);
+ bool const on_equator2 = math::equals(sqrt_1_C2_sqr, c0);
+ if (on_equator1 && on_equator2)
+ {
+ return false;
+ }
+ else if (on_equator1)
+ {
+ CT const dL2 = d_lambda_e_sqr(sin_beta2, c0, C2, sqrt_1_C2_sqr, e_sqr);
+ CT const asin_t2_t02 = asin(C2 * tan_beta2 / sqrt_1_C2_sqr);
+ lat = c0;
+ lon = lon2 - asin_t2_t02 + dL2;
+ return true;
+ }
+ else if (on_equator2)
+ {
+ CT const dL1 = d_lambda_e_sqr(sin_beta1, c0, C1, sqrt_1_C1_sqr, e_sqr);
+ CT const asin_t1_t01 = asin(C1 * tan_beta1 / sqrt_1_C1_sqr);
+ lat = c0;
+ lon = lon1 - asin_t1_t01 + dL1;
+ return true;
+ }
+
+ CT const t01 = sqrt_1_C1_sqr / C1;
+ CT const t02 = sqrt_1_C2_sqr / C2;
+
+ CT const asin_t1_t01 = asin(tan_beta1 / t01);
+ CT const asin_t2_t02 = asin(tan_beta2 / t02);
+ CT const t01_t02 = t01 * t02;
+ CT const t01_t02_2 = c2 * t01_t02;
+ CT const sqr_t01_sqr_t02 = math::sqr(t01) + math::sqr(t02);
+
+ CT t = tan_beta1;
+ int t_id = 0;
+
+ // find the initial t using simplified spherical solution
+ // though not entirely since the reduced latitudes and azimuths are spheroidal
+ // [Sjoberg07]
+ CT const k_base = lon1 - lon2 + asin_t2_t02 - asin_t1_t01;
+
+ {
+ CT const K = sin(k_base);
+ CT const d1 = sqr_t01_sqr_t02;
+ //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
+ CT const d2 = t01_t02_2 * cos(k_base);
+ CT const D1 = math::sqrt(d1 - d2);
+ CT const D2 = math::sqrt(d1 + d2);
+ CT const K_t01_t02 = K * t01_t02;
+
+ CT const T1 = K_t01_t02 / D1;
+ CT const T2 = K_t01_t02 / D2;
+ CT asin_T1_t01 = 0;
+ CT asin_T1_t02 = 0;
+ CT asin_T2_t01 = 0;
+ CT asin_T2_t02 = 0;
+
+ // test 4 possible results
+ CT l1 = 0, l2 = 0, dl = 0;
+ bool found = check_t<0>( T1,
+ lon1, asin_T1_t01 = asin(T1 / t01), asin_t1_t01,
+ lon2, asin_T1_t02 = asin(T1 / t02), asin_t2_t02,
+ t, l1, l2, dl, t_id)
+ || check_t<1>(-T1,
+ lon1, -asin_T1_t01 , asin_t1_t01,
+ lon2, -asin_T1_t02 , asin_t2_t02,
+ t, l1, l2, dl, t_id)
+ || check_t<2>( T2,
+ lon1, asin_T2_t01 = asin(T2 / t01), asin_t1_t01,
+ lon2, asin_T2_t02 = asin(T2 / t02), asin_t2_t02,
+ t, l1, l2, dl, t_id)
+ || check_t<3>(-T2,
+ lon1, -asin_T2_t01 , asin_t1_t01,
+ lon2, -asin_T2_t02 , asin_t2_t02,
+ t, l1, l2, dl, t_id);
+
+ boost::ignore_unused(found);
+ }
+
+ // [Sjoberg07]
+ //int const d2_sign = t_id < 2 ? -1 : 1;
+ int const t_sign = (t_id % 2) ? -1 : 1;
+ // [Sjoberg02]
+ CT const C1_sqr = math::sqr(C1);
+ CT const C2_sqr = math::sqr(C2);
+
+ CT beta = atan(t);
+ CT dL1 = 0, dL2 = 0;
+ CT asin_t_t01 = 0;
+ CT asin_t_t02 = 0;
+
+ for (int i = 0; i < 10; ++i)
+ {
+ CT const sin_beta = sin(beta);
+
+ // integrals approximation
+ dL1 = d_lambda_e_sqr(sin_beta1, sin_beta, C1, sqrt_1_C1_sqr, e_sqr);
+ dL2 = d_lambda_e_sqr(sin_beta2, sin_beta, C2, sqrt_1_C2_sqr, e_sqr);
+
+ // [Sjoberg07]
+ /*CT const k = k_base + dL1 - dL2;
+ CT const K = sin(k);
+ CT const d1 = sqr_t01_sqr_t02;
+ //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
+ CT const d2 = t01_t02_2 * cos(k);
+ CT const D = math::sqrt(d1 + d2_sign * d2);
+ CT const t_new = t_sign * K * t01_t02 / D;
+ CT const dt = math::abs(t_new - t);
+ t = t_new;
+ CT const new_beta = atan(t);
+ CT const dbeta = math::abs(new_beta - beta);
+ beta = new_beta;*/
+
+ // [Sjoberg02] - it converges faster
+ // NewtonRaphson method
+ asin_t_t01 = asin(t / t01);
+ asin_t_t02 = asin(t / t02);
+ CT const R1 = asin_t_t01 + dL1;
+ CT const R2 = asin_t_t02 + dL2;
+ CT const cos_beta = cos(beta);
+ CT const cos_beta_sqr = math::sqr(cos_beta);
+ CT const G = c1 - e_sqr * cos_beta_sqr;
+ CT const f1 = C1 / cos_beta * math::sqrt(G / (cos_beta_sqr - C1_sqr));
+ CT const f2 = C2 / cos_beta * math::sqrt(G / (cos_beta_sqr - C2_sqr));
+ CT const abs_f1 = math::abs(f1);
+ CT const abs_f2 = math::abs(f2);
+ CT const dbeta = t_sign * (k_base - R2 + R1) / (abs_f1 + abs_f2);
+
+ if (math::equals(dbeta, CT(0)))
+ {
+ break;
+ }
+
+ beta = beta - dbeta;
+ t = tan(beta);
+ }
+
+ // t = tan(beta) = (1-f)tan(lat)
+ lat = atan(t / one_minus_f);
+
+ CT const l1 = lon1 + asin_t_t01 - asin_t1_t01 + dL1;
+ //CT const l2 = lon2 + asin_t_t02 - asin_t2_t02 + dL2;
+ lon = l1;
+
+ return true;
+ }
+
+private:
+ /*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2
+ Maxima script:
+ dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB);
+ dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B);
+ S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3);
+ assume(c_j < 1);
+ assume(c_j > 0);
+ L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ */
+ static inline CT d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
+ CT const& Cj, CT const& sqrt_1_Cj_sqr,
+ CT const& e_sqr)
+ {
+ if (Order == 0)
+ {
+ return 0;
+ }
+
+ CT const c2 = 2;
+
+ CT const asin_B = asin(sin_beta / sqrt_1_Cj_sqr);
+ CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
+ CT const L0 = (asin_B - asin_Bj) / c2;
+
+ if (Order == 1)
+ {
+ return -Cj * e_sqr * L0;
+ }
+
+ CT const c1 = 1;
+ CT const c16 = 16;
+
+ CT const X = sin_beta;
+ CT const Xj = sin_betaj;
+ CT const Cj_sqr = math::sqr(Cj);
+ CT const Cj_sqr_plus_one = Cj_sqr + c1;
+ CT const one_minus_Cj_sqr = c1 - Cj_sqr;
+ CT const sqrt_Y = math::sqrt(-math::sqr(X) + one_minus_Cj_sqr);
+ CT const sqrt_Yj = math::sqrt(-math::sqr(Xj) + one_minus_Cj_sqr);
+ CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
+
+ if (Order == 2)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * L1);
+ }
+
+ CT const c3 = 3;
+ CT const c5 = 5;
+ CT const c128 = 128;
+
+ CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3;
+ CT const X_sqr = math::sqr(X);
+ CT const Xj_sqr = math::sqr(Xj);
+ CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5);
+ CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
+ CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
+
+ if (Order == 3)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
+ }
+
+ CT const c8 = 8;
+ CT const c9 = 9;
+ CT const c10 = 10;
+ CT const c15 = 15;
+ CT const c24 = 24;
+ CT const c26 = 26;
+ CT const c33 = 33;
+ CT const c6144 = 6144;
+
+ CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15;
+ CT const H = -c10 * Cj_sqr - c26;
+ CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33;
+ CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I;
+ CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I;
+ CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144;
+
+ // Order 4 and higher
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3)));
+ }
+
+ static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr)
+ {
+ CT const c1 = 1;
+ CT const Cj_sqr = math::sqr(Cj);
+ return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr));
+ }
+
+ template <int TId>
+ static inline bool check_t(CT const& t,
+ CT const& lon_a1, CT const& asin_t_t01, CT const& asin_t1_t01,
+ CT const& lon_b1, CT const& asin_t_t02, CT const& asin_t2_t02,
+ CT & current_t, CT & current_lon1, CT & current_lon2, CT & current_dlon,
+ int & t_id)
+ {
+ CT const lon1 = lon_a1 + asin_t_t01 - asin_t1_t01;
+ CT const lon2 = lon_b1 + asin_t_t02 - asin_t2_t02;
+
+ // TODO - true angle difference
+ CT const dlon = math::abs(lon2 - lon1);
+
+ bool are_equal = math::equals(dlon, CT(0));
+
+ if ((TId == 0) || are_equal || dlon < current_dlon)
+ {
+ current_t = t;
+ current_lon1 = lon1;
+ current_lon2 = lon2;
+ current_dlon = dlon;
+ t_id = TId;
+ }
+
+ return are_equal;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP
diff --git a/boost/geometry/formulas/thomas_direct.hpp b/boost/geometry/formulas/thomas_direct.hpp
new file mode 100644
index 0000000000..f8a7f83943
--- /dev/null
+++ b/boost/geometry/formulas/thomas_direct.hpp
@@ -0,0 +1,249 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_THOMAS_DIRECT_HPP
+#define BOOST_GEOMETRY_FORMULAS_THOMAS_DIRECT_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/result_direct.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+
+/*!
+\brief The solution of the direct problem of geodesics on latlong coordinates,
+ Forsyth-Andoyer-Lambert type approximation with second order terms.
+\author See
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
+ http://www.dtic.mil/docs/citations/AD0627893
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
+ http://www.dtic.mil/docs/citations/AD0703541
+
+*/
+template <
+ typename CT,
+ bool EnableCoordinates = true,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+>
+class thomas_direct
+{
+ static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
+ static const bool CalcCoordinates = EnableCoordinates || CalcQuantities;
+ static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcCoordinates || CalcQuantities;
+
+public:
+ typedef result_direct<CT> result_type;
+
+ template <typename T, typename Dist, typename Azi, typename Spheroid>
+ static inline result_type apply(T const& lo1,
+ T const& la1,
+ Dist const& distance,
+ Azi const& azimuth12,
+ Spheroid const& spheroid)
+ {
+ result_type result;
+
+ CT const lon1 = lo1;
+ CT const lat1 = la1;
+
+ if ( math::equals(distance, Dist(0)) || distance < Dist(0) )
+ {
+ result.lon2 = lon1;
+ result.lat2 = lat1;
+ return result;
+ }
+
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+ CT const c4 = 4;
+
+ CT const a = CT(get_radius<0>(spheroid));
+ CT const b = CT(get_radius<2>(spheroid));
+ CT const f = detail::flattening<CT>(spheroid);
+ CT const one_minus_f = c1 - f;
+
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ // keep azimuth small - experiments show low accuracy
+ // if the azimuth is closer to (+-)180 deg.
+ CT azi12_alt = azimuth12;
+ CT lat1_alt = lat1;
+ bool alter_result = vflip_if_south(lat1, azimuth12, lat1_alt, azi12_alt);
+
+ CT const theta1 = math::equals(lat1_alt, pi_half) ? lat1_alt :
+ math::equals(lat1_alt, -pi_half) ? lat1_alt :
+ atan(one_minus_f * tan(lat1_alt));
+ CT const sin_theta1 = sin(theta1);
+ CT const cos_theta1 = cos(theta1);
+
+ CT const sin_a12 = sin(azi12_alt);
+ CT const cos_a12 = cos(azi12_alt);
+
+ CT const M = cos_theta1 * sin_a12; // cos_theta0
+ CT const theta0 = acos(M);
+ CT const sin_theta0 = sin(theta0);
+
+ CT const N = cos_theta1 * cos_a12;
+ CT const C1 = f * M; // lower-case c1 in the technical report
+ CT const C2 = f * (c1 - math::sqr(M)) / c4; // lower-case c2 in the technical report
+ CT const D = (c1 - C2) * (c1 - C2 - C1 * M);
+ CT const P = C2 * (c1 + C1 * M / c2) / D;
+
+ // special case for equator:
+ // sin_theta0 = 0 <=> lat1 = 0 ^ |azimuth12| = pi/2
+ // NOTE: in this case it doesn't matter what's the value of cos_sigma1 because
+ // theta1=0, theta0=0, M=1|-1, C2=0 so X=0 and Y=0 so d_sigma=d
+ // cos_a12=0 so N=0, therefore
+ // lat2=0, azi21=pi/2|-pi/2
+ // d_eta = atan2(sin_d_sigma, cos_d_sigma)
+ // H = C1 * d_sigma
+ CT const cos_sigma1 = math::equals(sin_theta0, c0)
+ ? c1
+ : normalized1_1(sin_theta1 / sin_theta0);
+ CT const sigma1 = acos(cos_sigma1);
+ CT const d = distance / (a * D);
+ CT const u = 2 * (sigma1 - d);
+ CT const cos_d = cos(d);
+ CT const sin_d = sin(d);
+ CT const cos_u = cos(u);
+ CT const sin_u = sin(u);
+
+ CT const W = c1 - c2 * P * cos_u;
+ CT const V = cos_u * cos_d - sin_u * sin_d;
+ CT const X = math::sqr(C2) * sin_d * cos_d * (2 * math::sqr(V) - c1);
+ CT const Y = c2 * P * V * W * sin_d;
+ CT const d_sigma = d + X - Y;
+ CT const sin_d_sigma = sin(d_sigma);
+ CT const cos_d_sigma = cos(d_sigma);
+
+ if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth))
+ {
+ result.reverse_azimuth = atan2(M, N * cos_d_sigma - sin_theta1 * sin_d_sigma);
+
+ if (alter_result)
+ {
+ vflip_rev_azi(result.reverse_azimuth, azimuth12);
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(CalcCoordinates))
+ {
+ CT const S_sigma = c2 * sigma1 - d_sigma;
+ CT const cos_S_sigma = cos(S_sigma);
+ CT const d_eta = atan2(sin_d_sigma * sin_a12, cos_theta1 * cos_d_sigma - sin_theta1 * sin_d_sigma * cos_a12);
+ CT const H = C1 * (c1 - C2) * d_sigma - C1 * C2 * sin_d_sigma * cos_S_sigma;
+ CT const d_lambda = d_eta - H;
+
+ result.lon2 = lon1 + d_lambda;
+
+ if (! math::equals(M, c0))
+ {
+ CT const sin_a21 = sin(result.reverse_azimuth);
+ CT const tan_theta2 = (sin_theta1 * cos_d_sigma + N * sin_d_sigma) * sin_a21 / M;
+ result.lat2 = atan(tan_theta2 / one_minus_f);
+ }
+ else
+ {
+ CT const sigma2 = S_sigma - sigma1;
+ //theta2 = asin(cos(sigma2)) <=> sin_theta0 = 1
+ CT const tan_theta2 = cos(sigma2) / sin(sigma2);
+ result.lat2 = atan(tan_theta2 / one_minus_f);
+ }
+
+ if (alter_result)
+ {
+ result.lat2 = -result.lat2;
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
+ {
+ typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
+ quantities::apply(lon1, lat1, result.lon2, result.lat2,
+ azimuth12, result.reverse_azimuth,
+ b, f,
+ result.reduced_length, result.geodesic_scale);
+ }
+
+ return result;
+ }
+
+private:
+ static inline bool vflip_if_south(CT const& lat1, CT const& azi12, CT & lat1_alt, CT & azi12_alt)
+ {
+ CT const c2 = 2;
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ if (azi12 > pi_half)
+ {
+ azi12_alt = pi - azi12;
+ lat1_alt = -lat1;
+ return true;
+ }
+ else if (azi12 < -pi_half)
+ {
+ azi12_alt = -pi - azi12;
+ lat1_alt = -lat1;
+ return true;
+ }
+
+ return false;
+ }
+
+ static inline void vflip_rev_azi(CT & rev_azi, CT const& azimuth12)
+ {
+ CT const c0 = 0;
+ CT const pi = math::pi<CT>();
+
+ if (rev_azi == c0)
+ {
+ rev_azi = azimuth12 >= 0 ? pi : -pi;
+ }
+ else if (rev_azi > c0)
+ {
+ rev_azi = pi - rev_azi;
+ }
+ else
+ {
+ rev_azi = -pi - rev_azi;
+ }
+ }
+
+ static inline CT normalized1_1(CT const& value)
+ {
+ CT const c1 = 1;
+ return value > c1 ? c1 :
+ value < -c1 ? -c1 :
+ value;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_THOMAS_DIRECT_HPP
diff --git a/boost/geometry/formulas/thomas_inverse.hpp b/boost/geometry/formulas/thomas_inverse.hpp
new file mode 100644
index 0000000000..d68c9de054
--- /dev/null
+++ b/boost/geometry/formulas/thomas_inverse.hpp
@@ -0,0 +1,221 @@
+// Boost.Geometry
+
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_THOMAS_INVERSE_HPP
+#define BOOST_GEOMETRY_FORMULAS_THOMAS_INVERSE_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/result_inverse.hpp>
+
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief The solution of the inverse problem of geodesics on latlong coordinates,
+ Forsyth-Andoyer-Lambert type approximation with second order terms.
+\author See
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
+ http://www.dtic.mil/docs/citations/AD0627893
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
+ http://www.dtic.mil/docs/citations/AD0703541
+*/
+template <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+>
+class thomas_inverse
+{
+ static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
+ static const bool CalcAzimuths = EnableAzimuth || EnableReverseAzimuth || CalcQuantities;
+ static const bool CalcFwdAzimuth = EnableAzimuth || CalcQuantities;
+ static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities;
+
+public:
+ typedef result_inverse<CT> result_type;
+
+ template <typename T1, typename T2, typename Spheroid>
+ static inline result_type apply(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2,
+ Spheroid const& spheroid)
+ {
+ result_type result;
+
+ // coordinates in radians
+
+ if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) )
+ {
+ return result;
+ }
+
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+ CT const c4 = 4;
+
+ CT const pi_half = math::pi<CT>() / c2;
+ CT const f = detail::flattening<CT>(spheroid);
+ CT const one_minus_f = c1 - f;
+
+// CT const tan_theta1 = one_minus_f * tan(lat1);
+// CT const tan_theta2 = one_minus_f * tan(lat2);
+// CT const theta1 = atan(tan_theta1);
+// CT const theta2 = atan(tan_theta2);
+
+ CT const theta1 = math::equals(lat1, pi_half) ? lat1 :
+ math::equals(lat1, -pi_half) ? lat1 :
+ atan(one_minus_f * tan(lat1));
+ CT const theta2 = math::equals(lat2, pi_half) ? lat2 :
+ math::equals(lat2, -pi_half) ? lat2 :
+ atan(one_minus_f * tan(lat2));
+
+ CT const theta_m = (theta1 + theta2) / c2;
+ CT const d_theta_m = (theta2 - theta1) / c2;
+ CT const d_lambda = lon2 - lon1;
+ CT const d_lambda_m = d_lambda / c2;
+
+ CT const sin_theta_m = sin(theta_m);
+ CT const cos_theta_m = cos(theta_m);
+ CT const sin_d_theta_m = sin(d_theta_m);
+ CT const cos_d_theta_m = cos(d_theta_m);
+ CT const sin2_theta_m = math::sqr(sin_theta_m);
+ CT const cos2_theta_m = math::sqr(cos_theta_m);
+ CT const sin2_d_theta_m = math::sqr(sin_d_theta_m);
+ CT const cos2_d_theta_m = math::sqr(cos_d_theta_m);
+ CT const sin_d_lambda_m = sin(d_lambda_m);
+ CT const sin2_d_lambda_m = math::sqr(sin_d_lambda_m);
+
+ CT const H = cos2_theta_m - sin2_d_theta_m;
+ CT const L = sin2_d_theta_m + H * sin2_d_lambda_m;
+ CT const cos_d = c1 - c2 * L;
+ CT const d = acos(cos_d);
+ CT const sin_d = sin(d);
+
+ CT const one_minus_L = c1 - L;
+
+ if ( math::equals(sin_d, c0)
+ || math::equals(L, c0)
+ || math::equals(one_minus_L, c0) )
+ {
+ return result;
+ }
+
+ CT const U = c2 * sin2_theta_m * cos2_d_theta_m / one_minus_L;
+ CT const V = c2 * sin2_d_theta_m * cos2_theta_m / L;
+ CT const X = U + V;
+ CT const Y = U - V;
+ CT const T = d / sin_d;
+ CT const D = c4 * math::sqr(T);
+ CT const E = c2 * cos_d;
+ CT const A = D * E;
+ CT const B = c2 * D;
+ CT const C = T - (A - E) / c2;
+
+ CT const f_sqr = math::sqr(f);
+ CT const f_sqr_per_64 = f_sqr / CT(64);
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
+ {
+ CT const n1 = X * (A + C*X);
+ CT const n2 = Y * (B + E*Y);
+ CT const n3 = D*X*Y;
+
+ CT const delta1d = f * (T*X-Y) / c4;
+ CT const delta2d = f_sqr_per_64 * (n1 - n2 + n3);
+
+ CT const a = get_radius<0>(spheroid);
+
+ //result.distance = a * sin_d * (T - delta1d);
+ result.distance = a * sin_d * (T - delta1d + delta2d);
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(CalcAzimuths) )
+ {
+ // NOTE: if both cos_latX == 0 then below we'd have 0 * INF
+ // it's a situation when the endpoints are on the poles +-90 deg
+ // in this case the azimuth could either be 0 or +-pi
+ // but above always 0 is returned
+
+ CT const F = c2*Y-E*(c4-X);
+ CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+c4)*Y;
+ CT const G = f*T/c2 + f_sqr_per_64 * M;
+
+ // TODO:
+ // If d_lambda is close to 90 or -90 deg then tan(d_lambda) is big
+ // and F is small. The result is not accurate.
+ // In the edge case the result may be 2 orders of magnitude less
+ // accurate than Andoyer's.
+ CT const tan_d_lambda = tan(d_lambda);
+ CT const Q = -(F*G*tan_d_lambda) / c4;
+ CT const d_lambda_m_p = (d_lambda + Q) / c2;
+ CT const tan_d_lambda_m_p = tan(d_lambda_m_p);
+
+ CT const v = atan2(cos_d_theta_m, sin_theta_m * tan_d_lambda_m_p);
+ CT const u = atan2(-sin_d_theta_m, cos_theta_m * tan_d_lambda_m_p);
+
+ CT const pi = math::pi<CT>();
+
+ if (BOOST_GEOMETRY_CONDITION(EnableAzimuth))
+ {
+ CT alpha1 = v + u;
+ if (alpha1 > pi)
+ {
+ alpha1 -= c2 * pi;
+ }
+
+ result.azimuth = alpha1;
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(EnableReverseAzimuth))
+ {
+ CT alpha2 = pi - (v - u);
+ if (alpha2 > pi)
+ {
+ alpha2 -= c2 * pi;
+ }
+
+ result.reverse_azimuth = alpha2;
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
+ {
+ typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
+ quantities::apply(lon1, lat1, lon2, lat2,
+ result.azimuth, result.reverse_azimuth,
+ get_radius<2>(spheroid), f,
+ result.reduced_length, result.geodesic_scale);
+ }
+
+ return result;
+ }
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_THOMAS_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/vincenty_direct.hpp b/boost/geometry/formulas/vincenty_direct.hpp
index 1c47a0f68d..f3647ff4e6 100644
--- a/boost/geometry/algorithms/detail/vincenty_direct.hpp
+++ b/boost/geometry/formulas/vincenty_direct.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,8 +11,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP
+#ifndef BOOST_GEOMETRY_FORMULAS_VINCENTY_DIRECT_HPP
+#define BOOST_GEOMETRY_FORMULAS_VINCENTY_DIRECT_HPP
#include <boost/math/constants/constants.hpp>
@@ -20,30 +20,22 @@
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/result_direct.hpp>
+
#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS
#define BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS 1000
#endif
-namespace boost { namespace geometry { namespace detail
-{
-
-template <typename T>
-struct result_direct
+namespace boost { namespace geometry { namespace formula
{
- void set(T const& lo2, T const& la2)
- {
- lon2 = lo2;
- lat2 = la2;
- }
- T lon2;
- T lat2;
-};
/*!
\brief The solution of the direct problem of geodesics on latlong coordinates, after Vincenty, 1975
@@ -56,12 +48,22 @@ struct result_direct
- http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
*/
-template <typename CT>
-struct vincenty_direct
+template <
+ typename CT,
+ bool EnableCoordinates = true,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+>
+class vincenty_direct
{
- typedef result_direct<CT> result_type;
+ static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
+ static const bool CalcCoordinates = EnableCoordinates || CalcQuantities;
+ static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities;
public:
+ typedef result_direct<CT> result_type;
+
template <typename T, typename Dist, typename Azi, typename Spheroid>
static inline result_type apply(T const& lo1,
T const& la1,
@@ -76,7 +78,8 @@ public:
if ( math::equals(distance, Dist(0)) || distance < Dist(0) )
{
- result.set(lon1, lat1);
+ result.lon2 = lon1;
+ result.lat2 = lat1;
return result;
}
@@ -141,13 +144,12 @@ public:
//&& geometry::math::abs(sigma) < pi
&& counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness
+ if (BOOST_GEOMETRY_CONDITION(CalcCoordinates))
{
result.lat2
= atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12,
one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8)
- }
-
- {
+
CT const lambda = atan2( sin_sigma * sin_azimuth12,
cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9)
CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10)
@@ -157,21 +159,27 @@ public:
result.lon2 = lon1 + L;
}
+ if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth))
+ {
+ result.reverse_azimuth
+ = atan2(sin_alpha, -sin_U1 * sin_sigma + cos_U1 * cos_sigma * cos_azimuth12); // (12)
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
+ {
+ typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
+ quantities::apply(lon1, lat1, result.lon2, result.lat2,
+ azimuth12, result.reverse_azimuth,
+ radius_b, flattening,
+ result.reduced_length, result.geodesic_scale);
+ }
+
return result;
}
- /*
- inline CT azimuth21() const
- {
- // NOTE: signs of X and Y are different than in the original paper
- return is_distance_zero ?
- CT(0) :
- atan2(-sin_alpha, sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12); // (12)
- }
- */
};
-}}} // namespace boost::geometry::detail
+}}} // namespace boost::geometry::formula
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP
+#endif // BOOST_GEOMETRY_FORMULAS_VINCENTY_DIRECT_HPP
diff --git a/boost/geometry/algorithms/detail/vincenty_inverse.hpp b/boost/geometry/formulas/vincenty_inverse.hpp
index fe05e95932..bbda00036b 100644
--- a/boost/geometry/algorithms/detail/vincenty_inverse.hpp
+++ b/boost/geometry/formulas/vincenty_inverse.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,8 +11,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP
+#ifndef BOOST_GEOMETRY_FORMULAS_VINCENTY_INVERSE_HPP
+#define BOOST_GEOMETRY_FORMULAS_VINCENTY_INVERSE_HPP
#include <boost/math/constants/constants.hpp>
@@ -24,7 +24,9 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
-#include <boost/geometry/algorithms/detail/result_inverse.hpp>
+
+#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/result_inverse.hpp>
#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS
@@ -32,7 +34,7 @@
#endif
-namespace boost { namespace geometry { namespace detail
+namespace boost { namespace geometry { namespace formula
{
/*!
@@ -46,12 +48,24 @@ namespace boost { namespace geometry { namespace detail
- http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
*/
-template <typename CT, bool EnableDistance, bool EnableAzimuth>
+template <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+>
struct vincenty_inverse
{
- typedef result_inverse<CT> result_type;
+ static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale;
+ static const bool CalcAzimuths = EnableAzimuth || EnableReverseAzimuth || CalcQuantities;
+ static const bool CalcFwdAzimuth = EnableAzimuth || CalcQuantities;
+ static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities;
public:
+ typedef result_inverse<CT> result_type;
+
template <typename T1, typename T2, typename Spheroid>
static inline result_type apply(T1 const& lon1,
T1 const& lat1,
@@ -63,7 +77,6 @@ public:
if (math::equals(lat1, lat2) && math::equals(lon1, lon2))
{
- result.set(CT(0), CT(0));
return result;
}
@@ -174,31 +187,34 @@ public:
result.distance = radius_b * A * (sigma - delta_sigma); // (19)
}
- else
- {
- result.distance = CT(0);
- }
- if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
+ if ( BOOST_GEOMETRY_CONDITION(CalcAzimuths) )
{
- result.azimuth = atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20)
+ if (BOOST_GEOMETRY_CONDITION(CalcFwdAzimuth))
+ {
+ result.azimuth = atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20)
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth))
+ {
+ result.reverse_azimuth = atan2(cos_U1 * sin_lambda, -sin_U1 * cos_U2 + cos_U1 * sin_U2 * cos_lambda); // (21)
+ }
}
- else
+
+ if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
{
- result.azimuth = CT(0);
+ typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
+ quantities::apply(lon1, lat1, lon2, lat2,
+ result.azimuth, result.reverse_azimuth,
+ radius_b, flattening,
+ result.reduced_length, result.geodesic_scale);
}
return result;
}
-
-// inline CT azimuth21() const
-// {
-// // NOTE: signs of X and Y are different than in the original paper
-// atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21)
-// }
};
-}}} // namespace boost::geometry::detail
+}}} // namespace boost::geometry::formula
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP
+#endif // BOOST_GEOMETRY_FORMULAS_VINCENTY_INVERSE_HPP
diff --git a/boost/geometry/geometries/adapted/std_array.hpp b/boost/geometry/geometries/adapted/std_array.hpp
new file mode 100644
index 0000000000..4f5cbe0d32
--- /dev/null
+++ b/boost/geometry/geometries/adapted/std_array.hpp
@@ -0,0 +1,115 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010 Alfredo Correa
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2016 Norbert Wenzel
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP
+
+
+#define BOOST_GEOMETRY_ADAPTED_STD_ARRAY_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <array>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+// Create class and specialization to indicate the tag
+// for normal cases and the case that the type of the std-array is arithmetic
+template <bool>
+struct std_array_tag
+{
+ typedef geometry_not_recognized_tag type;
+};
+
+
+template <>
+struct std_array_tag<true>
+{
+ typedef point_tag type;
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Assign the point-tag, preventing arrays of points getting a point-tag
+template <typename CoordinateType, std::size_t DimensionCount>
+struct tag<std::array<CoordinateType, DimensionCount> >
+ : detail::std_array_tag<boost::is_arithmetic<CoordinateType>::value> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct coordinate_type<std::array<CoordinateType, DimensionCount> >
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct dimension<std::array<CoordinateType, DimensionCount> >: boost::mpl::int_<DimensionCount> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>
+struct access<std::array<CoordinateType, DimensionCount>, Dimension>
+{
+ static inline CoordinateType get(std::array<CoordinateType, DimensionCount> const& a)
+ {
+ return a[Dimension];
+ }
+
+ static inline void set(std::array<CoordinateType, DimensionCount>& a,
+ CoordinateType const& value)
+ {
+ a[Dimension] = value;
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#define BOOST_GEOMETRY_REGISTER_STD_ARRAY_CS(CoordinateSystem) \
+ namespace boost { namespace geometry { namespace traits { \
+ template <class T, std::size_t N> \
+ struct coordinate_system<std::array<T, N> > \
+ { \
+ typedef CoordinateSystem type; \
+ }; \
+ }}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP
+
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
index 227939c96d..72c6c661b7 100644
--- a/boost/geometry/index/detail/predicates.hpp
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -11,7 +11,11 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
-#include <boost/geometry/index/predicates.hpp>
+//#include <utility>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/tuple/tuple.hpp>
+
#include <boost/geometry/index/detail/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/predicates.hpp b/boost/geometry/index/predicates.hpp
index 3bb1bf4d87..f4e22bdd55 100644
--- a/boost/geometry/index/predicates.hpp
+++ b/boost/geometry/index/predicates.hpp
@@ -11,10 +11,6 @@
#ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_PREDICATES_HPP
-#include <utility>
-#include <boost/tuple/tuple.hpp>
-#include <boost/mpl/assert.hpp>
-
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/detail/tuples.hpp>
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index fe77de9e2d..28a6f29336 100644
--- a/boost/geometry/strategies/cartesian/box_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/box_in_box.hpp
@@ -36,8 +36,7 @@ namespace within
{
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct box_within_range
+struct box_within_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
@@ -51,8 +50,7 @@ struct box_within_range
};
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct box_covered_by_range
+struct box_covered_by_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
@@ -65,7 +63,19 @@ struct box_covered_by_range
};
-struct box_within_longitude_check
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct box_within_range
+ : box_within_coord
+{};
+
+
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct box_covered_by_range
+ : box_covered_by_coord
+{};
+
+
+struct box_within_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_ed)
@@ -74,7 +84,7 @@ struct box_within_longitude_check
}
};
-struct box_covered_by_longitude_check
+struct box_covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const&)
@@ -84,6 +94,7 @@ struct box_covered_by_longitude_check
};
template <typename Geometry,
+ typename CoordCheck,
typename InteriorCheck>
struct box_longitude_range
{
@@ -101,6 +112,11 @@ struct box_longitude_range
typedef typename coordinate_system<Geometry>::type::units units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+ if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
+ {
+ return true;
+ }
+
// min <= max <=> diff >= 0
calc_t const diff_ed = bed_max - bed_min;
calc_t const diff_ing = bing_max - bing_min;
@@ -122,7 +138,8 @@ struct box_longitude_range
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
// max of contained translated into the containing origin must be lesser than max of containing
- return bing_min + diff_min + diff_ed <= bing_max;
+ return bing_min + diff_min + diff_ed <= bing_max
+ /*|| bing_max - diff_min - diff_ed >= bing_min*/;
}
};
@@ -130,13 +147,13 @@ struct box_longitude_range
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Geometry>
struct box_within_range<Geometry, 0, spherical_tag>
- : box_longitude_range<Geometry, box_within_longitude_check>
+ : box_longitude_range<Geometry, box_within_coord, box_within_longitude_diff>
{};
template <typename Geometry>
struct box_covered_by_range<Geometry, 0, spherical_tag>
- : box_longitude_range<Geometry, box_covered_by_longitude_check>
+ : box_longitude_range<Geometry, box_covered_by_coord, box_covered_by_longitude_diff>
{};
diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp
index 28ed8215e7..227a98f2ad 100644
--- a/boost/geometry/strategies/cartesian/point_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_box.hpp
@@ -33,9 +33,7 @@ namespace boost { namespace geometry { namespace strategy
namespace within
{
-
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct within_range
+struct within_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
@@ -44,9 +42,7 @@ struct within_range
}
};
-
-template <typename Geometry, std::size_t Dimension, typename CSTag>
-struct covered_by_range
+struct covered_by_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
@@ -55,32 +51,47 @@ struct covered_by_range
}
};
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct within_range
+ : within_coord
+{};
+
+
+template <typename Geometry, std::size_t Dimension, typename CSTag>
+struct covered_by_range
+ : covered_by_coord
+{};
+
// NOTE: the result would be the same if instead of structs defined below
// the above xxx_range were used with the following arguments:
// (min_value + diff_min, min_value, max_value)
-struct within_longitude_range
+struct within_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
CalcT const c0 = 0;
- return diff_min > c0 && min_value + diff_min < max_value;
+ return diff_min > c0
+ && (min_value + diff_min < max_value
+ /*|| max_value - diff_min > min_value*/);
}
};
-struct covered_by_longitude_range
+struct covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
- return min_value + diff_min <= max_value;
+ return min_value + diff_min <= max_value
+ /*|| max_value - diff_min >= min_value*/;
}
};
template <typename Geometry,
- typename ResultCheck>
+ typename CoordCheck,
+ typename DiffCheck>
struct longitude_range
{
template <typename Value1, typename Value2>
@@ -93,6 +104,11 @@ struct longitude_range
typedef typename coordinate_system<Geometry>::type::units units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+ if (CoordCheck::apply(value, min_value, max_value))
+ {
+ return true;
+ }
+
// min <= max <=> diff >= 0
calc_t const diff_ing = max_value - min_value;
@@ -105,7 +121,7 @@ struct longitude_range
// calculate positive longitude translation with min_value as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);
- return ResultCheck::template apply<calc_t>(diff_min, min_value, max_value);
+ return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value);
}
};
@@ -113,13 +129,13 @@ struct longitude_range
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Geometry>
struct within_range<Geometry, 0, spherical_tag>
- : longitude_range<Geometry, within_longitude_range>
+ : longitude_range<Geometry, within_coord, within_longitude_diff>
{};
template <typename Geometry>
struct covered_by_range<Geometry, 0, spherical_tag>
- : longitude_range<Geometry, covered_by_longitude_range>
+ : longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff>
{};
diff --git a/boost/geometry/strategies/geographic/distance_andoyer.hpp b/boost/geometry/strategies/geographic/distance_andoyer.hpp
index 1646727d09..1946cd1090 100644
--- a/boost/geometry/strategies/geographic/distance_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/distance_andoyer.hpp
@@ -20,9 +20,10 @@
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
-#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
@@ -89,7 +90,7 @@ public :
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& point1, Point2 const& point2) const
{
- return geometry::detail::andoyer_inverse
+ return geometry::formula::andoyer_inverse
<
typename calculation_type<Point1, Point2>::type,
true, false
diff --git a/boost/geometry/strategies/geographic/distance_thomas.hpp b/boost/geometry/strategies/geographic/distance_thomas.hpp
index 7252b723dd..39e0ecfa6f 100644
--- a/boost/geometry/strategies/geographic/distance_thomas.hpp
+++ b/boost/geometry/strategies/geographic/distance_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,7 +23,7 @@
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
-#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>
+#include <boost/geometry/formulas/thomas_inverse.hpp>
namespace boost { namespace geometry
{
@@ -78,7 +78,7 @@ public :
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& point1, Point2 const& point2) const
{
- return geometry::detail::thomas_inverse
+ return geometry::formula::thomas_inverse
<
typename calculation_type<Point1, Point2>::type,
true, false
diff --git a/boost/geometry/strategies/geographic/distance_vincenty.hpp b/boost/geometry/strategies/geographic/distance_vincenty.hpp
index 65bfa19939..e79e9aeb46 100644
--- a/boost/geometry/strategies/geographic/distance_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/distance_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,7 +23,7 @@
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
-#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
{
@@ -80,7 +80,7 @@ public :
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& point1, Point2 const& point2) const
{
- return geometry::detail::vincenty_inverse
+ return geometry::formula::vincenty_inverse
<
typename calculation_type<Point1, Point2>::type,
true, false
diff --git a/boost/geometry/strategies/geographic/side_andoyer.hpp b/boost/geometry/strategies/geographic/side_andoyer.hpp
index e0f0c04067..c3e71cd1cd 100644
--- a/boost/geometry/strategies/geographic/side_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/side_andoyer.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,7 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
-#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
#include <boost/geometry/strategies/geographic/side_detail.hpp>
@@ -36,9 +36,9 @@ namespace strategy { namespace side
*/
template <typename Model, typename CalculationType = void>
class andoyer
- : public detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType>
+ : public detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType>
{
- typedef detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType> base_t;
+ typedef detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType> base_t;
public:
andoyer(Model const& model = Model())
diff --git a/boost/geometry/strategies/geographic/side_detail.hpp b/boost/geometry/strategies/geographic/side_detail.hpp
index c00213d072..ce1b47c88e 100644
--- a/boost/geometry/strategies/geographic/side_detail.hpp
+++ b/boost/geometry/strategies/geographic/side_detail.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -46,7 +46,7 @@ namespace detail
\tparam Model Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <template<typename, bool, bool> class InverseFormula,
+template <template<typename, bool, bool, bool, bool, bool> class InverseFormula,
typename Model,
typename CalculationType = void>
class by_azimuth
@@ -68,7 +68,7 @@ public:
>::type
>::type calc_t;
- typedef InverseFormula<calc_t, false, true> inverse_formula;
+ typedef InverseFormula<calc_t, false, true, false, false, false> inverse_formula;
calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
diff --git a/boost/geometry/strategies/geographic/side_thomas.hpp b/boost/geometry/strategies/geographic/side_thomas.hpp
index a96cabdaab..96b0323307 100644
--- a/boost/geometry/strategies/geographic/side_thomas.hpp
+++ b/boost/geometry/strategies/geographic/side_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,7 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
-#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>
+#include <boost/geometry/formulas/thomas_inverse.hpp>
#include <boost/geometry/strategies/geographic/side_detail.hpp>
@@ -36,9 +36,9 @@ namespace strategy { namespace side
*/
template <typename Model, typename CalculationType = void>
class thomas
- : public detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType>
+ : public detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType>
{
- typedef detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType> base_t;
+ typedef detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType> base_t;
public:
thomas(Model const& model = Model())
diff --git a/boost/geometry/strategies/geographic/side_vincenty.hpp b/boost/geometry/strategies/geographic/side_vincenty.hpp
index a8ef9550d6..103277a8bd 100644
--- a/boost/geometry/strategies/geographic/side_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/side_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,7 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
-#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
#include <boost/geometry/strategies/geographic/side_detail.hpp>
@@ -36,9 +36,9 @@ namespace strategy { namespace side
*/
template <typename Model, typename CalculationType = void>
class vincenty
- : public detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType>
+ : public detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType>
{
- typedef detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType> base_t;
+ typedef detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType> base_t;
public:
vincenty(Model const& model = Model())
diff --git a/boost/graph/adjacency_iterator.hpp b/boost/graph/adjacency_iterator.hpp
index d500606443..c134fe5ad3 100644
--- a/boost/graph/adjacency_iterator.hpp
+++ b/boost/graph/adjacency_iterator.hpp
@@ -10,6 +10,7 @@
#ifndef BOOST_ADJACENCY_ITERATOR_HPP
#define BOOST_ADJACENCY_ITERATOR_HPP
+#include <boost/detail/iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/graph/graph_traits.hpp>
diff --git a/boost/graph/adjacency_list.hpp b/boost/graph/adjacency_list.hpp
index d7fbc06d87..da80063df4 100644
--- a/boost/graph/adjacency_list.hpp
+++ b/boost/graph/adjacency_list.hpp
@@ -20,14 +20,6 @@
#include <boost/unordered_set.hpp>
-#if !defined BOOST_NO_SLIST
-# ifdef BOOST_SLIST_HEADER
-# include BOOST_SLIST_HEADER
-# else
-# include <slist>
-# endif
-#endif
-
#include <boost/scoped_ptr.hpp>
#include <boost/graph/graph_traits.hpp>
@@ -52,10 +44,6 @@ namespace boost {
// to map the selectors to the container type used to implement the
// graph.
-#if !defined BOOST_NO_SLIST
- struct slistS {};
-#endif
-
struct vecS { };
struct listS { };
struct setS { };
@@ -74,12 +62,7 @@ namespace boost {
struct container_gen<listS, ValueType> {
typedef std::list<ValueType> type;
};
-#if !defined BOOST_NO_SLIST
- template <class ValueType>
- struct container_gen<slistS, ValueType> {
- typedef BOOST_STD_EXTENSION_NAMESPACE::slist<ValueType> type;
- };
-#endif
+
template <class ValueType>
struct container_gen<vecS, ValueType> {
typedef std::vector<ValueType> type;
@@ -136,12 +119,6 @@ namespace boost {
struct parallel_edge_traits<listS> {
typedef allow_parallel_edge_tag type; };
-#if !defined BOOST_NO_SLIST