aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-09-17 22:03:44 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-09-17 22:03:44 +0300
commit49726f2627f20969d8e6358fc107bdf139c87f99 (patch)
treef94d610e293cb577fbf973b1d0ac07c005c948d0 /contrib/restricted
parente4065899cddff8a7bde3bc774f33e9b6bebd961c (diff)
downloadydb-49726f2627f20969d8e6358fc107bdf139c87f99.tar.gz
Update contrib/restricted/boost/interprocess to 1.80.0
Diffstat (limited to 'contrib/restricted')
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/container_or_allocator_rebind.hpp53
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/container_rebind.hpp163
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/flat_tree.hpp1698
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/is_container.hpp72
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/is_contiguous_container.hpp82
-rw-r--r--contrib/restricted/boost/container/include/boost/container/detail/is_sorted.hpp57
-rw-r--r--contrib/restricted/boost/container/include/boost/container/flat_map.hpp3069
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/allocators/detail/allocator_common.hpp3
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/containers/allocation_type.hpp2
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/atomic.hpp67
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/char_wchar_holder.hpp127
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/config_external_begin.hpp5
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/in_place_interface.hpp4
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/intermodule_singleton_common.hpp25
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_file_functions.hpp202
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp20
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/posix_time_types_wrk.hpp51
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/segment_manager_helper.hpp22
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/shared_dir_helpers.hpp104
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/timed_utils.hpp388
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/utilities.hpp6
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/win32_api.hpp1737
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/windows_intermodule_singleton.hpp11
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/detail/workaround.hpp86
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/errors.hpp27
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/exceptions.hpp31
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/mapped_region.hpp65
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp29
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/permissions.hpp18
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/shared_memory_object.hpp158
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/deleter.hpp2
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp2
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/shared_count.hpp24
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp21
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/scoped_ptr.hpp20
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp14
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/weak_ptr.hpp4
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/streams/bufferstream.hpp18
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/cv_status.hpp29
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/common_algorithms.hpp58
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp214
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/locks.hpp40
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_condition.hpp66
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_mutex.hpp93
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/lock_options.hpp8
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/condition.hpp44
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/mutex.hpp63
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/pthread_helpers.hpp10
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp48
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/timepoint_to_timespec.hpp87
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/scoped_lock.hpp61
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/condition.hpp404
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/mutex.hpp39
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/condition.hpp63
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/mutex.hpp47
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/semaphore.hpp46
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/sync_utils.hpp107
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp7
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp7
-rw-r--r--contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_wrapper_common.hpp68
-rw-r--r--contrib/restricted/boost/move/include/boost/move/algo/adaptive_sort.hpp654
-rw-r--r--contrib/restricted/boost/move/include/boost/move/algo/detail/pdqsort.hpp344
-rw-r--r--contrib/restricted/boost/python/README.md4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/call.hpp4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/call_method.hpp2
-rw-r--r--contrib/restricted/boost/python/include/boost/python/def_visitor.hpp4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/detail/caller.hpp31
-rw-r--r--contrib/restricted/boost/python/include/boost/python/detail/config.hpp7
-rw-r--r--contrib/restricted/boost/python/include/boost/python/detail/wrap_python.hpp40
-rw-r--r--contrib/restricted/boost/python/include/boost/python/list.hpp2
-rw-r--r--contrib/restricted/boost/python/include/boost/python/long.hpp4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/object/iterator.hpp4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/object/make_instance.hpp2
-rw-r--r--contrib/restricted/boost/python/include/boost/python/other.hpp8
-rw-r--r--contrib/restricted/boost/python/include/boost/python/override.hpp4
-rw-r--r--contrib/restricted/boost/python/include/boost/python/ptr.hpp8
-rw-r--r--contrib/restricted/boost/python/src/exec.cpp4
-rw-r--r--contrib/restricted/boost/python/src/long.cpp8
-rw-r--r--contrib/restricted/boost/python/src/module.cpp2
-rw-r--r--contrib/restricted/boost/python/src/object/class.cpp19
-rw-r--r--contrib/restricted/boost/python/src/object/enum.cpp2
-rw-r--r--contrib/restricted/boost/python/src/object/function.cpp7
-rw-r--r--contrib/restricted/boost/python/src/object/life_support.cpp2
-rw-r--r--contrib/restricted/boost/python/src/wrapper.cpp4
-rw-r--r--contrib/restricted/boost/winapi/include/boost/winapi/directory_management.hpp106
-rw-r--r--contrib/restricted/boost/winapi/include/boost/winapi/file_mapping.hpp262
-rw-r--r--contrib/restricted/boost/winapi/include/boost/winapi/get_system_directory.hpp64
-rw-r--r--contrib/restricted/boost/winapi/include/boost/winapi/mutex.hpp185
-rw-r--r--contrib/restricted/boost/winapi/include/boost/winapi/security.hpp89
89 files changed, 9682 insertions, 2290 deletions
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/container_or_allocator_rebind.hpp b/contrib/restricted/boost/container/include/boost/container/detail/container_or_allocator_rebind.hpp
new file mode 100644
index 0000000000..1525e41d9d
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/container_or_allocator_rebind.hpp
@@ -0,0 +1,53 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
+#define BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/container_rebind.hpp>
+#include <boost/container/detail/is_container.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class AllocatorOrContainer, class ToType, bool = is_container<AllocatorOrContainer>::value>
+struct container_or_allocator_rebind_impl
+ : container_rebind<AllocatorOrContainer, ToType>
+{};
+
+template<class AllocatorOrContainer, class ToType>
+struct container_or_allocator_rebind_impl<AllocatorOrContainer, ToType, false>
+ : allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc<ToType>
+{};
+
+template<class ToType>
+struct container_or_allocator_rebind_impl<void, ToType, false>
+ : real_allocator<ToType, void>
+{};
+
+template<class AllocatorOrContainer, class ToType>
+struct container_or_allocator_rebind
+ : container_or_allocator_rebind_impl<AllocatorOrContainer, ToType>
+{};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/container_rebind.hpp b/contrib/restricted/boost/container/include/boost/container/detail/container_rebind.hpp
new file mode 100644
index 0000000000..854291ae7c
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/container_rebind.hpp
@@ -0,0 +1,163 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
+#define BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+ template <class Cont, class U>
+ struct container_rebind;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <template <class, class, class...> class Cont, typename V, typename A, class... An, class U>
+ struct container_rebind<Cont<V, A, An...>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, An...> type;
+ };
+
+ //Needed for non-conforming compilers like GCC 4.3
+ template <template <class, class> class Cont, typename V, typename A, class U>
+ struct container_rebind<Cont<V, A>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class> class Cont, typename V, class U>
+ struct container_rebind<Cont<V>, U>
+ {
+ typedef Cont<U> type;
+ };
+
+#else //C++03 compilers
+
+ template <template <class> class Cont //0arg
+ , typename V
+ , class U>
+ struct container_rebind<Cont<V>, U>
+ {
+ typedef Cont<U> type;
+ };
+
+ template <template <class, class> class Cont //0arg
+ , typename V, typename A
+ , class U>
+ struct container_rebind<Cont<V, A>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class, class, class> class Cont //1arg
+ , typename V, typename A, class P0
+ , class U>
+ struct container_rebind<Cont<V, A, P0>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0> type;
+ };
+
+ template <template <class, class, class, class> class Cont //2arg
+ , typename V, typename A, class P0, class P1
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1> type;
+ };
+
+ template <template <class, class, class, class, class> class Cont //3arg
+ , typename V, typename A, class P0, class P1, class P2
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
+ };
+
+ template <template <class, class, class, class, class, class> class Cont //4arg
+ , typename V, typename A, class P0, class P1, class P2, class P3
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
+ };
+
+ template <template <class, class, class, class, class, class, class> class Cont //5arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class> class Cont //6arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class> class Cont //7arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class, class> class Cont //8arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
+ {
+ typedef Cont<U, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
+ };
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //for small_vector,static_vector
+
+ template <typename V, std::size_t N, typename A, typename O, class U>
+ struct container_rebind<small_vector<V, N, A, O>, U>
+ {
+ typedef small_vector<U, N, typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type, O> type;
+ };
+
+ template <typename V, std::size_t N, typename O, class U>
+ struct container_rebind<static_vector<V, N, O>, U>
+ {
+ typedef static_vector<U, N, O> type;
+ };
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/flat_tree.hpp b/contrib/restricted/boost/container/include/boost/container/detail/flat_tree.hpp
new file mode 100644
index 0000000000..bbc89589b5
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/flat_tree.hpp
@@ -0,0 +1,1698 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_FLAT_TREE_HPP
+#define BOOST_CONTAINER_FLAT_TREE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/container_fwd.hpp>
+
+#include <boost/move/utility_core.hpp>
+
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator_traits.hpp>
+
+#include <boost/container/detail/value_init.hpp>
+#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/is_sorted.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/is_contiguous_container.hpp>
+#include <boost/container/detail/is_container.hpp>
+
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+
+#include <boost/move/make_unique.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/detail/force_ptr.hpp>
+#include <boost/move/algo/adaptive_sort.hpp>
+#include <boost/move/algo/detail/pdqsort.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
+#endif
+
+//merge_unique
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge_unique
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//merge_equal
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//index_of
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME index_of
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//nth
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME nth
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//reserve
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME reserve
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic pop
+#endif
+
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+///////////////////////////////////////
+//
+// Helper functions to merge elements
+//
+///////////////////////////////////////
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
+
+///////////////////////////////////////
+//
+// flat_tree_container_inplace_merge
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_container_inplace_merge //is_contiguous_container == true
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
+{
+ typedef typename SequenceContainer::value_type value_type;
+ value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
+ value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
+ value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
+ boost::movelib::adaptive_merge
+ (braw, iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
+}
+
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_container_inplace_merge //is_contiguous_container == false
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::false_)
+{
+ boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_container_inplace_sort_ending
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_container_inplace_sort_ending //is_contiguous_container == true
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
+{
+ typedef typename SequenceContainer::value_type value_type;
+ value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
+ value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
+ boost::movelib::adaptive_sort
+ (iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
+}
+
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_container_inplace_sort_ending //is_contiguous_container == false
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::false_)
+{
+ boost::movelib::adaptive_sort(it, dest.end(), comp);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_merge
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
+{
+ dest.merge(first, last, comp);
+}
+
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal //has_merge_unique == false
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
+{
+ typedef typename SequenceContainer::iterator iterator;
+ iterator const it = dest.insert( dest.end(), first, last );
+ dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
+ (flat_tree_container_inplace_merge)(dest, it, comp, contiguous_tag);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_merge_unique
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == true
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
+{
+ dest.merge_unique(first, last, comp);
+}
+
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == false
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
+{
+ typedef typename SequenceContainer::iterator iterator;
+ typedef typename SequenceContainer::size_type size_type;
+ typedef typename SequenceContainer::difference_type difference_type;
+
+ size_type const old_sz = dest.size();
+ iterator const first_new = dest.insert(dest.cend(), first, last );
+ iterator e = boost::movelib::inplace_set_unique_difference(first_new, dest.end(), dest.begin(), first_new, comp);
+ dest.erase(e, dest.end());
+ dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
+ (flat_tree_container_inplace_merge)(dest, dest.begin() + difference_type(old_sz), comp, contiguous_tag);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_index_of
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_index_of // has_index_of == true
+ (SequenceContainer& cont, Iterator p, dtl::true_)
+{
+ return cont.index_of(p);
+}
+
+template<class SequenceContainer, class Iterator>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_index_of // has_index_of == false
+ (SequenceContainer& cont, Iterator p, dtl::false_)
+{
+ typedef typename SequenceContainer::size_type size_type;
+ return static_cast<size_type>(p - cont.begin());
+}
+
+///////////////////////////////////////
+//
+// flat_tree_nth
+//
+///////////////////////////////////////
+template<class Iterator, class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE Iterator
+ flat_tree_nth // has_nth == true
+ (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::true_)
+{
+ return cont.nth(n);
+}
+
+template<class Iterator, class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE Iterator
+ flat_tree_nth // has_nth == false
+ (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::false_)
+{
+ return cont.begin()+ typename SequenceContainer::difference_type(n);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_get_stored_allocator
+//
+///////////////////////////////////////
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
+ flat_tree_get_stored_allocator // has_get_stored_allocator == true
+ (SequenceContainer& cont, dtl::true_)
+{
+ return cont.get_stored_allocator();
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_type &
+ flat_tree_get_stored_allocator // has_get_stored_allocator == true
+ (const SequenceContainer& cont, dtl::true_)
+{
+ return cont.get_stored_allocator();
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
+ flat_tree_get_stored_allocator // has_get_stored_allocator == false
+ (SequenceContainer& cont, dtl::false_)
+{
+ return cont.get_allocator();
+}
+
+///////////////////////////////////////
+//
+// flat_tree_adopt_sequence_equal
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
+{
+ if(tseq.capacity() >= (seq.capacity() - seq.size())) {
+ tseq.clear();
+ boost::movelib::adaptive_sort
+ (boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp
+ , boost::movelib::iterator_to_raw_pointer(tseq.begin())
+ , tseq.capacity());
+ }
+ else{
+ boost::movelib::adaptive_sort
+ (boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , seq.capacity() - seq.size());
+ }
+}
+
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_adopt_sequence_equal // is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
+{
+ flat_tree_sort_contiguous_to_adopt(tseq, boost::move(seq), comp);
+ tseq = boost::move(seq);
+}
+
+template<class SequenceContainer, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_adopt_sequence_equal // is_contiguous_container == false
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
+{
+ boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
+ tseq = boost::move(seq);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_adopt_sequence_unique
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_unique// is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
+{
+ boost::movelib::pdqsort
+ ( boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp);
+ seq.erase(boost::movelib::unique
+ (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
+ tseq = boost::move(seq);
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_unique// is_contiguous_container == false
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
+{
+ boost::movelib::pdqsort(seq.begin(), seq.end(), comp);
+ seq.erase(boost::movelib::unique
+ (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
+ tseq = boost::move(seq);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_reserve
+//
+///////////////////////////////////////
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE void // has_reserve == true
+ flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
+{
+ tseq.reserve(cap);
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE void // has_reserve == false
+ flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_)
+{
+}
+
+///////////////////////////////////////
+//
+// flat_tree_capacity
+//
+///////////////////////////////////////
+template<class SequenceContainer> // has_capacity == true
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
+{
+ return tseq.capacity();
+}
+
+template<class SequenceContainer> // has_capacity == false
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_capacity(const SequenceContainer &tseq, dtl::false_)
+{
+ return tseq.size();
+}
+
+///////////////////////////////////////
+//
+// flat_tree_value_compare
+//
+///////////////////////////////////////
+
+template<class Compare, class Value, class KeyOfValue>
+class flat_tree_value_compare
+ : private Compare
+{
+ typedef Value first_argument_type;
+ typedef Value second_argument_type;
+ typedef bool return_type;
+ public:
+ BOOST_CONTAINER_FORCEINLINE flat_tree_value_compare()
+ : Compare()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree_value_compare(const Compare &pred)
+ : Compare(pred)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const Value& lhs, const Value& rhs) const
+ {
+ KeyOfValue key_extract;
+ return Compare::operator()(key_extract(lhs), key_extract(rhs));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE const Compare &get_comp() const
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE Compare &get_comp()
+ { return *this; }
+};
+
+
+///////////////////////////////////////
+//
+// select_container_type
+//
+///////////////////////////////////////
+template < class Value, class AllocatorOrContainer
+ , bool = boost::container::dtl::is_container<AllocatorOrContainer>::value
+ >
+struct select_container_type
+{
+ typedef AllocatorOrContainer type;
+};
+
+template <class Value, class AllocatorOrContainer>
+struct select_container_type<Value, AllocatorOrContainer, false>
+{
+ typedef boost::container::vector<Value, typename real_allocator<Value, AllocatorOrContainer>::type> type;
+};
+
+
+///////////////////////////////////////
+//
+// flat_tree
+//
+///////////////////////////////////////
+template <class Value, class KeyOfValue,
+ class Compare, class AllocatorOrContainer>
+class flat_tree
+{
+ public:
+ typedef typename select_container_type<Value, AllocatorOrContainer>::type container_type;
+ typedef container_type sequence_type; //For backwards compatibility
+
+ private:
+ typedef typename container_type::allocator_type allocator_t;
+ typedef allocator_traits<allocator_t> allocator_traits_type;
+
+ public:
+ typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
+
+ private:
+
+ struct Data
+ //Inherit from value_compare to do EBO
+ : public value_compare
+ {
+ BOOST_COPYABLE_AND_MOVABLE(Data)
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE Data()
+ : value_compare(), m_seq()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit Data(const allocator_t &alloc)
+ : value_compare(), m_seq(alloc)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit Data(const Compare &comp)
+ : value_compare(comp), m_seq()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE Data(const Compare &comp, const allocator_t &alloc)
+ : value_compare(comp), m_seq(alloc)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit Data(const Data &d)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE Data(BOOST_RV_REF(Data) d)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE Data(const Data &d, const allocator_t &a)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE Data(BOOST_RV_REF(Data) d, const allocator_t &a)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
+ {}
+
+ Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
+ {
+ this->value_compare::operator=(d);
+ m_seq = d.m_seq;
+ return *this;
+ }
+
+ Data& operator=(BOOST_RV_REF(Data) d)
+ {
+ this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
+ m_seq = boost::move(d.m_seq);
+ return *this;
+ }
+
+ void swap(Data &d)
+ {
+ value_compare& mycomp = *this, & othercomp = d;
+ boost::adl_move_swap(mycomp, othercomp);
+ this->m_seq.swap(d.m_seq);
+ }
+
+ container_type m_seq;
+ };
+
+ Data m_data;
+ BOOST_COPYABLE_AND_MOVABLE(flat_tree)
+
+ public:
+
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::const_pointer const_pointer;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::const_reference const_reference;
+ typedef typename KeyOfValue::type key_type;
+ typedef Compare key_compare;
+ typedef typename container_type::allocator_type allocator_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::iterator iterator;
+ typedef typename container_type::const_iterator const_iterator;
+ typedef typename container_type::reverse_iterator reverse_iterator;
+ typedef typename container_type::const_reverse_iterator const_reverse_iterator;
+
+ //!Standard extension
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::, container_type
+ ,stored_allocator_type, allocator_type) stored_allocator_type;
+
+ static const bool has_stored_allocator_type =
+ BOOST_INTRUSIVE_HAS_TYPE(boost::container::dtl::, container_type, stored_allocator_type);
+
+ private:
+ typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
+
+ public:
+ typedef typename dtl::if_c
+ <has_stored_allocator_type, const stored_allocator_type &, allocator_type>::type get_stored_allocator_const_return_t;
+
+ typedef typename dtl::if_c
+ <has_stored_allocator_type, stored_allocator_type &, allocator_type>::type get_stored_allocator_noconst_return_t;
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree()
+ : m_data()
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const Compare& comp)
+ : m_data(comp)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a)
+ : m_data(a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x)
+ : m_data(x.m_data)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_data(boost::move(x.m_data))
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x, const allocator_type &a)
+ : m_data(x.m_data, a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
+ : m_data(boost::move(x.m_data), a)
+ { }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp)
+ : m_data(comp)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const allocator_type& a)
+ : m_data(a)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE ~flat_tree()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
+ { m_data = x.m_data; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { m_data = boost::move(x.m_data); return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const
+ { return static_cast<const value_compare &>(this->m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp()
+ { return static_cast<value_compare &>(this->m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE const key_compare &priv_key_comp() const
+ { return this->priv_value_comp().get_comp(); }
+
+ BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp()
+ { return this->priv_value_comp().get_comp(); }
+
+ struct insert_commit_data
+ {
+ const_iterator position;
+ };
+
+ public:
+ // accessors:
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ Compare key_comp() const
+ { return this->m_data.get_comp(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ value_compare value_comp() const
+ { return this->m_data; }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ allocator_type get_allocator() const
+ { return this->m_data.m_seq.get_allocator(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ get_stored_allocator_const_return_t get_stored_allocator() const
+ {
+ return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ get_stored_allocator_noconst_return_t get_stored_allocator()
+ {
+ return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator begin()
+ { return this->m_data.m_seq.begin(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator begin() const
+ { return this->cbegin(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cbegin() const
+ { return this->m_data.m_seq.begin(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator end()
+ { return this->m_data.m_seq.end(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator end() const
+ { return this->cend(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cend() const
+ { return this->m_data.m_seq.end(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rbegin()
+ { return reverse_iterator(this->end()); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rbegin() const
+ { return this->crbegin(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(this->cend()); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rend()
+ { return reverse_iterator(this->begin()); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rend() const
+ { return this->crend(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crend() const
+ { return const_reverse_iterator(this->cbegin()); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool empty() const
+ { return this->m_data.m_seq.empty(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type size() const
+ { return this->m_data.m_seq.size(); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type max_size() const
+ { return this->m_data.m_seq.max_size(); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { this->m_data.swap(other.m_data); }
+
+ public:
+ // insert/erase
+ std::pair<iterator,bool> insert_unique(const value_type& val)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
+ ret.first = ret.second ? this->priv_insert_commit(data, val)
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ return ret;
+ }
+
+ std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
+ ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ return ret;
+ }
+
+ iterator insert_equal(const value_type& val)
+ {
+ iterator i = this->upper_bound(KeyOfValue()(val));
+ i = this->m_data.m_seq.insert(i, val);
+ return i;
+ }
+
+ iterator insert_equal(BOOST_RV_REF(value_type) mval)
+ {
+ iterator i = this->upper_bound(KeyOfValue()(mval));
+ i = this->m_data.m_seq.insert(i, boost::move(mval));
+ return i;
+ }
+
+ iterator insert_unique(const_iterator hint, const value_type& val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
+ ? this->priv_insert_commit(data, val)
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ }
+
+ iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
+ ? this->priv_insert_commit(data, boost::move(val))
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ }
+
+ iterator insert_equal(const_iterator hint, const value_type& val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ this->priv_insert_equal_prepare(hint, val, data);
+ return this->priv_insert_commit(data, val);
+ }
+
+ iterator insert_equal(const_iterator hint, BOOST_RV_REF(value_type) mval)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ this->priv_insert_equal_prepare(hint, mval, data);
+ return this->priv_insert_commit(data, boost::move(mval));
+ }
+
+ template <class InIt>
+ void insert_unique(InIt first, InIt last)
+ {
+ dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
+ container_type &seq = this->m_data.m_seq;
+ value_compare &val_cmp = this->priv_value_comp();
+
+ //Step 1: put new elements in the back
+ typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
+
+ //Step 2: sort them
+ boost::movelib::pdqsort(it, seq.end(), val_cmp);
+
+ //Step 3: only left unique values from the back not already present in the original range
+ typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
+ (it, seq.end(), seq.begin(), it, val_cmp);
+
+ seq.erase(e, seq.cend());
+ //it might be invalidated by erasing [e, seq.end) if e == it
+ if (it != e)
+ {
+ //Step 4: merge both ranges
+ (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
+ }
+ }
+
+ template <class InIt>
+ void insert_equal(InIt first, InIt last)
+ {
+ dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
+ container_type &seq = this->m_data.m_seq;
+ typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
+ (flat_tree_container_inplace_sort_ending)(seq, it, this->priv_value_comp(), contiguous_tag);
+ (flat_tree_container_inplace_merge) (seq, it, this->priv_value_comp(), contiguous_tag);
+ }
+
+ //Ordered
+
+ template <class InIt>
+ void insert_equal(ordered_range_t, InIt first, InIt last)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
+ (flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
+ }
+
+ template <class InIt>
+ void insert_unique(ordered_unique_range_t, InIt first, InIt last)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
+ (flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
+ }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
+ {
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v), ::boost::forward<Args>(args)... );
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);
+ return this->insert_unique(::boost::move(*pval));
+ }
+
+ template <class... Args>
+ iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ //hint checked in insert_unique
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v), ::boost::forward<Args>(args)... );
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);
+ return this->insert_unique(hint, ::boost::move(*pval));
+ }
+
+ template <class... Args>
+ iterator emplace_equal(BOOST_FWD_REF(Args)... args)
+ {
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v), ::boost::forward<Args>(args)... );
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);
+ return this->insert_equal(::boost::move(*pval));
+ }
+
+ template <class... Args>
+ iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ //hint checked in insert_equal
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v), ::boost::forward<Args>(args)... );
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);
+ return this->insert_equal(hint, ::boost::move(*pval));
+ }
+
+ template <class KeyType, class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
+ (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ const key_type & k = key;
+ ret.second = hint == const_iterator()
+ ? this->priv_insert_unique_prepare(k, data)
+ : this->priv_insert_unique_prepare(hint, k, data);
+
+ if(!ret.second){
+ ret.first = this->nth(size_type(data.position - this->cbegin()));
+ }
+ else{
+ ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
+ }
+ return ret;
+ }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
+ {\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);\
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);\
+ return this->insert_unique(::boost::move(*pval));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);\
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);\
+ return this->insert_unique(hint, ::boost::move(*pval));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace_equal(BOOST_MOVE_UREF##N)\
+ {\
+ typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);\
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);\
+ return this->insert_equal(::boost::move(*pval));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ typename dtl::aligned_storage <sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, move_detail::force_ptr<value_type *>(&v) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_type *pval = move_detail::force_ptr<value_type *>(&v);\
+ value_destructor<stored_allocator_type, value_type> d(a, *pval);\
+ return this->insert_equal(hint, ::boost::move(*pval));\
+ }\
+ template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
+ try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ std::pair<iterator,bool> ret;\
+ insert_commit_data data;\
+ const key_type & k = key;\
+ ret.second = hint == const_iterator()\
+ ? this->priv_insert_unique_prepare(k, data)\
+ : this->priv_insert_unique_prepare(hint, k, data);\
+ \
+ if(!ret.second){\
+ ret.first = this->nth(size_type(data.position - this->cbegin()));\
+ }\
+ else{\
+ ret.first = this->m_data.m_seq.emplace(data.position, try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ return ret;\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class KeyType, class M>
+ std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
+ {
+ const key_type& k = key;
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = hint == const_iterator()
+ ? this->priv_insert_unique_prepare(k, data)
+ : this->priv_insert_unique_prepare(hint, k, data);
+ if(!ret.second){
+ ret.first = this->nth(size_type(data.position - this->cbegin()));
+ ret.first->second = boost::forward<M>(obj);
+ }
+ else{
+ ret.first = this->m_data.m_seq.emplace(data.position, boost::forward<KeyType>(key), boost::forward<M>(obj));
+ }
+ return ret;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position)
+ { return this->m_data.m_seq.erase(position); }
+
+ size_type erase(const key_type& k)
+ {
+ std::pair<iterator,iterator > itp = this->equal_range(k);
+ size_type ret = static_cast<size_type>(itp.second-itp.first);
+ if (ret){
+ this->m_data.m_seq.erase(itp.first, itp.second);
+ }
+ return ret;
+ }
+
+ size_type erase_unique(const key_type& k)
+ {
+ iterator i = this->find(k);
+ size_type ret = static_cast<size_type>(i != this->end());
+ if (ret)
+ this->erase(i);
+ return ret;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ { return this->m_data.m_seq.erase(first, last); }
+
+ BOOST_CONTAINER_FORCEINLINE void clear()
+ { this->m_data.m_seq.clear(); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
+ { this->m_data.m_seq.shrink_to_fit(); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_nth<container_type, size_type>::value;
+ return flat_tree_nth<iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_nth<container_type, size_type>::value;
+ return flat_tree_nth<const_iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_index_of<container_type, iterator>::value;
+ return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_index_of<container_type, const_iterator>::value;
+ return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
+ }
+
+ // set operations:
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ iterator find(const key_type& k)
+ {
+ iterator i = this->lower_bound(k);
+ iterator end_it = this->end();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ const_iterator find(const key_type& k) const
+ {
+ const_iterator i = this->lower_bound(k);
+
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ find(const K& k)
+ {
+ iterator i = this->lower_bound(k);
+ iterator end_it = this->end();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ find(const K& k) const
+ {
+ const_iterator i = this->lower_bound(k);
+
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ size_type count(const key_type& k) const
+ {
+ std::pair<const_iterator, const_iterator> p = this->equal_range(k);
+ size_type n = size_type(p.second - p.first);
+ return n;
+ }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD
+ typename dtl::enable_if_transparent<key_compare, K, size_type>::type
+ count(const K& k) const
+ {
+ std::pair<const_iterator, const_iterator> p = this->equal_range(k);
+ size_type n = size_type(p.second - p.first);
+ return n;
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE bool contains(const key_type& x) const
+ { return this->find(x) != this->cend(); }
+
+ template<typename K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, bool>::type
+ contains(const K& x) const
+ { return this->find(x) != this->cend(); }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
+ {
+ this->insert_unique( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
+ {
+ this->insert_equal( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree& source)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
+ (flat_tree_merge_unique)
+ ( this->m_data.m_seq
+ , boost::make_move_iterator(source.m_data.m_seq.begin())
+ , boost::make_move_iterator(source.m_data.m_seq.end())
+ , this->priv_value_comp()
+ , dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree& source)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
+ (flat_tree_merge_equal)
+ ( this->m_data.m_seq
+ , boost::make_move_iterator(source.m_data.m_seq.begin())
+ , boost::make_move_iterator(source.m_data.m_seq.end())
+ , this->priv_value_comp()
+ , dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator lower_bound(const key_type& k)
+ { return this->priv_lower_bound(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator lower_bound(const key_type& k) const
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ lower_bound(const K& k)
+ { return this->priv_lower_bound(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ lower_bound(const K& k) const
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator upper_bound(const key_type& k)
+ { return this->priv_upper_bound(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator upper_bound(const key_type& k) const
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,iterator>::type
+ upper_bound(const K& k)
+ { return this->priv_upper_bound(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,const_iterator>::type
+ upper_bound(const K& k) const
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator,iterator> equal_range(const key_type& k)
+ { return this->priv_equal_range(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
+ equal_range(const K& k)
+ { return this->priv_equal_range(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
+ equal_range(const K& k) const
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator, iterator> lower_bound_range(const key_type& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
+ { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
+ lower_bound_range(const K& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
+ lower_bound_range(const K& k) const
+ { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type capacity() const
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_capacity<container_type>::value;
+ return (flat_tree_capacity)(this->m_data.m_seq, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE
+ void reserve(size_type cnt)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_reserve<container_type, size_type>::value;
+ (flat_tree_reserve)(this->m_data.m_seq, cnt, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ container_type extract_sequence()
+ { return boost::move(m_data.m_seq); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ container_type &get_sequence_ref()
+ { return m_data.m_seq; }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const container_type &get_sequence_cref() const
+ { return m_data.m_seq; }
+
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
+ {
+ (flat_tree_adopt_sequence_equal)( m_data.m_seq, boost::move(seq), this->priv_value_comp()
+ , dtl::bool_<is_contiguous_container<container_type>::value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
+ {
+ (flat_tree_adopt_sequence_unique)(m_data.m_seq, boost::move(seq), this->priv_value_comp()
+ , dtl::bool_<is_contiguous_container<container_type>::value>());
+ }
+
+ void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
+ {
+ BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ m_data.m_seq = boost::move(seq);
+ }
+
+ void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
+ {
+ BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ m_data.m_seq = boost::move(seq);
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator==(const flat_tree& x, const flat_tree& y)
+ {
+ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<(const flat_tree& x, const flat_tree& y)
+ {
+ return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+ }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator!=(const flat_tree& x, const flat_tree& y)
+ { return !(x == y); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>(const flat_tree& x, const flat_tree& y)
+ { return y < x; }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<=(const flat_tree& x, const flat_tree& y)
+ { return !(y < x); }
+
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>=(const flat_tree& x, const flat_tree& y)
+ { return !(x < y); }
+
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_tree& x, flat_tree& y)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
+ { x.swap(y); }
+
+ private:
+
+ template <class InputIterator>
+ void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ //Call end() every iteration as reallocation might have invalidated iterators
+ if(unique_insertion){
+ this->insert_unique(first, last);
+ }
+ else{
+ this->insert_equal (first, last);
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos <= this->end());
+ }
+
+ // insert/erase
+ void priv_insert_equal_prepare
+ (const_iterator pos, const value_type& val, insert_commit_data &data)
+ {
+ // N1780
+ // To insert val at pos:
+ // if pos == end || val <= *pos
+ // if pos == begin || val >= *(pos-1)
+ // insert val before pos
+ // else
+ // insert val before upper_bound(val)
+ // else
+ // insert val before lower_bound(val)
+ const value_compare &val_cmp = this->m_data;
+
+ if(pos == this->cend() || !val_cmp(*pos, val)){
+ if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
+ data.position = pos;
+ }
+ else{
+ data.position =
+ this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
+ }
+ }
+ else{
+ data.position =
+ this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
+ }
+ }
+
+ bool priv_insert_unique_prepare
+ (const_iterator b, const_iterator e, const key_type& k, insert_commit_data &commit_data)
+ {
+ const key_compare &key_cmp = this->priv_key_comp();
+ commit_data.position = this->priv_lower_bound(b, e, k);
+ return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_insert_unique_prepare
+ (const key_type& k, insert_commit_data &commit_data)
+ { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
+
+ bool priv_insert_unique_prepare
+ (const_iterator pos, const key_type& k, insert_commit_data &commit_data)
+ {
+ //N1780. Props to Howard Hinnant!
+ //To insert k at pos:
+ //if pos == end || k <= *pos
+ // if pos == begin || k >= *(pos-1)
+ // insert k before pos
+ // else
+ // insert k before upper_bound(k)
+ //else if pos+1 == end || k <= *(pos+1)
+ // insert k after pos
+ //else
+ // insert k before lower_bound(k)
+ const key_compare &key_cmp = this->priv_key_comp();
+ const const_iterator cend_it = this->cend();
+ if(pos == cend_it || key_cmp(k, KeyOfValue()(*pos))){ //Check if k should go before end
+ const const_iterator cbeg = this->cbegin();
+ commit_data.position = pos;
+ if(pos == cbeg){ //If container is empty then insert it in the beginning
+ return true;
+ }
+ const_iterator prev(pos);
+ --prev;
+ if(key_cmp(KeyOfValue()(*prev), k)){ //If previous element was less, then it should go between prev and pos
+ return true;
+ }
+ else if(!key_cmp(k, KeyOfValue()(*prev))){ //If previous was equal then insertion should fail
+ commit_data.position = prev;
+ return false;
+ }
+ else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
+ //but reduce the search between beg and prev as prev is bigger than k
+ return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
+ }
+ }
+ else{
+ //The hint is before the insertion position, so insert it
+ //in the remaining range [pos, end)
+ return this->priv_insert_unique_prepare(pos, cend_it, k, commit_data);
+ }
+ }
+
+ template<class Convertible>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
+ (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
+ {
+ return this->m_data.m_seq.insert
+ ( commit_data.position
+ , boost::forward<Convertible>(convertible));
+ }
+
+ template <class RanIt, class K>
+ RanIt priv_lower_bound(RanIt first, const RanIt last,
+ const K & key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += difference_type(step);
+
+ if (key_cmp(key_extract(*middle), key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+ }
+
+ template <class RanIt, class K>
+ RanIt priv_upper_bound
+ (RanIt first, const RanIt last,const K & key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += difference_type(step);
+
+ if (key_cmp(key, key_extract(*middle))) {
+ len = step;
+ }
+ else{
+ first = ++middle;
+ len -= step + 1;
+ }
+ }
+ return first;
+ }
+
+ template <class RanIt, class K>
+ std::pair<RanIt, RanIt>
+ priv_equal_range(RanIt first, RanIt last, const K& key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += difference_type(step);
+
+ if (key_cmp(key_extract(*middle), key)){
+ first = ++middle;
+ len -= step + 1;
+ }
+ else if (key_cmp(key, key_extract(*middle))){
+ len = step;
+ }
+ else {
+ //Middle is equal to key
+ last = first;
+ last += difference_type(len);
+ RanIt const first_ret = this->priv_lower_bound(first, middle, key);
+ return std::pair<RanIt, RanIt>
+ ( first_ret, this->priv_upper_bound(++middle, last, key));
+ }
+ }
+ return std::pair<RanIt, RanIt>(first, first);
+ }
+
+ template<class RanIt, class K>
+ std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const K& k) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
+ if(lb != last && !key_cmp(k, key_extract(*lb))){
+ ++ub;
+ }
+ return std::pair<RanIt, RanIt>(lb, ub);
+ }
+};
+
+} //namespace dtl {
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class KeyOfValue,
+class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
+{
+ typedef boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> flat_tree;
+ typedef typename flat_tree::container_type container_type;
+ typedef typename flat_tree::key_compare key_compare;
+ static const bool value = ::boost::has_trivial_destructor_after_move<container_type>::value &&
+ ::boost::has_trivial_destructor_after_move<key_compare>::value;
+};
+
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_FLAT_TREE_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/is_container.hpp b/contrib/restricted/boost/container/include/boost/container/detail/is_container.hpp
new file mode 100644
index 0000000000..8ef0274d7a
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/is_container.hpp
@@ -0,0 +1,72 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
+#define BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
+#endif
+
+//empty
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME empty
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//size
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME size
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//#pragma GCC diagnostic ignored "-Wunused-result"
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic pop
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class Container>
+struct is_container
+{
+ static const bool value =
+ boost::container::is_container_detail::
+ has_member_function_callable_with_size <const Container>::value &&
+ boost::container::is_container_detail::
+ has_member_function_callable_with_empty<const Container>::value;
+};
+
+template <>
+struct is_container<void>
+{
+ static const bool value = false;
+};
+
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/is_contiguous_container.hpp b/contrib/restricted/boost/container/include/boost/container/detail/is_contiguous_container.hpp
new file mode 100644
index 0000000000..045de843a6
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/is_contiguous_container.hpp
@@ -0,0 +1,82 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
+#define BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
+#endif
+
+//data
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME data
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_contiguous_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//back_free_capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME back_free_capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace back_free_capacity_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//#pragma GCC diagnostic ignored "-Wunused-result"
+#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
+#pragma GCC diagnostic pop
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class Container>
+struct is_contiguous_container
+{
+ static const bool value =
+ boost::container::is_contiguous_container_detail::
+ has_member_function_callable_with_data<Container>::value &&
+ boost::container::is_contiguous_container_detail::
+ has_member_function_callable_with_data<const Container>::value;
+};
+
+
+template < class Container
+ , bool = boost::container::back_free_capacity_detail::
+ has_member_function_callable_with_back_free_capacity<const Container>::value>
+struct back_free_capacity
+{
+ static typename Container::size_type get(const Container &c)
+ { return c.back_free_capacity(); }
+};
+
+template < class Container>
+struct back_free_capacity<Container, false>
+{
+ static typename Container::size_type get(const Container &c)
+ { return c.capacity() - c.size(); }
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/detail/is_sorted.hpp b/contrib/restricted/boost/container/include/boost/container/detail/is_sorted.hpp
new file mode 100644
index 0000000000..315bab54d7
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/detail/is_sorted.hpp
@@ -0,0 +1,57 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
+#define BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class ForwardIterator, class Pred>
+bool is_sorted (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(pred(*next, *first))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+template <class ForwardIterator, class Pred>
+bool is_sorted_and_unique (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(!pred(*first, *next))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
diff --git a/contrib/restricted/boost/container/include/boost/container/flat_map.hpp b/contrib/restricted/boost/container/include/boost/container/flat_map.hpp
new file mode 100644
index 0000000000..0a85b9db4a
--- /dev/null
+++ b/contrib/restricted/boost/container/include/boost/container/flat_map.hpp
@@ -0,0 +1,3069 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_FLAT_MAP_HPP
+#define BOOST_CONTAINER_FLAT_MAP_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/flat_tree.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+// move
+#include <boost/move/utility_core.hpp>
+#include <boost/move/traits.hpp>
+// move/detail
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/detail/force_ptr.hpp>
+// intrusive
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal
+//others
+#include <boost/core/no_exceptions_support.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+class flat_multimap;
+
+namespace dtl{
+
+template<class D, class S>
+BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
+{ return *move_detail::force_ptr<D*>(&s); }
+
+template<class D, class S>
+BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
+{ return *move_detail::force_ptr<const D*>(&s); }
+
+template<class D, class S>
+BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
+{
+ const D *const vp = move_detail::force_ptr<const D *>(&s);
+ D ret_val(*vp);
+ return ret_val;
+}
+
+} //namespace dtl{
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A flat_map is a kind of associative container that supports unique keys (contains at
+//! most one of each key value) and provides for fast retrieval of values of another
+//! type T based on the keys.
+//!
+//! A flat_map satisfies all of the requirements of a container, a reversible
+//! container and an associative container. A flat_map also provides
+//! most operations described for unique keys. For a
+//! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
+//! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
+//!
+//! flat_map is similar to std::map but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the key_type of the map
+//! \tparam Value is the <code>mapped_type</code>
+//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
+#else
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+#endif
+class flat_map
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_map)
+ //This is the tree that we should store if pair was movable
+ typedef dtl::flat_tree<
+ std::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ AllocatorOrContainer> tree_t;
+
+ //This is the real tree stored here. It's based on a movable pair
+ typedef dtl::flat_tree<
+ dtl::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
+ > impl_tree_t;
+ impl_tree_t m_flat_tree; // flat tree representing flat_map
+
+ typedef typename impl_tree_t::value_type impl_value_type;
+ typedef typename impl_tree_t::const_iterator impl_const_iterator;
+ typedef typename impl_tree_t::iterator impl_iterator;
+ typedef typename impl_tree_t::allocator_type impl_allocator_type;
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ typedef std::initializer_list<impl_value_type> impl_initializer_list;
+ #endif
+
+ typedef dtl::flat_tree_value_compare
+ < Compare
+ , dtl::select1st<Key>
+ , std::pair<Key, T> > value_compare_t;
+ typedef typename tree_t::iterator iterator_t;
+ typedef typename tree_t::const_iterator const_iterator_t;
+ typedef typename tree_t::reverse_iterator reverse_iterator_t;
+ typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
+
+ public:
+ typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
+
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
+ { return m_flat_tree; }
+
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
+ { return m_flat_tree; }
+
+ private:
+ typedef typename tree_t::get_stored_allocator_const_return_t get_stored_allocator_const_return_t;
+ typedef typename tree_t::get_stored_allocator_noconst_return_t get_stored_allocator_noconst_return_t;
+ typedef typename impl_tree_t::get_stored_allocator_const_return_t impl_get_stored_allocator_const_return_t;
+ typedef typename impl_tree_t::get_stored_allocator_noconst_return_t impl_get_stored_allocator_noconst_return_t;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Compare key_compare;
+ typedef std::pair<Key, T> value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+
+ //AllocatorOrContainer::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, value_type>::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty flat_map.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_map() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : m_flat_tree()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const allocator_type& a)
+ : m_flat_tree(dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! comparison object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_map(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last)
+ : m_flat_tree(true, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(true, first, last, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map
+ //! and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, Compare(), a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il)
+ : m_flat_tree( true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a)
+ : m_flat_tree( true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs a flat_map.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x)
+ : m_flat_tree(x.m_flat_tree)
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_map.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_flat_tree(boost::move(x.m_flat_tree))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a)
+ : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
+ : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
+ { m_flat_tree = x.m_flat_tree; return *this; }
+
+ //! <b>Effects</b>: Move constructs a flat_map.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_RV_REF(flat_map) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assign elements from il to *this
+ flat_map& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the allocator that
+ //! was passed to the object's constructor.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ get_stored_allocator_noconst_return_t get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator();
+ return dtl::force<stored_allocator_type>(r);
+ }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ get_stored_allocator_const_return_t get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ impl_get_stored_allocator_const_return_t r = m_flat_tree.get_stored_allocator();
+ return dtl::force<const stored_allocator_type>(r);
+ }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the container contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.empty(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.max_size(); }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), or the
+ //! underlying container has no `reserve` member, this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
+ //! to values might be invalidated.
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
+ { m_flat_tree.reserve(cnt); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
+ { m_flat_tree.shrink_to_fit(); }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! Effects: If there is no key equivalent to x in the flat_map, inserts
+ //! value_type(x, T()) into the flat_map.
+ //!
+ //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
+ mapped_type &operator[](const key_type& k);
+
+ //! Effects: If there is no key equivalent to x in the flat_map, inserts
+ //! value_type(move(x), T()) into the flat_map (the key is move-constructed)
+ //!
+ //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
+ mapped_type &operator[](key_type &&k);
+ #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
+ //in compilers like GCC 3.4, we can't catch temporaries
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
+ #endif
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic search time plus linear insertion time in case no equivalent key is present.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( impl_const_iterator(), k, ::boost::forward<M>(obj))
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy<iterator>
+ (this->m_flat_tree.insert_or_assign
+ ( dtl::force_copy<impl_const_iterator>(hint)
+ , k, ::boost::forward<M>(obj)).first
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy<iterator>
+ (this->m_flat_tree.insert_or_assign
+ ( dtl::force_copy<impl_const_iterator>(hint)
+ , ::boost::move(k), ::boost::forward<M>(obj)).first
+ );
+ }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type) const
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(iterator)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p)); }
+
+ //! Returns: A reference to the element whose key is equivalent to x.
+ //!
+ //! Throws: An exception object of type out_of_range if no such element is present.
+ //!
+ //! Complexity: logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD T& at(const key_type& k)
+ {
+ iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("flat_map::at key not found");
+ }
+ return i->second;
+ }
+
+ //! Returns: A reference to the element whose key is equivalent to x.
+ //!
+ //! Throws: An exception object of type out_of_range if no such element is present.
+ //!
+ //! Complexity: logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
+ {
+ const_iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("flat_map::at key not found");
+ }
+ return i->second;
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object x of type T constructed with
+ //! std::forward<Args>(args)... if and only if there is no element in the container
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ { return dtl::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.emplace_hint_unique( dtl::force_copy<impl_const_iterator>(hint)
+ , boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >(
+ m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>(m_flat_tree.try_emplace
+ (dtl::force_copy<impl_const_iterator>(hint), k, boost::forward<Args>(args)...).first);
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion time in case the key is not present.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p. Linear insertion time in case no equivalent key is present.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.try_emplace(dtl::force_copy
+ <impl_const_iterator>(hint), boost::move(k), boost::forward<Args>(args)...).first);
+ }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy< std::pair<iterator, bool> >\
+ (m_flat_tree.emplace_unique(BOOST_MOVE_FWD##N));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
+ (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy< std::pair<iterator, bool> >\
+ (m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
+ (dtl::force_copy<impl_const_iterator>(hint), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy< std::pair<iterator, bool> >\
+ (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
+ (dtl::force_copy<impl_const_iterator>(hint), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //! <b>Effects</b>: Inserts x if and only if there is no element in the container
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
+ { return dtl::force_copy<std::pair<iterator,bool> >(
+ m_flat_tree.insert_unique(dtl::force<const impl_value_type>(x))); }
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
+ {
+ return dtl::force_copy<std::pair<iterator,bool> >(
+ m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x))));
+ }
+
+ //! <b>Effects</b>: Inserts a new value_type constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class Pair>
+ BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
+ ( std::pair<iterator BOOST_MOVE_I bool>
+ , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
+ BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
+ insert(BOOST_FWD_REF(Pair) x)
+ {
+ return dtl::force_copy<std::pair<iterator,bool> >
+ (m_flat_tree.emplace_unique(boost::forward<Pair>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
+ , dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
+ , boost::move(dtl::force<impl_value_type>(x))));
+ }
+
+ //! <b>Effects</b>: Inserts an element constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class Pair>
+ BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
+ ( iterator
+ , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
+ BOOST_MOVE_I iterator>::type)
+ insert(const_iterator p, BOOST_FWD_REF(Pair) x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.emplace_hint_unique(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
+ }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(size()+N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { m_flat_tree.insert_unique(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
+ { m_flat_tree.insert_unique(ordered_unique_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_unique( dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_unique(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+#endif
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Move-inserts each element from source into *this a using
+ //! the comparison object of *this. If there is an element in a with key equivalent to the
+ //! key of an element from source, then that element is not moved from source.
+ //!
+ //! <b>Complexity</b>: Linear in this->size() + source.size().
+ //!
+ //! <b>Note</b>: Invalidates all iterators and references.
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Linear to the elements with keys bigger than p
+ //!
+ //! <b>Note</b>: Invalidates elements with keys
+ //! not less than the erased element.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
+ }
+
+ //! <b>Effects</b>: If present, erases the element in the container with key equivalent to x.
+ //!
+ //! <b>Returns</b>: Returns the number of erased elements (0/1).
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
+ { return m_flat_tree.erase_unique(x); }
+
+ //! <b>Effects</b>: Erases all the elements in the range [first, last).
+ //!
+ //! <b>Returns</b>: Returns last.
+ //!
+ //! <b>Complexity</b>: size()*N where N is the distance from first to last.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
+ , dtl::force_copy<impl_const_iterator>(last)));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_map& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { m_flat_tree.swap(x.m_flat_tree); }
+
+ //! <b>Effects</b>: erase(begin(),end()).
+ //!
+ //! <b>Postcondition</b>: size() == 0.
+ //!
+ //! <b>Complexity</b>: linear in size().
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { m_flat_tree.clear(); }
+
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ key_compare key_comp() const
+ { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ value_compare value_comp() const
+ { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
+
+ //////////////////////////////////////////////
+ //
+ // map operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator find(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator find(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator find(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator find(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type count(const key_type& x) const
+ { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type count(const K& x) const
+ //Don't use find() != end optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return m_flat_tree.count(x); }
+
+ //! <b>Returns</b>: Returns true if there is an element with key
+ //! equivalent to key in the container, otherwise false.
+ //!
+ //! <b>Complexity</b>: log(size()).
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool contains(const key_type& x) const
+ { return m_flat_tree.find(x) != m_flat_tree.end(); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: Returns true if there is an element with key
+ //! equivalent to key in the container, otherwise false.
+ //!
+ //! <b>Complexity</b>: log(size()).
+ template<typename K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool contains(const K& x) const
+ { return m_flat_tree.find(x) != m_flat_tree.end(); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator lower_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator lower_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator lower_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator lower_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key greater
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator upper_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! greater than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator upper_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key greater
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator upper_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! greater than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator upper_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator,iterator> equal_range(const K& x)
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> equal_range(const K& x) const
+ //Don't use lower_bound_range optimization here as transparent comparators with key K might
+ //return a different range than key_type (which can only return a single element range)
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
+ }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment. Erases non-unique elements.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //! and shall contain unique elements.
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Effects</b>: Returns a const view of the underlying sequence.
+ //!
+ //! <b>Complexity</b>: Constant
+ //!
+ //! <b>Throws</b>: Nothing
+ BOOST_CONTAINER_FORCEINLINE const sequence_type & sequence() const BOOST_NOEXCEPT
+ { return dtl::force<sequence_type>(m_flat_tree.get_sequence_cref()); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator==(const flat_map& x, const flat_map& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator!=(const flat_map& x, const flat_map& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<(const flat_map& x, const flat_map& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>(const flat_map& x, const flat_map& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<=(const flat_map& x, const flat_map& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>=(const flat_map& x, const flat_map& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_map& x, flat_map& y)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ mapped_type &priv_subscript(const key_type& k)
+ {
+ iterator i = this->lower_bound(k);
+ // i->first is greater than or equivalent to k.
+ if (i == end() || key_comp()(k, (*i).first)){
+ dtl::value_init<mapped_type> m;
+ impl_value_type v(k, ::boost::move(m.m_t));
+ i = this->insert(i, ::boost::move(v));
+ }
+ return (*i).second;
+ }
+ mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
+ {
+ key_type &k = mk;
+ iterator i = this->lower_bound(k);
+ // i->first is greater than or equivalent to k.
+ if (i == end() || key_comp()(k, (*i).first)){
+ dtl::value_init<mapped_type> m;
+ impl_value_type v(::boost::move(k), ::boost::move(m.m_t));
+ i = this->insert(i, ::boost::move(v));
+ }
+ return (*i).second;
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+
+template <typename InputIterator>
+flat_map(InputIterator, InputIterator) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>>;
+
+template < typename InputIterator, typename AllocatorOrCompare>
+ flat_map(InputIterator, InputIterator, AllocatorOrCompare const&) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , typename dtl::if_c< // Compare
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , std::less<it_based_non_const_first_type_t<InputIterator>>
+ , AllocatorOrCompare
+ >::type
+ , typename dtl::if_c< // Allocator
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , AllocatorOrCompare
+ , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
+ >::type
+ >;
+
+template < typename InputIterator, typename Compare, typename Allocator
+ , typename = dtl::require_nonallocator_t<Compare>
+ , typename = dtl::require_allocator_t<Allocator>>
+flat_map(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>>;
+
+template < typename InputIterator, typename AllocatorOrCompare>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator, AllocatorOrCompare const&) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , typename dtl::if_c< // Compare
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , std::less<it_based_non_const_first_type_t<InputIterator>>
+ , AllocatorOrCompare
+ >::type
+ , typename dtl::if_c< // Allocator
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , AllocatorOrCompare
+ , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
+ >::type
+ >;
+
+template < typename InputIterator, typename Compare, typename Allocator
+ , typename = dtl::require_nonallocator_t<Compare>
+ , typename = dtl::require_allocator_t<Allocator>>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_map< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , Compare
+ , Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
+{
+ typedef ::boost::container::dtl::pair<Key, T> value_t;
+ typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
+ typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A flat_multimap is a kind of associative container that supports equivalent keys
+//! (possibly containing multiple copies of the same key value) and provides for
+//! fast retrieval of values of another type T based on the keys.
+//!
+//! A flat_multimap satisfies all of the requirements of a container and of a reversible
+//! container and of an associative container. For a
+//! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
+//! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
+//!
+//! flat_multimap is similar to std::multimap but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the key_type of the map
+//! \tparam Value is the <code>mapped_type</code>
+//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
+#else
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+#endif
+class flat_multimap
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
+ typedef dtl::flat_tree<
+ std::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ AllocatorOrContainer> tree_t;
+ //This is the real tree stored here. It's based on a movable pair
+ typedef dtl::flat_tree<
+ dtl::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
+ > impl_tree_t;
+ impl_tree_t m_flat_tree; // flat tree representing flat_map
+
+ typedef typename impl_tree_t::value_type impl_value_type;
+ typedef typename impl_tree_t::const_iterator impl_const_iterator;
+ typedef typename impl_tree_t::iterator impl_iterator;
+ typedef typename impl_tree_t::allocator_type impl_allocator_type;
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ typedef std::initializer_list<impl_value_type> impl_initializer_list;
+ #endif
+
+ typedef dtl::flat_tree_value_compare
+ < Compare
+ , dtl::select1st<Key>
+ , std::pair<Key, T> > value_compare_t;
+ typedef typename tree_t::iterator iterator_t;
+ typedef typename tree_t::const_iterator const_iterator_t;
+ typedef typename tree_t::reverse_iterator reverse_iterator_t;
+ typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
+
+ public:
+ typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
+
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
+ { return m_flat_tree; }
+
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
+ { return m_flat_tree; }
+
+ private:
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Compare key_compare;
+ typedef std::pair<Key, T> value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+
+ //AllocatorOrContainer::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, value_type>::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty flat_map.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_multimap()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : m_flat_tree()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const allocator_type& a)
+ : m_flat_tree(dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
+ //! object .
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
+ //! object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last)
+ : m_flat_tree(false, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(false, first, last, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(false, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(false, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const allocator_type &a)
+ : m_flat_tree(ordered_range, first, last, Compare(), a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il)
+ : m_flat_tree( false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
+ : m_flat_tree(false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp, dtl::force<const impl_allocator_type>(a))
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs a flat_multimap.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const flat_multimap& x)
+ : m_flat_tree(x.m_flat_tree)
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(BOOST_RV_REF(flat_multimap) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_flat_tree(boost::move(x.m_flat_tree))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const flat_multimap& x, const allocator_type &a)
+ : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
+ : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x)
+ { m_flat_tree = x.m_flat_tree; return *this; }
+
+ //! <b>Effects</b>: this->swap(x.get()).
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assign content of il to *this
+ //!
+ //! <b>Complexity</b>: Linear in il.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the allocator that
+ //! was passed to the object's constructor.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the container contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.empty(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.max_size(); }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), or the
+ //! underlying container has no `reserve` member, this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
+ //! to values might be invalidated.
+ BOOST_CONTAINER_FORCEINLINE
+ void reserve(size_type cnt)
+ { m_flat_tree.reserve(cnt); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE
+ void shrink_to_fit()
+ { m_flat_tree.shrink_to_fit(); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type) const
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(iterator)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p)); }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
+ iterator emplace(BOOST_FWD_REF(Args)... args)
+ { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal
+ (dtl::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
+ }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
+ { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(BOOST_MOVE_FWD##N)); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal\
+ (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_equal(dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a new value constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template<class Pair>
+ BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
+ ( iterator
+ , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
+ BOOST_MOVE_I iterator >::type)
+ insert(BOOST_FWD_REF(Pair) x)
+ { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(x))); }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.insert_equal( dtl::force_copy<impl_const_iterator>(p)
+ , dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a value constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template<class Pair>
+ BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
+ ( iterator
+ , typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
+ BOOST_MOVE_I iterator>::type)
+ insert(const_iterator p, BOOST_FWD_REF(Pair) x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.emplace_hint_equal(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
+ }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { m_flat_tree.insert_equal(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
+ { m_flat_tree.insert_equal(ordered_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_equal( dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_equal( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+#endif
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Move-inserts each element from source into *this a using
+ //! the comparison object of *this.
+ //!
+ //! <b>Complexity</b>: Linear in this->size() + source.size().
+ //!
+ //! <b>Note</b>: Invalidates all iterators and references.
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Linear to the elements with keys bigger than p
+ //!
+ //! <b>Note</b>: Invalidates elements with keys
+ //! not less than the erased element.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
+ }
+
+ //! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
+ //!
+ //! <b>Returns</b>: Returns the number of erased elements.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
+ { return m_flat_tree.erase(x); }
+
+ //! <b>Effects</b>: Erases all the elements in the range [first, last).
+ //!
+ //! <b>Returns</b>: Returns last.
+ //!
+ //! <b>Complexity</b>: size()*N where N is the distance from first to last.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
+ , dtl::force_copy<impl_const_iterator>(last)));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_multimap& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { m_flat_tree.swap(x.m_flat_tree); }
+
+ //! <b>Effects</b>: erase(begin(),end()).
+ //!
+ //! <b>Postcondition</b>: size() == 0.
+ //!
+ //! <b>Complexity</b>: linear in size().
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { m_flat_tree.clear(); }
+
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ key_compare key_comp() const
+ { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ value_compare value_comp() const
+ { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
+
+ //////////////////////////////////////////////
+ //
+ // map operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator find(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: An const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator find(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator find(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator find(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type count(const key_type& x) const
+ { return m_flat_tree.count(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ size_type count(const K& x) const
+ { return m_flat_tree.count(x); }
+
+ //! <b>Returns</b>: Returns true if there is an element with key
+ //! equivalent to key in the container, otherwise false.
+ //!
+ //! <b>Complexity</b>: log(size()).
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool contains(const key_type& x) const
+ { return m_flat_tree.find(x) != m_flat_tree.end(); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: Returns true if there is an element with key
+ //! equivalent to key in the container, otherwise false.
+ //!
+ //! <b>Complexity</b>: log(size()).
+ template<typename K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ bool contains(const K& x) const
+ { return m_flat_tree.find(x) != m_flat_tree.end(); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator lower_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator lower_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator lower_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator lower_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key greater
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator upper_bound(const key_type& x)
+ {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! greater than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator upper_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key greater
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ iterator upper_bound(const K& x)
+ {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! greater than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ const_iterator upper_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<iterator,iterator> equal_range(const K& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ std::pair<const_iterator, const_iterator> equal_range(const K& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ sequence_type extract_sequence()
+ { return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref())); }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare().
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Effects</b>: Returns a const view of the underlying sequence.
+ //!
+ //! <b>Complexity</b>: Constant
+ //!
+ //! <b>Throws</b>: Nothing
+ BOOST_CONTAINER_FORCEINLINE const sequence_type & sequence() const BOOST_NOEXCEPT
+ { return dtl::force<sequence_type>(m_flat_tree.get_sequence_cref()); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator==(const flat_multimap& x, const flat_multimap& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<(const flat_multimap& x, const flat_multimap& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>(const flat_multimap& x, const flat_multimap& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
+ friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_multimap& x, flat_multimap& y)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
+ { x.swap(y); }
+};
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+
+template <typename InputIterator>
+flat_multimap(InputIterator, InputIterator) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>>;
+
+template < typename InputIterator, typename AllocatorOrCompare>
+flat_multimap(InputIterator, InputIterator, AllocatorOrCompare const&) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , typename dtl::if_c< // Compare
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , std::less<it_based_non_const_first_type_t<InputIterator>>
+ , AllocatorOrCompare
+ >::type
+ , typename dtl::if_c< // Allocator
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , AllocatorOrCompare
+ , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
+ >::type
+ >;
+
+template < typename InputIterator, typename Compare, typename Allocator
+ , typename = dtl::require_nonallocator_t<Compare>
+ , typename = dtl::require_allocator_t<Allocator>>
+flat_multimap(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+flat_multimap(ordered_range_t, InputIterator, InputIterator) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>>;
+
+template < typename InputIterator, typename AllocatorOrCompare>
+flat_multimap(ordered_range_t, InputIterator, InputIterator, AllocatorOrCompare const&) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , typename dtl::if_c< // Compare
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , std::less<it_based_non_const_first_type_t<InputIterator>>
+ , AllocatorOrCompare
+ >::type
+ , typename dtl::if_c< // Allocator
+ dtl::is_allocator<AllocatorOrCompare>::value
+ , AllocatorOrCompare
+ , new_allocator<std::pair<it_based_non_const_first_type_t<InputIterator>, it_based_second_type_t<InputIterator>>>
+ >::type
+ >;
+
+template < typename InputIterator, typename Compare, typename Allocator
+ , typename = dtl::require_nonallocator_t<Compare>
+ , typename = dtl::require_allocator_t<Allocator>>
+flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multimap< it_based_non_const_first_type_t<InputIterator>
+ , it_based_second_type_t<InputIterator>
+ , Compare
+ , Allocator>;
+
+#endif
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
+{
+ typedef ::boost::container::dtl::pair<Key, T> value_t;
+ typedef typename ::boost::container::dtl::container_or_allocator_rebind<AllocatorOrContainer, value_t>::type alloc_or_cont_t;
+ typedef ::boost::container::dtl::flat_tree<value_t,::boost::container::dtl::select1st<Key>, Compare, alloc_or_cont_t> tree;
+ static const bool value = ::boost::has_trivial_destructor_after_move<tree>::value;
+};
+
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_FLAT_MAP_HPP
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/allocators/detail/allocator_common.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/allocators/detail/allocator_common.hpp
index 7939404696..bb301ebfbb 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/allocators/detail/allocator_common.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/allocators/detail/allocator_common.hpp
@@ -220,8 +220,7 @@ class cache_impl
BOOST_CATCH(...){
this->cached_deallocation(chain);
BOOST_RETHROW
- }
- BOOST_CATCH_END
+ } BOOST_CATCH_END
}
void cached_deallocation(void *ptr)
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/containers/allocation_type.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/containers/allocation_type.hpp
index 7175207473..d99b7ab51d 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/containers/allocation_type.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/containers/allocation_type.hpp
@@ -26,7 +26,7 @@ namespace boost {
namespace interprocess {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-typedef int allocation_type;
+using boost::container::allocation_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
static const allocation_type allocate_new = boost::container::allocate_new;
static const allocation_type expand_fwd = boost::container::expand_fwd;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/atomic.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/atomic.hpp
index f02a11a386..3dda5c4031 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/atomic.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/atomic.hpp
@@ -27,6 +27,14 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/cstdint.hpp>
+#if !defined(_AIX)
+#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label) label ":\n\t"
+#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " " label "\n\t"
+#else
+#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label)
+#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " $" offset "\n\t"
+#endif
+
namespace boost{
namespace interprocess{
namespace ipcdetail{
@@ -64,7 +72,12 @@ inline boost::uint32_t atomic_cas32
#if defined( _MSC_VER )
extern "C" void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
- #define BOOST_INTERPROCESS_READ_WRITE_BARRIER _ReadWriteBarrier()
+
+#define BOOST_INTERPROCESS_READ_WRITE_BARRIER \
+ BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING \
+ _ReadWriteBarrier() \
+ BOOST_INTERPROCESS_RESTORE_WARNING
+
#elif defined(__GNUC__)
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
#define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize()
@@ -81,13 +94,13 @@ namespace ipcdetail{
//! "mem": pointer to the atomic value
//! Returns the old value pointed to by mem
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
-{ return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
+{ return (boost::uint32_t)winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
//! Atomically increment an apr_uint32_t by 1
//! "mem": pointer to the object
//! Returns the old value pointed to by mem
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
-{ return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
+{ return (boost::uint32_t)winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
@@ -101,7 +114,7 @@ inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
//! "mem": pointer to the object
//! "param": val value that the object will assume
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
-{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
+{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), (long)val); }
//! Compare an boost::uint32_t's value with "cmp".
//! If they are the same swap the value with "with"
@@ -111,7 +124,7 @@ inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
//! Returns the old value of *mem
inline boost::uint32_t atomic_cas32
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
-{ return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
+{ return (boost::uint32_t)winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), (long)with, (long)cmp); }
} //namespace ipcdetail{
} //namespace interprocess{
@@ -153,7 +166,7 @@ inline boost::uint32_t atomic_add32
// int r = *pw;
// *mem += val;
// return r;
- int r;
+ boost::uint32_t r;
asm volatile
(
@@ -218,14 +231,17 @@ inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32
{
boost::uint32_t prev, temp;
- asm volatile ("1:\n\t"
- "lwarx %0,0,%2\n\t"
- "add %1,%0,%3\n\t"
- "stwcx. %1,0,%2\n\t"
- "bne- 1b"
- : "=&r" (prev), "=&r" (temp)
- : "b" (mem), "r" (val)
- : "cc", "memory");
+ asm volatile
+ (
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
+ "lwarx %0,0,%2\n\t"
+ "add %1,%0,%3\n\t"
+ "stwcx. %1,0,%2\n\t"
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
+ : "=&r" (prev), "=&r" (temp)
+ : "b" (mem), "r" (val)
+ : "cc", "memory"
+ );
return prev;
}
@@ -240,16 +256,19 @@ inline boost::uint32_t atomic_cas32
{
boost::uint32_t prev;
- asm volatile ("1:\n\t"
- "lwarx %0,0,%1\n\t"
- "cmpw %0,%3\n\t"
- "bne- 2f\n\t"
- "stwcx. %2,0,%1\n\t"
- "bne- 1b\n\t"
- "2:"
- : "=&r"(prev)
- : "b" (mem), "r" (with), "r" (cmp)
- : "cc", "memory");
+ asm volatile
+ (
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
+ "lwarx %0,0,%1\n\t"
+ "cmpw %0,%3\n\t"
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "2f", "+12")
+ "stwcx. %2,0,%1\n\t"
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
+ BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("2")
+ : "=&r"(prev)
+ : "b" (mem), "r" (with), "r" (cmp)
+ : "cc", "memory"
+ );
return prev;
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/char_wchar_holder.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/char_wchar_holder.hpp
new file mode 100644
index 0000000000..8831aa202d
--- /dev/null
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/char_wchar_holder.hpp
@@ -0,0 +1,127 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2020-2021. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP
+#define BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <cwchar>
+#include <cstring>
+
+namespace boost {
+namespace interprocess {
+
+class char_wchar_holder
+{
+ public:
+ char_wchar_holder()
+ : m_str(), m_is_wide()
+ {
+ m_str.n = 0;
+ }
+
+ char_wchar_holder(const char *nstr)
+ : m_str(), m_is_wide()
+ {
+ m_str.n = new char [std::strlen(nstr)+1];
+ std::strcpy(m_str.n, nstr);
+ }
+
+ char_wchar_holder(const wchar_t *wstr)
+ : m_str(), m_is_wide(true)
+ {
+ m_str.w = new wchar_t [std::wcslen(wstr)+1];
+ std::wcscpy(m_str.w, wstr);
+ }
+
+ char_wchar_holder& operator=(const char *nstr)
+ {
+ char *tmp = new char [std::strlen(nstr)+1];
+ this->delete_mem();
+ m_str.n = tmp;
+ std::strcpy(m_str.n, nstr);
+ return *this;
+ }
+
+ char_wchar_holder& operator=(const wchar_t *wstr)
+ {
+ wchar_t *tmp = new wchar_t [std::wcslen(wstr)+1];
+ this->delete_mem();
+ m_str.w = tmp;
+ std::wcscpy(m_str.w, wstr);
+ return *this;
+ }
+
+ char_wchar_holder& operator=(const char_wchar_holder &other)
+ {
+ if (other.m_is_wide)
+ *this = other.getn();
+ else
+ *this = other.getw();
+ return *this;
+ }
+
+ ~char_wchar_holder()
+ {
+ this->delete_mem();
+ }
+
+ wchar_t *getw() const
+ { return m_is_wide ? m_str.w : 0; }
+
+ char *getn() const
+ { return !m_is_wide ? m_str.n : 0; }
+
+ void swap(char_wchar_holder& other)
+ {
+ char_wchar tmp;
+ std::memcpy(&tmp, &m_str, sizeof(char_wchar));
+ std::memcpy(&m_str, &other.m_str, sizeof(char_wchar));
+ std::memcpy(&other.m_str, &tmp, sizeof(char_wchar));
+ //
+ bool b_tmp(m_is_wide);
+ m_is_wide = other.m_is_wide;
+ other.m_is_wide = b_tmp;
+ }
+
+ private:
+
+ void delete_mem()
+ {
+ if(m_is_wide)
+ delete [] m_str.w;
+ else
+ delete [] m_str.n;
+ }
+
+ union char_wchar
+ {
+ char *n;
+ wchar_t *w;
+ } m_str;
+ bool m_is_wide;
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/config_external_begin.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/config_external_begin.hpp
index fb578ef013..67c0556807 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/config_external_begin.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/config_external_begin.hpp
@@ -15,4 +15,9 @@
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wshadow"
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+# pragma GCC diagnostic ignored "-Wconversion"
+# if (BOOST_GCC >= 100000)
+# pragma GCC diagnostic ignored "-Warith-conversion"
+# endif
#endif
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/in_place_interface.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/in_place_interface.hpp
index 367f9dca3d..6ba6229bfc 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/in_place_interface.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/in_place_interface.hpp
@@ -54,14 +54,14 @@ struct placement_destroy : public in_place_interface
: in_place_interface(::boost::container::dtl::alignment_of<T>::value, sizeof(T), typeid(T).name())
{}
- virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
+ virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) BOOST_OVERRIDE
{
T* memory = static_cast<T*>(mem);
for(destroyed = 0; destroyed < num; ++destroyed)
(memory++)->~T();
}
- virtual void construct_n(void *, std::size_t, std::size_t &) {}
+ virtual void construct_n(void *, std::size_t, std::size_t &) BOOST_OVERRIDE {}
private:
void destroy(void *mem)
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/intermodule_singleton_common.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/intermodule_singleton_common.hpp
index 392db1f86b..2218cd9b9f 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/intermodule_singleton_common.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/intermodule_singleton_common.hpp
@@ -34,6 +34,7 @@
#include <cstdlib>
#include <cstring>
#include <string>
+#include <typeinfo>
#include <sstream>
namespace boost{
@@ -120,7 +121,7 @@ class intermodule_singleton_common
}
}
if(previous_module_singleton_initialized == Uninitialized){
- try{
+ BOOST_TRY{
//Now initialize the global map, this function must solve concurrency
//issues between threads of several modules
initialize_global_map_handle();
@@ -142,11 +143,11 @@ class intermodule_singleton_common
//before this one. Now marked as initialized
atomic_write32(&this_module_singleton_initialized, Initialized);
}
- catch(...){
+ BOOST_CATCH(...){
//Mark singleton failed to initialize
atomic_write32(&this_module_singleton_initialized, Broken);
- throw;
- }
+ BOOST_RETHROW
+ } BOOST_CATCH_END
}
//If previous state was initializing, this means that another winner thread is
//trying to initialize the singleton. Just wait until completes its work.
@@ -231,7 +232,7 @@ class intermodule_singleton_common
}
else{ //(tmp == Uninitialized)
//If not initialized try it again?
- try{
+ BOOST_TRY{
//Remove old global map from the system
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
//in-place construction of the global map class
@@ -254,10 +255,10 @@ class intermodule_singleton_common
break;
}
}
- catch(...){
+ BOOST_CATCH(...){
//
- throw;
- }
+ BOOST_RETHROW
+ } BOOST_CATCH_END
}
}
}
@@ -405,17 +406,17 @@ class intermodule_singleton_impl
<ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
if(!rcount){
C *p = new C;
- try{
+ BOOST_TRY{
ref_count_ptr val(p, 0u);
rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
<ThreadSafeGlobalMap>::insert(m_map, typeid(C).name(), val);
}
- catch(...){
+ BOOST_CATCH(...){
intermodule_singleton_helpers::thread_safe_global_map_dependant
<ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
delete p;
- throw;
- }
+ BOOST_RETHROW
+ } BOOST_CATCH_END
}
//if(Phoenix){
std::atexit(&atexit_work);
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_file_functions.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_file_functions.hpp
index 7a41868188..5e3a5a0ddd 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_file_functions.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_file_functions.hpp
@@ -24,22 +24,22 @@
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/permissions.hpp>
-#include <string>
-#include <limits>
#include <climits>
+#include <string>
#include <boost/move/detail/type_traits.hpp> //make_unsigned
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
+# include <wchar.h> //wcsxxx()
#else
# ifdef BOOST_HAS_UNISTD_H
# include <fcntl.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
-# include <errno.h>
-# include <cstdio>
# include <dirent.h>
+# include <cerrno>
+# include <cstdio>
# if 0
# include <sys/file.h>
# endif
@@ -99,10 +99,26 @@ inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd.handle; }
-inline bool create_directory(const char *path)
+template<class CharT>
+inline bool create_directory(const CharT *path)
{ return winapi::create_directory(path); }
-inline bool remove_directory(const char *path)
+template<class CharT>
+inline bool open_or_create_directory(const CharT *path)
+{
+ //If fails, check that it's because it already exists
+ return create_directory(path)
+ || error_info(system_error_code()).get_error_code() == already_exists_error;
+}
+
+template<class CharT>
+inline bool open_or_create_shared_directory(const CharT *path)
+{
+ return open_or_create_directory(path);
+}
+
+template <class CharT>
+inline bool remove_directory(const CharT *path)
{ return winapi::remove_directory(path); }
inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
@@ -115,15 +131,33 @@ inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &r
return false;
}
required_len = winapi::get_temp_path(buf_len, buffer);
- const bool ret = !(buf_len < required_len);
+ const bool ret = required_len && (buf_len > required_len);
if(ret && buffer[required_len-1] == '\\'){
- buffer[required_len-1] = 0;
+ buffer[required_len-1] = '\0';
}
return ret;
}
+inline bool get_temporary_path(wchar_t *buffer, std::size_t buf_len, std::size_t &required_len)
+{
+ required_len = 0;
+ //std::size_t is always bigger or equal than unsigned long in Windows systems
+ //In case std::size_t is bigger than unsigned long
+ unsigned long buf = buf_len;
+ if(buf_len != buf){ //maybe overflowed
+ return false;
+ }
+ required_len = winapi::get_temp_path(buf_len, buffer);
+ const bool ret = !(buf_len < required_len);
+ if(ret && buffer[required_len-1] == L'\\'){
+ buffer[required_len-1] = L'\0';
+ }
+ return ret;
+}
+
+template<class CharT>
inline file_handle_t create_new_file
- (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+ (const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -131,8 +165,9 @@ inline file_handle_t create_new_file
, (winapi::interprocess_security_attributes*)perm.get_permissions());
}
+template <class CharT>
inline file_handle_t create_or_open_file
- (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+ (const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -140,8 +175,9 @@ inline file_handle_t create_or_open_file
, (winapi::interprocess_security_attributes*)perm.get_permissions());
}
+template<class CharT>
inline file_handle_t open_existing_file
- (const char *name, mode_t mode, bool temporary = false)
+ (const CharT *name, mode_t mode, bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -151,6 +187,9 @@ inline file_handle_t open_existing_file
inline bool delete_file(const char *name)
{ return winapi::unlink_file(name); }
+inline bool delete_file(const wchar_t *name)
+{ return winapi::unlink_file(name); }
+
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
offset_t filesize;
@@ -158,8 +197,8 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
return false;
typedef ::boost::move_detail::make_unsigned<offset_t>::type uoffset_t;
- const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)());
- const uoffset_t uoff_size = uoffset_t(size);
+ const uoffset_t max_filesize = uoffset_t(-1)/2u;
+ const uoffset_t uoff_size = uoffset_t(size);
//Avoid unused variable warnings in 32 bit systems
if(uoff_size > max_filesize){
winapi::set_last_error(winapi::error_file_too_large);
@@ -167,12 +206,12 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
}
if(offset_t(size) > filesize){
- if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
+ if(!winapi::set_file_pointer(hnd, filesize, 0, winapi::file_begin)){
return false;
}
//We will write zeros in the end of the file
//since set_end_of_file does not guarantee this
- for(std::size_t remaining = size - filesize, write_size = 0
+ for(std::size_t remaining = size - std::size_t(filesize), write_size = 0
;remaining > 0
;remaining -= write_size){
const std::size_t DataSize = 512;
@@ -186,7 +225,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
}
}
else{
- if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
+ if(!winapi::set_file_pointer(hnd, size, 0, winapi::file_begin)){
return false;
}
if(!winapi::set_end_of_file(hnd)){
@@ -200,10 +239,10 @@ inline bool get_file_size(file_handle_t hnd, offset_t &size)
{ return winapi::get_file_size(hnd, size); }
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
-{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
+{ return winapi::set_file_pointer(hnd, off, 0, (unsigned long) pos); }
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
-{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
+{ return winapi::set_file_pointer(hnd, 0, &off, winapi::file_current); }
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
{
@@ -239,7 +278,8 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
acquired = false, true : false;
}
- return (acquired = true);
+ acquired = true;
+ return true;
}
inline bool release_file_lock(file_handle_t hnd)
@@ -268,32 +308,75 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
return winapi::get_last_error() == winapi::error_lock_violation ?
acquired = false, true : false;
}
- return (acquired = true);
+
+ acquired = true;
+ return true;
}
inline bool release_file_lock_sharable(file_handle_t hnd)
{ return release_file_lock(hnd); }
+template<class CharT>
+struct os_file_traits;
+
+template<>
+struct os_file_traits<char>
+{
+ static const char *any_file()
+ { return "\\*.*"; }
+
+ static const char *backslash()
+ { return "\\"; }
+
+ static char dot()
+ { return '.'; }
+
+ typedef winapi::win32_find_data_a win32_find_data_t;
+
+ static int cmp(const char *a, const char *b)
+ { return std::strcmp(a, b); }
+};
+
+template<>
+struct os_file_traits<wchar_t>
+{
+ static const wchar_t *any_file()
+ { return L"\\*.*"; }
+
+ static const wchar_t *backslash()
+ { return L"\\"; }
+
+ static wchar_t dot()
+ { return L'.'; }
+
+ typedef winapi::win32_find_data_w win32_find_data_t;
+
+ static int cmp(const wchar_t *a, const wchar_t *b)
+ { return std::wcscmp(a, b); }
+};
+
+template<class CharT>
inline bool delete_subdirectories_recursive
- (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
+ (const std::basic_string<CharT> &refcstrRootDirectory, const CharT *dont_delete_this, unsigned int count)
{
bool bSubdirectory = false; // Flag, indicating whether
// subdirectories have been found
void * hFile; // Handle to directory
- std::string strFilePath; // Filepath
- std::string strPattern; // Pattern
- winapi::win32_find_data FileInformation; // File information
+ std::basic_string<CharT> strFilePath; // Filepath
+ std::basic_string<CharT> strPattern; // Pattern
+ typedef os_file_traits<CharT> traits_t;
+ typename traits_t::win32_find_data_t FileInformation; // File information
//Find all files and directories
- strPattern = refcstrRootDirectory + "\\*.*";
+ strPattern = refcstrRootDirectory + traits_t::any_file();
hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
if(hFile != winapi::invalid_handle_value){
do{
//If it's not "." or ".." or the pointed root_level dont_delete_this erase it
- if(FileInformation.cFileName[0] != '.' &&
- !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
+ if(FileInformation.cFileName[0] != traits_t::dot() &&
+ !(dont_delete_this && count == 0 && traits_t::cmp(dont_delete_this, FileInformation.cFileName) == 0)){
strFilePath.erase();
- strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
+ strFilePath = refcstrRootDirectory + traits_t::backslash() + FileInformation.cFileName;
//If it's a directory, go recursive
if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
@@ -340,7 +423,8 @@ inline bool delete_subdirectories_recursive
}
//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
-inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
+template <class CharT>
+inline bool delete_subdirectories(const std::basic_string<CharT> &refcstrRootDirectory, const CharT *dont_delete_this)
{
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
}
@@ -350,7 +434,7 @@ template<class Function>
inline bool for_each_file_in_dir(const char *dir, Function f)
{
void * hFile; // Handle to directory
- winapi::win32_find_data FileInformation; // File information
+ winapi::win32_find_data_a FileInformation; // File information
//Get base directory
std::string str(dir);
@@ -423,7 +507,27 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd.handle; }
inline bool create_directory(const char *path)
-{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
+{
+ ::mode_t m = ::mode_t(0777);
+ return ::mkdir(path, m) == 0;
+}
+
+inline bool open_or_create_directory(const char *path)
+{
+ ::mode_t m = ::mode_t(0777);
+ return ::mkdir(path, m) == 0 || (errno == EEXIST);
+}
+
+inline bool open_or_create_shared_directory(const char *path)
+{
+ const ::mode_t m = ::mode_t(01777);
+ const bool created = ::mkdir(path, m) == 0;
+ const bool created_or_exists = created || (errno == EEXIST);
+ //Try to maximize the chance that the sticky bit is set in shared dirs
+ //created with old versions that did not set it (for security reasons)
+ const bool chmoded = ::chmod(path, m) == 0;
+ return created ? chmoded : created_or_exists;
+}
inline bool remove_directory(const char *path)
{ return ::rmdir(path) == 0; }
@@ -457,7 +561,7 @@ inline file_handle_t create_or_open_file
int ret = -1;
//We need a loop to change permissions correctly using fchmod, since
//with "O_CREAT only" ::open we don't know if we've created or opened the file.
- while(1){
+ while(true){
ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
if(ret >= 0){
::fchmod(ret, perm.get_permissions());
@@ -488,7 +592,8 @@ inline bool delete_file(const char *name)
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
typedef boost::move_detail::make_unsigned<off_t>::type uoff_t;
- if(uoff_t((std::numeric_limits<off_t>::max)()) < size){
+ BOOST_STATIC_ASSERT(( sizeof(uoff_t) >= sizeof(std::size_t) ));
+ if( uoff_t(-1)/2u < uoff_t(size) ){
errno = EINVAL;
return false;
}
@@ -543,7 +648,7 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
- acquired = false, true : false;
+ (acquired = false, true) : false;
}
return (acquired = true);
}
@@ -578,7 +683,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
- acquired = false, true : false;
+ (acquired = false, true) : false;
}
return (acquired = true);
}
@@ -711,23 +816,26 @@ inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
-inline bool open_or_create_directory(const char *dir_name)
+inline std::string get_temporary_path()
{
- //If fails, check that it's because it already exists
- if(!create_directory(dir_name)){
- error_info info(system_error_code());
- if(info.get_error_code() != already_exists_error){
- return false;
- }
+ std::size_t required_len = 0;
+ get_temporary_path((char*)0, 0, required_len);
+ std::string ret_str(required_len, char(0));
+ get_temporary_path(&ret_str[0], ret_str.size(), required_len);
+ while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
+ ret_str.erase(ret_str.size()-1);
}
- return true;
+
+ return ret_str;
}
-inline std::string get_temporary_path()
+#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES
+
+inline std::wstring get_temporary_wpath()
{
std::size_t required_len = 0;
- get_temporary_path(0, 0, required_len);
- std::string ret_str(required_len, char(0));
+ get_temporary_path((wchar_t*)0, 0, required_len);
+ std::wstring ret_str(required_len, char(0));
get_temporary_path(&ret_str[0], ret_str.size(), required_len);
while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
ret_str.erase(ret_str.size()-1);
@@ -736,6 +844,8 @@ inline std::string get_temporary_path()
return ret_str;
}
+#endif
+
} //namespace ipcdetail{
} //namespace interprocess {
} //namespace boost {
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp
index ff1ed1ac02..7d88b4dd30 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp
@@ -33,13 +33,12 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <cstddef>
#include <ostream>
#if defined(BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
-# include <process.h>
+# include <boost/winapi/thread.hpp>
#else
# include <pthread.h>
# include <unistd.h>
@@ -158,7 +157,7 @@ inline OS_highres_count_t get_current_system_highres_count()
if(!winapi::query_performance_counter(&count)){
count = winapi::get_tick_count();
}
- return count;
+ return (OS_highres_count_t)count;
}
inline void zero_highres_count(OS_highres_count_t &count)
@@ -229,7 +228,7 @@ inline long double get_current_process_creation_time()
inline unsigned int get_num_cores()
{
- winapi::system_info sysinfo;
+ winapi::interprocess_system_info sysinfo;
winapi::get_system_info( &sysinfo );
//in Windows dw is long which is equal in bits to int
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
@@ -422,7 +421,7 @@ inline void thread_sleep_tick()
struct timespec rqt;
//Sleep for the half of the tick time
rqt.tv_sec = 0;
- rqt.tv_nsec = get_system_tick_ns()/2;
+ rqt.tv_nsec = (long)get_system_tick_ns()/2;
::nanosleep(&rqt, 0);
}
@@ -519,9 +518,9 @@ inline void get_pid_str(pid_str_t &pid_str)
#if defined(BOOST_INTERPROCESS_WINDOWS)
-inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg )
+inline int thread_create( OS_thread_t * thread, boost::ipwinapiext::LPTHREAD_START_ROUTINE_ start_routine, void* arg )
{
- void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
+ void* h = boost::ipwinapiext::CreateThread(0, 0, start_routine, arg, 0, 0);
if( h != 0 ){
thread->m_handle = h;
@@ -530,9 +529,6 @@ inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_rout
else{
return 1;
}
-
- thread->m_handle = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
- return thread->m_handle != 0;
}
inline void thread_join( OS_thread_t thread)
@@ -576,7 +572,7 @@ class os_thread_func_ptr_deleter
#if defined(BOOST_INTERPROCESS_WINDOWS)
-inline unsigned __stdcall launch_thread_routine( void * pv )
+inline boost::winapi::DWORD_ __stdcall launch_thread_routine(boost::winapi::LPVOID_ pv)
{
os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
pt->run();
@@ -605,7 +601,7 @@ class launch_thread_impl
: f_( f )
{}
- void run()
+ virtual void run() BOOST_OVERRIDE
{ f_(); }
private:
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/posix_time_types_wrk.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/posix_time_types_wrk.hpp
deleted file mode 100644
index 5a12d83d76..0000000000
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/posix_time_types_wrk.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2005-2012. 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)
-//
-// See http://www.boost.org/libs/interprocess for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
-#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
-
-#ifndef BOOST_CONFIG_HPP
-# include <boost/config.hpp>
-#endif
-#
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-# pragma once
-#endif
-
-//workaround to avoid winsock redefines when using date-time
-
-#ifdef _WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
-#endif //#ifndef WIN32_LEAN_AND_MEAN
-#endif //#ifdef _WIN32
-
-#include <boost/date_time/microsec_time_clock.hpp>
-#include <boost/date_time/posix_time/ptime.hpp>
-#include <boost/date_time/posix_time/posix_time_duration.hpp>
-
-namespace boost {
-namespace interprocess {
-
-typedef boost::date_time::microsec_clock<boost::posix_time::ptime> microsec_clock;
-
-}
-}
-
-#ifdef _WIN32
-#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
-#undef WIN32_LEAN_AND_MEAN
-#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
-#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
-#endif //#ifdef _WIN32
-
-#endif //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
-
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/segment_manager_helper.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/segment_manager_helper.hpp
index 96ccf227fe..036dab5cc7 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/segment_manager_helper.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/segment_manager_helper.hpp
@@ -35,6 +35,7 @@
#include <boost/intrusive/pointer_traits.hpp>
// move/detail
#include <boost/move/detail/type_traits.hpp> //make_unsigned
+#include <boost/move/detail/force_ptr.hpp>
// other boost
#include <boost/assert.hpp> //BOOST_ASSERT
#include <boost/core/no_exceptions_support.hpp>
@@ -92,7 +93,7 @@ struct block_header
: m_value_bytes(val_bytes)
, m_num_char((unsigned short)num_char)
, m_value_alignment((unsigned char)val_alignment)
- , m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) )
+ , m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) )
{};
template<class T>
@@ -102,7 +103,7 @@ struct block_header
size_type total_size() const
{
if(alloc_type() != anonymous_type){
- return name_offset() + (m_num_char+1)*sizeof_char();
+ return name_offset() + (m_num_char+1u)*sizeof_char();
}
else{
return this->value_offset() + m_value_bytes;
@@ -130,7 +131,7 @@ struct block_header
template<class CharType>
CharType *name() const
{
- return const_cast<CharType*>(reinterpret_cast<const CharType*>
+ return const_cast<CharType*>(move_detail::force_ptr<const CharType*>
(reinterpret_cast<const char*>(this) + name_offset()));
}
@@ -175,7 +176,7 @@ struct block_header
{
block_header * hdr =
const_cast<block_header*>
- (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
+ (move_detail::force_ptr<const block_header*>(reinterpret_cast<const char*>(value) -
get_rounded_size(sizeof(block_header), algn)));
(void)sz;
//Some sanity checks
@@ -188,7 +189,7 @@ struct block_header
static block_header<size_type> *from_first_header(Header *header)
{
block_header<size_type> * hdr =
- reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
+ move_detail::force_ptr<block_header<size_type>*>(reinterpret_cast<char*>(header) +
get_rounded_size( size_type(sizeof(Header))
, size_type(::boost::container::dtl::alignment_of<block_header<size_type> >::value)));
//Some sanity checks
@@ -199,7 +200,7 @@ struct block_header
static Header *to_first_header(block_header<size_type> *bheader)
{
Header * hdr =
- reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
+ move_detail::force_ptr<Header*>(reinterpret_cast<char*>(bheader) -
get_rounded_size( size_type(sizeof(Header))
, size_type(::boost::container::dtl::alignment_of<block_header<size_type> >::value)));
//Some sanity checks
@@ -219,8 +220,7 @@ inline void array_construct(void *mem, std::size_t num, in_place_interface &tabl
std::size_t destroyed = 0;
table.destroy_n(mem, constructed, destroyed);
BOOST_RETHROW
- }
- BOOST_CATCH_END
+ } BOOST_CATCH_END
}
template<class CharT>
@@ -280,7 +280,7 @@ struct intrusive_value_type_impl
block_header<size_type> *get_block_header() const
{
return const_cast<block_header<size_type>*>
- (reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
+ (move_detail::force_ptr<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
}
@@ -292,7 +292,7 @@ struct intrusive_value_type_impl
static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
{
- return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
+ return move_detail::force_ptr<intrusive_value_type_impl*>(reinterpret_cast<char*>(hdr) -
get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
}
@@ -472,7 +472,7 @@ class segment_manager_iterator_value_adaptor<Iterator, false>
const void *value() const
{
- return reinterpret_cast<block_header<size_type>*>
+ return move_detail::force_ptr<block_header<size_type>*>
(to_raw_pointer(m_val->second.m_ptr))->value();
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/shared_dir_helpers.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/shared_dir_helpers.hpp
index 0fcd898dcb..8d9d36f2db 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/shared_dir_helpers.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/shared_dir_helpers.hpp
@@ -34,9 +34,33 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
+template<class CharT>
+struct shared_dir_constants;
+
+template<>
+struct shared_dir_constants<char>
+{
+ static char dir_separator()
+ { return '/'; }
+
+ static const char *dir_interprocess()
+ { return "/boost_interprocess"; }
+};
+
+template<>
+struct shared_dir_constants<wchar_t>
+{
+ static wchar_t dir_separator()
+ { return L'/'; }
+
+ static const wchar_t *dir_interprocess()
+ { return L"/boost_interprocess"; }
+};
+
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
#if defined(BOOST_INTERPROCESS_WINDOWS)
//This type will initialize the stamp
+ template<class CharT>
struct windows_bootstamp
{
windows_bootstamp()
@@ -49,12 +73,13 @@ namespace ipcdetail {
}
//Use std::string. Even if this will be constructed in shared memory, all
//modules/dlls are from this process so internal raw pointers to heap are always valid
- std::string stamp;
+ std::basic_string<CharT> stamp;
};
- inline void get_bootstamp(std::string &s, bool add = false)
+ template <class CharT>
+ inline void get_bootstamp(std::basic_string<CharT> &s, bool add = false)
{
- const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
+ const windows_bootstamp<CharT> &bootstamp = windows_intermodule_singleton<windows_bootstamp<CharT> >::get();
if(add){
s += bootstamp.stamp;
}
@@ -102,7 +127,8 @@ namespace ipcdetail {
#endif
#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
-inline void get_shared_dir_root(std::string &dir_path)
+template <class CharT>
+inline void get_shared_dir_root(std::basic_string<CharT> &dir_path)
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
winapi::get_shared_documents_folder(dir_path);
@@ -115,8 +141,8 @@ inline void get_shared_dir_root(std::string &dir_path)
error_info err = system_error_code();
throw interprocess_exception(err);
}
- //Remove final null.
- dir_path += "/boost_interprocess";
+
+ dir_path += shared_dir_constants<CharT>::dir_interprocess();
}
#if defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC) && defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
@@ -129,57 +155,75 @@ inline void get_shared_dir_root(std::string &dir_path)
// get_shared_dir
void get_shared_dir(std::string &shared_dir);
+ // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
+ // get_shared_dir
+ void get_shared_dir(std::wstring &shared_dir);
+
#else
+
+#if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
+
inline void get_shared_dir(std::string &shared_dir)
{
- #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
- shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
- #else
+ shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
+}
+
+#endif
+
+#if defined(BOOST_INTERPROCESS_SHARED_DIR_WPATH)
+
+inline void get_shared_dir(std::wstring &shared_dir)
+{
+ shared_dir = BOOST_INTERPROCESS_SHARED_DIR_WPATH;
+}
+
+#endif
+
+template<class CharT>
+inline void get_shared_dir(std::basic_string<CharT> &shared_dir)
+{
get_shared_dir_root(shared_dir);
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
- shared_dir += "/";
+ shared_dir += shared_dir_constants<CharT>::dir_separator();
get_bootstamp(shared_dir, true);
#endif
- #endif
}
#endif
-inline void shared_filepath(const char *filename, std::string &filepath)
+template<class CharT>
+inline void shared_filepath(const CharT *filename, std::basic_string<CharT> &filepath)
{
get_shared_dir(filepath);
- filepath += "/";
+ filepath += shared_dir_constants<CharT>::dir_separator();
filepath += filename;
}
-inline void create_shared_dir_and_clean_old(std::string &shared_dir)
+template<class CharT>
+inline void create_shared_dir_and_clean_old(std::basic_string<CharT> &shared_dir)
{
#if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) || defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC)
get_shared_dir(shared_dir);
#else
//First get the temp directory
- std::string root_shared_dir;
+ std::basic_string<CharT> root_shared_dir;
get_shared_dir_root(root_shared_dir);
//If fails, check that it's because already exists
- if(!create_directory(root_shared_dir.c_str())){
+ if(!open_or_create_shared_directory(root_shared_dir.c_str())){
error_info info(system_error_code());
- if(info.get_error_code() != already_exists_error){
- throw interprocess_exception(info);
- }
+ throw interprocess_exception(info);
}
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
get_shared_dir(shared_dir);
//If fails, check that it's because already exists
- if(!create_directory(shared_dir.c_str())){
+ if(!open_or_create_shared_directory(shared_dir.c_str())){
error_info info(system_error_code());
- if(info.get_error_code() != already_exists_error){
- throw interprocess_exception(info);
- }
+ throw interprocess_exception(info);
}
//Now erase all old directories created in the previous boot sessions
- std::string subdir = shared_dir;
+ std::basic_string<CharT> subdir = shared_dir;
subdir.erase(0, root_shared_dir.size()+1);
delete_subdirectories(root_shared_dir, subdir.c_str());
#else
@@ -188,17 +232,19 @@ inline void create_shared_dir_and_clean_old(std::string &shared_dir)
#endif
}
-inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir)
+template<class CharT>
+inline void create_shared_dir_cleaning_old_and_get_filepath(const CharT *filename, std::basic_string<CharT> &shared_dir)
{
create_shared_dir_and_clean_old(shared_dir);
- shared_dir += "/";
+ shared_dir += shared_dir_constants<CharT>::dir_separator();
shared_dir += filename;
}
-inline void add_leading_slash(const char *name, std::string &new_name)
+template<class CharT>
+inline void add_leading_slash(const CharT *name, std::basic_string<CharT> &new_name)
{
- if(name[0] != '/'){
- new_name = '/';
+ if(name[0] != shared_dir_constants<CharT>::dir_separator()){
+ new_name = shared_dir_constants<CharT>::dir_separator();
}
new_name += name;
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/timed_utils.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/timed_utils.hpp
new file mode 100644
index 0000000000..89fbccd068
--- /dev/null
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/timed_utils.hpp
@@ -0,0 +1,388 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2021-2021.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
+
+#include <ctime>
+#include <boost/cstdint.hpp>
+
+//The following is used to support high precision time clocks
+#ifdef BOOST_HAS_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+
+#ifdef BOOST_HAS_FTIME
+#include <time.h>
+#include <boost/winapi/time.hpp>
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(time_duration_type)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(clock)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep_type)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep)
+
+template<class T>
+struct enable_if_ptime
+ : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
+{};
+
+template<class T>
+struct disable_if_ptime
+ : enable_if_c< ! BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
+{};
+
+template<class T>
+struct enable_if_ptime_duration
+ : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep_type) >
+{};
+
+template<class T>
+struct enable_if_time_point
+ : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, clock) >
+{};
+
+template<class T>
+struct enable_if_duration
+ : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep) >
+{};
+
+#if defined(BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS)
+
+ inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
+ {
+ // gmtime_r() not in namespace std???
+ #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
+ std::tm tmp;
+ if(!gmtime_r(t,&tmp))
+ result = 0;
+ else
+ *result = tmp;
+ #else
+ result = gmtime_r(t, result);
+ #endif
+ return result;
+ }
+
+#else // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
+
+ #if defined(__clang__) // Clang has to be checked before MSVC
+ # pragma clang diagnostic push
+ # pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
+ # pragma warning(push) // preserve warning settings
+ # pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8
+ #endif
+
+ inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
+ {
+ result = std::gmtime(t);
+ return result;
+ }
+
+ #if defined(__clang__) // Clang has to be checked before MSVC
+ # pragma clang diagnostic pop
+ #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
+ # pragma warning(pop) // restore warnings to previous state
+ #endif
+
+#endif // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
+
+#if defined(BOOST_HAS_FTIME)
+/*!
+* The function converts file_time into number of microseconds elapsed since 1970-Jan-01
+*
+* \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
+*/
+inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
+{
+ // shift is difference between 1970-Jan-01 & 1601-Jan-01
+ // in 100-nanosecond units
+ const boost::uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
+
+ // 100-nanos since 1601-Jan-01
+ boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
+
+ ft_as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
+ return (ft_as_integer / 10U); // truncate to microseconds
+}
+#endif
+
+class ustime;
+
+class usduration
+{
+ public:
+ friend class ustime;
+
+ explicit usduration(boost::uint64_t microsecs)
+ : m_microsecs(microsecs)
+ {}
+
+ boost::uint64_t get_microsecs() const
+ { return m_microsecs; }
+
+ bool operator < (const usduration &other) const
+ { return m_microsecs < other.m_microsecs; }
+
+ bool operator > (const usduration &other) const
+ { return m_microsecs > other.m_microsecs; }
+
+ bool operator <= (const usduration &other) const
+ { return m_microsecs <= other.m_microsecs; }
+
+ bool operator >= (const usduration &other) const
+ { return m_microsecs >= other.m_microsecs; }
+
+ private:
+ boost::uint64_t m_microsecs;
+};
+
+class ustime
+{
+ public:
+ explicit ustime(boost::uint64_t microsecs)
+ : m_microsecs(microsecs)
+ {}
+
+ ustime &operator += (const usduration &other)
+ { m_microsecs += other.m_microsecs; return *this; }
+
+ ustime operator + (const usduration &other)
+ { ustime r(*this); r += other; return r; }
+
+ ustime &operator -= (const usduration &other)
+ { m_microsecs -= other.m_microsecs; return *this; }
+
+ ustime operator - (const usduration &other)
+ { ustime r(*this); r -= other; return r; }
+
+ friend usduration operator - (const ustime &l, const ustime &r)
+ { return usduration(l.m_microsecs - r.m_microsecs); }
+
+ bool operator < (const ustime &other) const
+ { return m_microsecs < other.m_microsecs; }
+
+ bool operator > (const ustime &other) const
+ { return m_microsecs > other.m_microsecs; }
+
+ bool operator <= (const ustime &other) const
+ { return m_microsecs <= other.m_microsecs; }
+
+ bool operator >= (const ustime &other) const
+ { return m_microsecs >= other.m_microsecs; }
+
+ boost::uint64_t get_microsecs() const
+ { return m_microsecs; }
+
+ private:
+ boost::uint64_t m_microsecs;
+};
+
+inline usduration usduration_milliseconds(boost::uint64_t millisec)
+{ return usduration(millisec*1000u); }
+
+inline usduration usduration_seconds(boost::uint64_t sec)
+{ return usduration(sec*uint64_t(1000000u)); }
+
+template<class TimeType, class Enable = void>
+class microsec_clock;
+
+template<class TimeType>
+class microsec_clock<TimeType, typename enable_if_ptime<TimeType>::type>
+{
+ private:
+ typedef typename TimeType::date_type date_type;
+ typedef typename TimeType::time_duration_type time_duration_type;
+ typedef typename time_duration_type::rep_type resolution_traits_type;
+ public:
+
+ static TimeType universal_time()
+ {
+ #ifdef BOOST_HAS_GETTIMEOFDAY
+ timeval tv;
+ gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
+ std::time_t t = tv.tv_sec;
+ boost::uint32_t sub_sec = static_cast<boost::uint32_t>(tv.tv_usec);
+ #elif defined(BOOST_HAS_FTIME)
+ boost::winapi::FILETIME_ ft;
+ boost::winapi::GetSystemTimeAsFileTime(&ft);
+ boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
+ // and cannot be before 1970-Jan-01
+ std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
+ // microseconds -- static casts suppress warnings
+ boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
+ #else
+ #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
+ #endif
+
+ std::tm curr;
+ std::tm* curr_ptr = interprocess_gmtime(&t, &curr);
+ date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
+ static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
+ static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
+
+ //The following line will adjust the fractional second tick in terms
+ //of the current time system. For example, if the time system
+ //doesn't support fractional seconds then res_adjust returns 0
+ //and all the fractional seconds return 0.
+ unsigned adjust = static_cast< unsigned >(resolution_traits_type::res_adjust() / 1000000);
+
+ time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
+ static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
+ static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
+ static_cast< typename time_duration_type::fractional_seconds_type >(sub_sec * adjust)
+ );
+ return TimeType(d,td);
+ }
+};
+
+template<>
+class microsec_clock<ustime>
+{
+ public:
+ static ustime universal_time()
+ {
+ #ifdef BOOST_HAS_GETTIMEOFDAY
+ timeval tv;
+ gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
+ boost::uint64_t micros = boost::uint64_t(tv.tv_sec)*1000000;
+ micros += (boost::uint64_t)tv.tv_usec;
+ #elif defined(BOOST_HAS_FTIME)
+ boost::winapi::FILETIME_ ft;
+ boost::winapi::GetSystemTimeAsFileTime(&ft);
+ boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
+ // and cannot be before 1970-Jan-01
+ #else
+ #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
+ #endif
+ return ustime(micros);
+ }
+};
+
+template<class TimePoint>
+class microsec_clock<TimePoint, typename enable_if_time_point<TimePoint>::type>
+{
+ public:
+ static TimePoint universal_time()
+ { return TimePoint::clock::now(); }
+};
+
+
+template<class TimePoint>
+inline TimePoint delay_ms(unsigned msecs, typename enable_if_ptime<TimePoint>::type* = 0)
+{
+ typedef typename TimePoint::time_duration_type time_duration_type;
+ typedef typename time_duration_type::rep_type resolution_traits_type;
+
+ time_duration_type td(msecs*1000*resolution_traits_type::res_adjust());
+
+ TimePoint tp(microsec_clock<TimePoint>::universal_time());
+ return (tp += td);
+}
+
+template<class TimePoint>
+inline bool is_pos_infinity(const TimePoint &abs_time, typename enable_if_ptime<TimePoint>::type* = 0)
+{
+ return abs_time.is_pos_infinity();
+}
+
+template<class TimePoint>
+inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoint>::type* = 0)
+{
+ return false;
+}
+
+/*
+template<class Duration>
+inline ustime duration_to_timepoint(const Duration &dur, typename enable_if_ptime<Duration>::type* = 0)
+{
+ return dur.is_pos_infinity();
+}
+
+template<class Duration>
+inline bool duration_to_timepoint(const Duration &, typename disable_if_ptime<Duration>::type* = 0)
+{
+ return false;
+}
+*/
+
+// duration_to_milliseconds
+
+template<class Duration>
+inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
+{
+ return static_cast<boost::uint64_t>(abs_time.total_milliseconds());
+}
+
+template<class Duration>
+inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
+{
+ const double factor = double(Duration::period::num)*1000.0/double(Duration::period::den);
+ return static_cast<boost::uint64_t>(double(d.count())*factor);
+}
+
+inline boost::uint64_t duration_to_milliseconds(const usduration &d)
+{
+ return d.get_microsecs()/1000;
+}
+
+// duration_to_usduration
+
+template<class Duration>
+inline usduration duration_to_usduration(const Duration &d, typename enable_if_ptime_duration<Duration>::type* = 0)
+{
+ return usduration(static_cast<boost::uint64_t>(d.total_microseconds()));
+}
+
+template<class Duration>
+inline usduration duration_to_usduration(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
+{
+ const double factor = double(Duration::period::num)*1000000.0/double(Duration::period::den);
+ return usduration(static_cast<boost::uint64_t>(double(d.count())*factor));
+}
+
+// duration_to_ustime
+
+template<class Duration>
+inline ustime duration_to_ustime(const Duration &d)
+{
+ return microsec_clock<ustime>::universal_time() + (duration_to_usduration)(d);
+}
+
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
+
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/utilities.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/utilities.hpp
index c1b23423c2..247dff1e88 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/utilities.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/utilities.hpp
@@ -87,7 +87,7 @@ struct ct_rounded_size
};
// Gennaro Prota wrote this. Thanks!
-template <int p, int n = 4>
+template <std::size_t p, std::size_t n = 4>
struct ct_max_pow2_less
{
static const std::size_t c = 2*n < p;
@@ -163,8 +163,8 @@ template<class T, class OffsetType>
class pointer_offset_caster<T*, OffsetType>
{
public:
- BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType offset)
- : m_offset(offset)
+ BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType off)
+ : m_offset(off)
{}
BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(const volatile T *p)
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/win32_api.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/win32_api.hpp
index d12097f512..3967b0b299 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/win32_api.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/win32_api.hpp
@@ -21,7 +21,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/date_time/filetime_functions.hpp>
+#include <boost/cstdint.hpp>
#include <cstddef>
#include <cstring>
#include <cstdlib>
@@ -31,51 +31,8 @@
#include <string>
#include <vector>
-//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
-//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
-//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
-
-#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 1
-#else
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 0
-#endif
-
-#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 1
-#else
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 0
-#endif
-
-#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 1
-#else
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 0
-#endif
-
-#define BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM \
- (BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE + \
- BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE + \
- BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE)
-
-#if 1 < BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
-# error "Only one of BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME, \
- BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED and \
- BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED can be defined"
-#endif
-
-#if 0 == BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
-# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
-#endif
-
#ifdef BOOST_USE_WINDOWS_H
#include <windows.h>
-# if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME)
-# include <wbemidl.h>
-# include <objbase.h>
-# endif
-
-#include <shlobj.h>
#endif
#if defined(_MSC_VER)
@@ -83,7 +40,6 @@
# pragma comment( lib, "Advapi32.lib" )
# pragma comment( lib, "oleaut32.lib" )
# pragma comment( lib, "Ole32.lib" )
-# pragma comment( lib, "Shell32.lib" ) //SHGetFolderPath
#endif
#if defined (BOOST_INTERPROCESS_WINDOWS)
@@ -99,631 +55,63 @@
//
//////////////////////////////////////////////////////////////////////////////
-//Ignore -pedantic errors here (anonymous structs, etc.)
+
#if defined(BOOST_GCC)
+//Ignore -pedantic errors here (anonymous structs, etc.)
# if (BOOST_GCC >= 40600)
# pragma GCC diagnostic push
-# if (BOOST_GCC >= 60000)
+# if (BOOST_GCC >= 40800)
# pragma GCC diagnostic ignored "-Wpedantic"
# else
# pragma GCC diagnostic ignored "-pedantic"
# endif
+# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
# else
# pragma GCC system_header
# endif
+//When loading DLLs we have no option but reinterpret casting function types
+# if (BOOST_GCC >= 80000)
+# pragma GCC diagnostic ignored "-Wcast-function-type"
+# endif
#endif
-namespace boost {
-namespace interprocess {
-namespace winapi {
-
-//Own defines
-static const unsigned long MaxPath = 260;
-
-#ifndef BOOST_USE_WINDOWS_H
-
-struct GUID_BIPC
-{
- unsigned long Data1;
- unsigned short Data2;
- unsigned short Data3;
- unsigned char Data4[8];
-};
-
-#if defined(_MSC_VER)
-#pragma warning (push)
-#pragma warning (disable : 4201) // nonstandard extension used
-#endif
-
-struct decimal
-{
- unsigned short wReserved;
- union {
- struct {
- unsigned char scale;
- unsigned char sign;
- };
- unsigned short signscale;
- };
- unsigned long Hi32;
- union {
- struct {
- unsigned long Lo32;
- unsigned long Mid32;
- };
- ::boost::ulong_long_type Lo64;
- };
-};
-
-typedef unsigned short *bstr;
+//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
-struct wchar_variant
-{
- union
- {
- struct
- {
- unsigned short vt;
- unsigned short wReserved1;
- unsigned short wReserved2;
- unsigned short wReserved3;
- union
- {
- bstr bstrVal;
- struct
- {
- void* pvRecord;
- void* pRecInfo;
- };
- };
- };
- decimal decVal;
- };
-};
-
-#if defined(_MSC_VER)
-#pragma warning (pop)
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 1
+#else
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 0
#endif
-struct IUnknown_BIPC
-{
- public:
- virtual long __stdcall QueryInterface(
- const GUID_BIPC &riid, // [in]
- void **ppvObject) = 0; // [iid_is][out]
-
- virtual unsigned long __stdcall AddRef (void) = 0;
- virtual unsigned long __stdcall Release(void) = 0;
-};
-
-struct IWbemClassObject_BIPC : public IUnknown_BIPC
-{
- public:
- virtual long __stdcall GetQualifierSet(
- /* [out] */ void **ppQualSet) = 0;
-
- virtual long __stdcall Get(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [unique][in][out] */ wchar_variant *pVal,
- /* [unique][in][out] */ long *pType,
- /* [unique][in][out] */ long *plFlavor) = 0;
-
- virtual long __stdcall Put(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [in] */ wchar_variant *pVal,
- /* [in] */ long Type) = 0;
-
- virtual long __stdcall Delete(
- /* [string][in] */ const bstr wszName) = 0;
-
- virtual long __stdcall GetNames(
- /* [string][in] */ const bstr wszQualifierName,
- /* [in] */ long lFlags,
- /* [in] */ wchar_variant *pQualifierVal,
- /* [out] */ void * *pNames) = 0;
-
- virtual long __stdcall BeginEnumeration(
- /* [in] */ long lEnumFlags) = 0;
-
- virtual long __stdcall Next(
- /* [in] */ long lFlags,
- /* [unique][in][out] */ bstr *strName,
- /* [unique][in][out] */ wchar_variant *pVal,
- /* [unique][in][out] */ long *pType,
- /* [unique][in][out] */ long *plFlavor) = 0;
-
- virtual long __stdcall EndEnumeration( void) = 0;
-
- virtual long __stdcall GetPropertyQualifierSet(
- /* [string][in] */ const bstr wszProperty,
- /* [out] */ void **ppQualSet) = 0;
-
- virtual long __stdcall Clone(
- /* [out] */ IWbemClassObject_BIPC **ppCopy) = 0;
-
- virtual long __stdcall GetObjectText(
- /* [in] */ long lFlags,
- /* [out] */ bstr *pstrObjectText) = 0;
-
- virtual long __stdcall SpawnDerivedClass(
- /* [in] */ long lFlags,
- /* [out] */ IWbemClassObject_BIPC **ppNewClass) = 0;
-
- virtual long __stdcall SpawnInstance(
- /* [in] */ long lFlags,
- /* [out] */ IWbemClassObject_BIPC **ppNewInstance) = 0;
-
- virtual long __stdcall CompareTo(
- /* [in] */ long lFlags,
- /* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0;
-
- virtual long __stdcall GetPropertyOrigin(
- /* [string][in] */ const bstr wszName,
- /* [out] */ bstr *pstrClassName) = 0;
-
- virtual long __stdcall InheritsFrom(
- /* [in] */ const bstr strAncestor) = 0;
-
- virtual long __stdcall GetMethod(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [out] */ IWbemClassObject_BIPC **ppInSignature,
- /* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
-
- virtual long __stdcall PutMethod(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [in] */ IWbemClassObject_BIPC *pInSignature,
- /* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0;
-
- virtual long __stdcall DeleteMethod(
- /* [string][in] */ const bstr wszName) = 0;
-
- virtual long __stdcall BeginMethodEnumeration(
- /* [in] */ long lEnumFlags) = 0;
-
- virtual long __stdcall NextMethod(
- /* [in] */ long lFlags,
- /* [unique][in][out] */ bstr *pstrName,
- /* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature,
- /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
-
- virtual long __stdcall EndMethodEnumeration( void) = 0;
-
- virtual long __stdcall GetMethodQualifierSet(
- /* [string][in] */ const bstr wszMethod,
- /* [out] */ void **ppQualSet) = 0;
-
- virtual long __stdcall GetMethodOrigin(
- /* [string][in] */ const bstr wszMethodName,
- /* [out] */ bstr *pstrClassName) = 0;
-
-};
-
-struct IWbemContext_BIPC : public IUnknown_BIPC
-{
-public:
- virtual long __stdcall Clone(
- /* [out] */ IWbemContext_BIPC **ppNewCopy) = 0;
-
- virtual long __stdcall GetNames(
- /* [in] */ long lFlags,
- /* [out] */ void * *pNames) = 0;
-
- virtual long __stdcall BeginEnumeration(
- /* [in] */ long lFlags) = 0;
-
- virtual long __stdcall Next(
- /* [in] */ long lFlags,
- /* [out] */ bstr *pstrName,
- /* [out] */ wchar_variant *pValue) = 0;
-
- virtual long __stdcall EndEnumeration( void) = 0;
-
- virtual long __stdcall SetValue(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [in] */ wchar_variant *pValue) = 0;
-
- virtual long __stdcall GetValue(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags,
- /* [out] */ wchar_variant *pValue) = 0;
-
- virtual long __stdcall DeleteValue(
- /* [string][in] */ const bstr wszName,
- /* [in] */ long lFlags) = 0;
-
- virtual long __stdcall DeleteAll( void) = 0;
-
-};
-
-
-struct IEnumWbemClassObject_BIPC : public IUnknown_BIPC
-{
-public:
- virtual long __stdcall Reset( void) = 0;
-
- virtual long __stdcall Next(
- /* [in] */ long lTimeout,
- /* [in] */ unsigned long uCount,
- /* [length_is][size_is][out] */ IWbemClassObject_BIPC **apObjects,
- /* [out] */ unsigned long *puReturned) = 0;
-
- virtual long __stdcall NextAsync(
- /* [in] */ unsigned long uCount,
- /* [in] */ void *pSink) = 0;
-
- virtual long __stdcall Clone(
- /* [out] */ void **ppEnum) = 0;
-
- virtual long __stdcall Skip(
- /* [in] */ long lTimeout,
- /* [in] */ unsigned long nCount) = 0;
-
-};
-
-struct IWbemServices_BIPC : public IUnknown_BIPC
-{
-public:
- virtual long __stdcall OpenNamespace(
- /* [in] */ const bstr strNamespace,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppWorkingNamespace,
- /* [unique][in][out] */ void **ppResult) = 0;
-
- virtual long __stdcall CancelAsyncCall(
- /* [in] */ void *pSink) = 0;
-
- virtual long __stdcall QueryObjectSink(
- /* [in] */ long lFlags,
- /* [out] */ void **ppResponseHandler) = 0;
-
- virtual long __stdcall GetObject(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppObject,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall GetObjectAsync(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall PutClass(
- /* [in] */ IWbemClassObject_BIPC *pObject,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall PutClassAsync(
- /* [in] */ IWbemClassObject_BIPC *pObject,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall DeleteClass(
- /* [in] */ const bstr strClass,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall DeleteClassAsync(
- /* [in] */ const bstr strClass,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall CreateClassEnum(
- /* [in] */ const bstr strSuperclass,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [out] */ void **ppEnum) = 0;
-
- virtual long __stdcall CreateClassEnumAsync(
- /* [in] */ const bstr strSuperclass,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall PutInstance(
- /* [in] */ void *pInst,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall PutInstanceAsync(
- /* [in] */ void *pInst,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall DeleteInstance(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall DeleteInstanceAsync(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall CreateInstanceEnum(
- /* [in] */ const bstr strFilter,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [out] */ void **ppEnum) = 0;
-
- virtual long __stdcall CreateInstanceEnumAsync(
- /* [in] */ const bstr strFilter,
- /* [in] */ long lFlags,
- /* [in] */ void *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall ExecQuery(
- /* [in] */ const bstr strQueryLanguage,
- /* [in] */ const bstr strQuery,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0;
-
- virtual long __stdcall ExecQueryAsync(
- /* [in] */ const bstr strQueryLanguage,
- /* [in] */ const bstr strQuery,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall ExecNotificationQuery(
- /* [in] */ const bstr strQueryLanguage,
- /* [in] */ const bstr strQuery,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [out] */ void **ppEnum) = 0;
-
- virtual long __stdcall ExecNotificationQueryAsync(
- /* [in] */ const bstr strQueryLanguage,
- /* [in] */ const bstr strQuery,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [in] */ void *pResponseHandler) = 0;
-
- virtual long __stdcall ExecMethod(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ const bstr strMethodName,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [in] */ IWbemClassObject_BIPC *pInParams,
- /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutParams,
- /* [unique][in][out] */ void **ppCallResult) = 0;
-
- virtual long __stdcall ExecMethodAsync(
- /* [in] */ const bstr strObjectPath,
- /* [in] */ const bstr strMethodName,
- /* [in] */ long lFlags,
- /* [in] */ IWbemContext_BIPC *pCtx,
- /* [in] */ IWbemClassObject_BIPC *pInParams,
- /* [in] */ void *pResponseHandler) = 0;
-
-};
-
-struct IWbemLocator_BIPC : public IUnknown_BIPC
-{
-public:
- virtual long __stdcall ConnectServer(
- /* [in] */ const bstr strNetworkResource,
- /* [in] */ const bstr strUser,
- /* [in] */ const bstr strPassword,
- /* [in] */ const bstr strLocale,
- /* [in] */ long lSecurityFlags,
- /* [in] */ const bstr strAuthority,
- /* [in] */ void *pCtx,
- /* [out] */ IWbemServices_BIPC **ppNamespace) = 0;
-
-};
-
-struct interprocess_overlapped
-{
- unsigned long *internal;
- unsigned long *internal_high;
- union {
- struct {
- unsigned long offset;
- unsigned long offset_high;
- }dummy;
- void *pointer;
- };
-
- void *h_event;
-};
-
-
-struct interprocess_filetime
-{
- unsigned long dwLowDateTime;
- unsigned long dwHighDateTime;
-};
-
-struct win32_find_data
-{
- unsigned long dwFileAttributes;
- interprocess_filetime ftCreationTime;
- interprocess_filetime ftLastAccessTime;
- interprocess_filetime ftLastWriteTime;
- unsigned long nFileSizeHigh;
- unsigned long nFileSizeLow;
- unsigned long dwReserved0;
- unsigned long dwReserved1;
- char cFileName[MaxPath];
- char cAlternateFileName[14];
-};
-
-struct interprocess_security_attributes
-{
- unsigned long nLength;
- void *lpSecurityDescriptor;
- int bInheritHandle;
-};
-
-struct system_info {
- union {
- unsigned long dwOemId; // Obsolete field...do not use
- struct {
- unsigned short wProcessorArchitecture;
- unsigned short wReserved;
- } dummy;
- };
- unsigned long dwPageSize;
- void * lpMinimumApplicationAddress;
- void * lpMaximumApplicationAddress;
- unsigned long * dwActiveProcessorMask;
- unsigned long dwNumberOfProcessors;
- unsigned long dwProcessorType;
- unsigned long dwAllocationGranularity;
- unsigned short wProcessorLevel;
- unsigned short wProcessorRevision;
-};
-
-struct interprocess_acl
-{
- unsigned char AclRevision;
- unsigned char Sbz1;
- unsigned short AclSize;
- unsigned short AceCount;
- unsigned short Sbz2;
-};
-
-struct interprocess_security_descriptor
-{
- unsigned char Revision;
- unsigned char Sbz1;
- unsigned short Control;
- void *Owner;
- void *Group;
- interprocess_acl *Sacl;
- interprocess_acl *Dacl;
-};
-
-struct interprocess_by_handle_file_information
-{
- unsigned long dwFileAttributes;
- interprocess_filetime ftCreationTime;
- interprocess_filetime ftLastAccessTime;
- interprocess_filetime ftLastWriteTime;
- unsigned long dwVolumeSerialNumber;
- unsigned long nFileSizeHigh;
- unsigned long nFileSizeLow;
- unsigned long nNumberOfLinks;
- unsigned long nFileIndexHigh;
- unsigned long nFileIndexLow;
-};
-
-struct interprocess_eventlogrecord
-{
- unsigned long Length; // Length of full record
- unsigned long Reserved; // Used by the service
- unsigned long RecordNumber; // Absolute record number
- unsigned long TimeGenerated; // Seconds since 1-1-1970
- unsigned long TimeWritten; // Seconds since 1-1-1970
- unsigned long EventID;
- unsigned short EventType;
- unsigned short NumStrings;
- unsigned short EventCategory;
- unsigned short ReservedFlags; // For use with paired events (auditing)
- unsigned long ClosingRecordNumber; // For use with paired events (auditing)
- unsigned long StringOffset; // Offset from beginning of record
- unsigned long UserSidLength;
- unsigned long UserSidOffset;
- unsigned long DataLength;
- unsigned long DataOffset; // Offset from beginning of record
- //
- // Then follow:
- //
- // wchar_t SourceName[]
- // wchar_t Computername[]
- // SID UserSid
- // wchar_t Strings[]
- // BYTE Data[]
- // CHAR Pad[]
- // unsigned long Length;
- //
-};
-
-union large_integer
-{
- __int64 QuadPart;
-};
-
-struct hinstance_struct { int unused; };
-typedef hinstance_struct *hmodule;
-
-struct hkey_struct;
-typedef hkey_struct *hkey;
-
-#ifdef _WIN64
-typedef __int64 (__stdcall *farproc_t)();
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 1
#else
-typedef int (__stdcall *farproc_t)();
-#endif // _WIN64
-
-#else //#ifndef BOOST_USE_WINDOWS_H
-
-typedef GUID GUID_BIPC;
-typedef VARIANT wchar_variant;
-
-#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME)
-
-typedef IUnknown IUnknown_BIPC;
-
-typedef IWbemClassObject IWbemClassObject_BIPC;
-
-typedef IWbemContext IWbemContext_BIPC;
-
-typedef IEnumWbemClassObject IEnumWbemClassObject_BIPC;
-
-typedef IWbemServices IWbemServices_BIPC;
-
-typedef IWbemLocator IWbemLocator_BIPC;
-
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 0
#endif
-typedef OVERLAPPED interprocess_overlapped;
-
-typedef FILETIME interprocess_filetime;
-
-typedef WIN32_FIND_DATAA win32_find_data;
-
-typedef SECURITY_ATTRIBUTES interprocess_security_attributes;
-
-typedef SYSTEM_INFO system_info;
-
-typedef ACL interprocess_acl;
-
-typedef SECURITY_DESCRIPTOR interprocess_security_descriptor;
-
-typedef BY_HANDLE_FILE_INFORMATION interprocess_by_handle_file_information;
-
-typedef EVENTLOGRECORD interprocess_eventlogrecord;
-
-typedef LARGE_INTEGER large_integer;
+#define BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM \
+ (BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE + \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE)
-typedef HMODULE hmodule;
+#if 1 < BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
+# error "Only one of \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED and \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED can be defined"
+#endif
-typedef HKEY hkey;
+#if 0 == BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
+#endif
-typedef BSTR bstr;
-typedef FARPROC farproc_t;
+namespace boost {
+namespace interprocess {
+namespace winapi {
-#endif //#ifndef BOOST_USE_WINDOWS_H
+//Own defines
+static const unsigned long MaxPath = 260;
//////////////////////////////////////////////////////////////////////////////
//
@@ -733,8 +121,8 @@ typedef FARPROC farproc_t;
struct interprocess_semaphore_basic_information
{
- unsigned int count; // current semaphore count
- unsigned int limit; // max semaphore count
+ unsigned long count; // current semaphore count
+ unsigned long limit; // max semaphore count
};
struct interprocess_section_basic_information
@@ -876,148 +264,212 @@ enum section_information_class
section_image_information
};
+} //namespace winapi {
+} //namespace interprocess {
+} //namespace boost {
+
+
//////////////////////////////////////////////////////////////////////////////
//
// Forward declaration of winapi
//
//////////////////////////////////////////////////////////////////////////////
+#include <boost/winapi/get_current_process_id.hpp>
+#include <boost/winapi/get_current_thread_id.hpp>
+#include <boost/winapi/get_current_process.hpp>
+#include <boost/winapi/get_process_times.hpp>
+#include <boost/winapi/error_codes.hpp>
+#include <boost/winapi/thread.hpp>
+#include <boost/winapi/system.hpp>
+#include <boost/winapi/time.hpp>
+#include <boost/winapi/timers.hpp>
+#include <boost/winapi/get_last_error.hpp>
+#include <boost/winapi/handles.hpp>
+#include <boost/winapi/file_management.hpp>
+#include <boost/winapi/mutex.hpp>
+#include <boost/winapi/wait.hpp>
+#include <boost/winapi/file_mapping.hpp>
+#include <boost/winapi/semaphore.hpp>
+#include <boost/winapi/system.hpp>
+#include <boost/winapi/error_handling.hpp>
+#include <boost/winapi/local_memory.hpp>
+#include <boost/winapi/directory_management.hpp>
+#include <boost/winapi/security.hpp>
+#include <boost/winapi/dll.hpp>
+#include <boost/winapi/basic_types.hpp>
+
+//This should go in winapi's basic_types.hpp
+namespace boost {
+namespace ipwinapiext {
+typedef boost::winapi::LONG_ LSTATUS;
+
+typedef boost::winapi::DWORD_ (__stdcall *LPTHREAD_START_ROUTINE_)
+ (boost::winapi::LPVOID_ lpThreadParameter);
+
+
+//#ifndef BOOST_USE_WINDOWS_H
+//typedef boost::winapi::LARGE_INTEGER_ LARGE_INTEGER_EXT;
+//#else
+//typedef LARGE_INTEGER LARGE_INTEGER_EXT;
+//#endif
+
+}} //namespace boost::ipwinapiext
+
#ifndef BOOST_USE_WINDOWS_H
-//Kernel32.dll
+extern "C" {
-//Some windows API declarations
-extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
-extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
-extern "C" __declspec(dllimport) int __stdcall GetProcessTimes
- ( void *hProcess, interprocess_filetime* lpCreationTime
- , interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime
- , interprocess_filetime *lpUserTime );
-extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
-extern "C" __declspec(dllimport) unsigned long __stdcall GetTickCount(void);
-extern "C" __declspec(dllimport) int __stdcall SwitchToThread();
-extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
-extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long);
-extern "C" __declspec(dllimport) void * __stdcall GetCurrentProcess();
-extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*);
-extern "C" __declspec(dllimport) int __stdcall DuplicateHandle
- ( void *hSourceProcessHandle, void *hSourceHandle
- , void *hTargetProcessHandle, void **lpTargetHandle
- , unsigned long dwDesiredAccess, int bInheritHandle
- , unsigned long dwOptions);
-extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile);
-extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data *lpFindFileData);
-extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data *lpFindFileData);
-extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
-//extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
-//extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out);
-extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *);
-extern "C" __declspec(dllimport) void * __stdcall OpenMutexA(unsigned long, int, const char *);
-extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void *, unsigned long);
-extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void *);
-extern "C" __declspec(dllimport) int __stdcall UnmapViewOfFile(void *);
-extern "C" __declspec(dllimport) void * __stdcall CreateSemaphoreA(interprocess_security_attributes*, long, long, const char *);
-extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void *, long, long *);
-extern "C" __declspec(dllimport) void * __stdcall OpenSemaphoreA(unsigned long, int, const char *);
-extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, interprocess_security_attributes*, unsigned long, unsigned long, unsigned long, const char *);
-extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*);
-extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
-extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *);
-extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
-extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
-extern "C" __declspec(dllimport) int __stdcall VirtualUnlock (void *, std::size_t);
-extern "C" __declspec(dllimport) int __stdcall VirtualProtect (void *, std::size_t, unsigned long, unsigned long *);
-extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *);
-extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, large_integer *size);
-extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
- (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
- unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize,
- std::va_list *Arguments);
-extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *);
-extern "C" __declspec(dllimport) unsigned long __stdcall GetFileAttributesA(const char *);
-extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*);
-extern "C" __declspec(dllimport) int __stdcall RemoveDirectoryA(const char *lpPathName);
-extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer);
-extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*);
-extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size);
-extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *);
-extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, large_integer distance, large_integer *new_file_pointer, unsigned long move_method);
-extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
-extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
-extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
-extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
-extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped);
-extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped);
-extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
-extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
-extern "C" __declspec(dllimport) hmodule __stdcall LoadLibraryA(const char *);
-extern "C" __declspec(dllimport) int __stdcall FreeLibrary(hmodule);
-extern "C" __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char*);
-extern "C" __declspec(dllimport) hmodule __stdcall GetModuleHandleA(const char*);
-extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
-
-//Advapi32.dll
-extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(hkey, const char *, unsigned long, unsigned long, hkey*);
-extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(hkey, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
-extern "C" __declspec(dllimport) long __stdcall RegCloseKey(hkey);
-
-//Ole32.dll
-extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit);
-extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
- void* pSecDesc,
- long cAuthSvc,
- void * asAuthSvc,
- void *pReserved1,
- unsigned long dwAuthnLevel,
- unsigned long dwImpLevel,
- void *pAuthList,
- unsigned long dwCapabilities,
- void *pReserved3 );
-
- extern "C" __declspec(dllimport) long __stdcall CoSetProxyBlanket(
- IUnknown_BIPC *pProxy,
- unsigned long dwAuthnSvc,
- unsigned long dwAuthzSvc,
- wchar_t *pServerPrincName,
- unsigned long dwAuthnLevel,
- unsigned long dwImpLevel,
- void *pAuthInfo,
- unsigned long dwCapabilities);
-extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_BIPC & rclsid, IUnknown_BIPC *pUnkOuter,
- unsigned long dwClsContext, const GUID_BIPC & riid, void** ppv);
-extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void);
-
-//OleAut32.dll
-extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
-
-//Shell32.dll
-extern "C" __declspec(dllimport) int __stdcall SHGetSpecialFolderPathA
- (void* hwnd, const char *pszPath, int csidl, int fCreate);
-
-extern "C" __declspec(dllimport) int __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, const char *pszPath);
-
-//EventLog access functions
-
-extern "C" __declspec(dllimport) void* __stdcall OpenEventLogA
- (const char* lpUNCServerName, const char* lpSourceName);
-
-extern "C" __declspec(dllimport) int __stdcall CloseEventLog(void *hEventLog);
-
-extern "C" __declspec(dllimport) int __stdcall ReadEventLogA
- (void *hEventLog,
- unsigned long dwReadFlags,
- unsigned long dwRecordOffset,
- void *lpBuffer,
- unsigned long nNumberOfBytesToRead,
- unsigned long *pnBytesRead,
- unsigned long *pnMinNumberOfBytesNeeded
+//Error handling
+BOOST_SYMBOL_IMPORT BOOST_WINAPI_DETAIL_VOID BOOST_WINAPI_WINAPI_CC SetLastError(boost::winapi::DWORD_ dwErrCode);
+
+//File management
+BOOST_SYMBOL_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC GetFileType(boost::winapi::HANDLE_ hTemplateFile);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC FlushFileBuffers(boost::winapi::HANDLE_ hFile);
+
+//threading
+
+BOOST_SYMBOL_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateThread
+ ( ::_SECURITY_ATTRIBUTES* lpThreadAttributes
+ , boost::winapi::SIZE_T_ dwStackSize
+ , boost::ipwinapiext::LPTHREAD_START_ROUTINE_ lpStartAddress
+ , boost::winapi::LPVOID_ lpParameter
+ , boost::winapi::DWORD_ dwCreationFlags
+ , boost::winapi::LPDWORD_ lpThreadId
);
+//Virtual Memory
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC VirtualLock(boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC VirtualUnlock(boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC VirtualProtect( boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize
+ , boost::winapi::DWORD_ flNewProtect, boost::winapi::PDWORD_ lpflOldProtect);
+//registry.hpp
+BOOST_WINAPI_DETAIL_DECLARE_HANDLE(HKEY);
+
+
+BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegOpenKeyExA
+ (::HKEY hKey, const char *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, ::HKEY *phkResult);
+BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegOpenKeyExW
+ (::HKEY hKey, const wchar_t *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, ::HKEY *phkResult);
+BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegQueryValueExA
+ (::HKEY hKey, const char *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData);
+BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegQueryValueExW
+ (::HKEY hKey, const wchar_t *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData);
+BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegCloseKey(::HKEY hKey);
+
+
+//Event Log
+BOOST_SYMBOL_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC OpenEventLogA(const char* lpUNCServerName, const char* lpSourceName);
+BOOST_SYMBOL_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC OpenEventLogW(const wchar_t* lpUNCServerName, const wchar_t* lpSourceName);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CloseEventLog(boost::winapi::HANDLE_ hEventLog);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ReadEventLogA
+ ( boost::winapi::HANDLE_ hEventLog, boost::winapi::DWORD_ dwReadFlags, boost::winapi::DWORD_ dwRecordOffset, void* lpBuffer
+ , boost::winapi::DWORD_ nNumberOfBytesToRead, boost::winapi::DWORD_ *pnBytesRead, boost::winapi::DWORD_ *pnMinNumberOfBytesNeeded);
+BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ReadEventLogW
+ ( boost::winapi::HANDLE_ hEventLog, boost::winapi::DWORD_ dwReadFlags, boost::winapi::DWORD_ dwRecordOffset, void* lpBuffer
+ , boost::winapi::DWORD_ nNumberOfBytesToRead, boost::winapi::DWORD_ *pnBytesRead, boost::winapi::DWORD_ *pnMinNumberOfBytesNeeded);
+
+} //extern "C" {
+
#endif //#ifndef BOOST_USE_WINDOWS_H
-//kernel32.dll
-typedef int (__stdcall *QueryPerformanceCounter_t) (__int64 *lpPerformanceCount);
-typedef int (__stdcall *QueryPerformanceFrequency_t)(__int64 *lpFrequency);
+namespace boost {
+namespace ipwinapiext {
+
+typedef ::HKEY HKEY_;
+
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+
+//Threads
+BOOST_FORCEINLINE boost::winapi::HANDLE_ CreateThread
+ ( boost::winapi::SECURITY_ATTRIBUTES_* lpThreadAttributes
+ , boost::winapi::SIZE_T_ dwStackSize
+ , boost::ipwinapiext::LPTHREAD_START_ROUTINE_ lpStartAddress
+ , boost::winapi::LPVOID_ lpParameter
+ , boost::winapi::DWORD_ dwCreationFlags
+ , boost::winapi::LPDWORD_ lpThreadId
+)
+{
+ return ::CreateThread( reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes)
+ , dwStackSize, lpStartAddress
+ , lpParameter, dwCreationFlags, lpThreadId);
+}
+
+//Error handling
+BOOST_FORCEINLINE BOOST_WINAPI_DETAIL_VOID SetLastError(boost::winapi::DWORD_ dwErrCode)
+{ ::SetLastError(dwErrCode); }
+
+//File management
+BOOST_FORCEINLINE boost::winapi::DWORD_ GetFileType(boost::winapi::HANDLE_ hTemplateFile)
+{ return ::GetFileType(hTemplateFile); }
+
+BOOST_FORCEINLINE boost::winapi::BOOL_ FlushFileBuffers(boost::winapi::HANDLE_ hFile)
+{ return ::FlushFileBuffers(hFile); }
+
+//Virtual Memory
+BOOST_FORCEINLINE boost::winapi::BOOL_ VirtualLock(boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize)
+{ return ::VirtualLock(lpAddress, dwSize); }
+
+BOOST_FORCEINLINE boost::winapi::BOOL_ VirtualUnlock(boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize)
+{ return ::VirtualUnlock(lpAddress, dwSize); }
+
+BOOST_FORCEINLINE boost::winapi::BOOL_ VirtualProtect( boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize
+ , boost::winapi::DWORD_ flNewProtect, boost::winapi::PDWORD_ lpflOldProtect)
+{ return ::VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect); }
+
+//registry.hpp
+BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegOpenKeyExA
+ (boost::ipwinapiext::HKEY_ hKey, const char *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, boost::ipwinapiext::HKEY_ *phkResult)
+{
+ return ::RegOpenKeyExA(reinterpret_cast< ::HKEY >(hKey), lpSubKey, ulOptions, samDesired, reinterpret_cast< ::HKEY* >(phkResult));
+}
+
+BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegOpenKeyExW
+ (boost::ipwinapiext::HKEY_ hKey, const wchar_t *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, boost::ipwinapiext::HKEY_ *phkResult)
+{
+ return ::RegOpenKeyExW(reinterpret_cast< ::HKEY >(hKey), lpSubKey, ulOptions, samDesired, reinterpret_cast< ::HKEY* >(phkResult));
+}
+
+BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegQueryValueExA
+ (boost::ipwinapiext::HKEY_ hKey, const char *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData)
+{
+ return ::RegQueryValueExA(reinterpret_cast< ::HKEY >(hKey), lpValueName, lpReserved, lpType, lpData, lpcbData);
+}
+
+BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegQueryValueExW
+ (boost::ipwinapiext::HKEY_ hKey, const wchar_t *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData)
+{
+ return ::RegQueryValueExW(reinterpret_cast< ::HKEY >(hKey), lpValueName, lpReserved, lpType, lpData, lpcbData);
+}
+
+BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegCloseKey(boost::ipwinapiext::HKEY_ hKey)
+{
+ return ::RegCloseKey(reinterpret_cast< ::HKEY >(hKey));
+}
+
+BOOST_FORCEINLINE void GetSystemInfo(boost::winapi::LPSYSTEM_INFO_ lpSystemInfo)
+{ return ::GetSystemInfo(reinterpret_cast< ::_SYSTEM_INFO* >(lpSystemInfo)); }
+
+#endif //BOOST_WINAPI_PARTITION_APP_SYSTEM
+
+} //namespace ipwinapiext {
+} //namespace boost {
+
+namespace boost {
+namespace interprocess {
+namespace winapi {
+
+typedef boost::winapi::SYSTEM_INFO_ interprocess_system_info;
+typedef boost::winapi::OVERLAPPED_ interprocess_overlapped;
+typedef boost::winapi::FILETIME_ interprocess_filetime;
+typedef boost::winapi::WIN32_FIND_DATAA_ win32_find_data_a;
+typedef boost::winapi::WIN32_FIND_DATAW_ win32_find_data_w;
+typedef boost::winapi::SECURITY_ATTRIBUTES_ interprocess_security_attributes;
+typedef boost::winapi::SECURITY_DESCRIPTOR_ interprocess_security_descriptor;
+typedef boost::winapi::BY_HANDLE_FILE_INFORMATION_ interprocess_by_handle_file_information;
+typedef boost::winapi::HMODULE_ hmodule;
+typedef boost::ipwinapiext::HKEY_ hkey;
+typedef boost::winapi::FARPROC_ farproc_t;
//ntdll.dll
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
@@ -1177,27 +629,6 @@ const unsigned long max_path = 260;
static const hkey hkey_local_machine = (hkey)(unsigned long*)(long)(0x80000002);
static unsigned long key_query_value = 0x0001;
-//COM API
-const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4;
-const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL;
-const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL;
-const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3;
-const signed long EOAC_NONE_BIPC = 0;
-const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1;
-const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4;
-const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10;
-const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0;
-const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20;
-const signed long WBEM_INFINITE_BIPC = 0xffffffffL;
-const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L;
-const signed long S_OK_BIPC = 0L;
-const signed long S_FALSE_BIPC = 1;
-const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L;
-const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2;
-const unsigned long COINIT_MULTITHREADED_BIPC = 0x0;
-const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4;
-const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4;
-
// Registry types
#define reg_none ( 0 ) // No value type
#define reg_sz ( 1 ) // Unicode nul terminated string
@@ -1216,30 +647,6 @@ const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4;
#define reg_qword_little_endian ( 11 ) // 64-bit number (same as reg_qword)
-//If the user needs to change default COM initialization model,
-//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these:
-//
-// COINIT_APARTMENTTHREADED_BIPC
-// COINIT_MULTITHREADED_BIPC
-// COINIT_DISABLE_OLE1DDE_BIPC
-// COINIT_SPEED_OVER_MEMORY_BIPC
-#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL)
- #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC
-#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\
- (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC)
- #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro"
-#endif
-
-const GUID_BIPC CLSID_WbemAdministrativeLocator =
- { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}};
-
-const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
-
-static const unsigned long eventlog_sequential_read = 0x0001;
-static const unsigned long eventlog_backwards_read = 0x0008;
-
} //namespace winapi {
} //namespace interprocess {
} //namespace boost {
@@ -1269,7 +676,11 @@ inline void * local_free(void *hmem)
{ return LocalFree(hmem); }
inline unsigned long make_lang_id(unsigned long p, unsigned long s)
-{ return ((((unsigned short)(s)) << 10) | (unsigned short)(p)); }
+{
+ const unsigned short s_us = (unsigned short)s;
+ const unsigned short p_us = (unsigned short)p;
+ return (unsigned long)((s_us << 10) | p_us);
+}
inline void sched_yield()
{
@@ -1296,15 +707,21 @@ inline bool get_process_times
inline unsigned long get_current_process_id()
{ return GetCurrentProcessId(); }
-inline unsigned int close_handle(void* handle)
-{ return CloseHandle(handle); }
+inline bool close_handle(void* handle)
+{ return CloseHandle(handle) != 0; }
-inline void * find_first_file(const char *lpFileName, win32_find_data *lpFindFileData)
+inline void * find_first_file(const char *lpFileName, win32_find_data_a *lpFindFileData)
{ return FindFirstFileA(lpFileName, lpFindFileData); }
-inline bool find_next_file(void *hFindFile, win32_find_data *lpFindFileData)
+inline void * find_first_file(const wchar_t *lpFileName, win32_find_data_w *lpFindFileData)
+{ return FindFirstFileW(lpFileName, lpFindFileData); }
+
+inline bool find_next_file(void *hFindFile, win32_find_data_a *lpFindFileData)
{ return FindNextFileA(hFindFile, lpFindFileData) != 0; }
+inline bool find_next_file(void *hFindFile, win32_find_data_w *lpFindFileData)
+{ return FindNextFileW(hFindFile, lpFindFileData) != 0; }
+
inline bool find_close(void *handle)
{ return FindClose(handle) != 0; }
@@ -1333,6 +750,9 @@ inline bool file_time_to_local_file_time
inline void *open_or_create_mutex(const char *name, bool initial_owner, interprocess_security_attributes *attr)
{ return CreateMutexA(attr, (int)initial_owner, name); }
+inline void *open_or_create_mutex(const wchar_t *name, bool initial_owner, interprocess_security_attributes *attr)
+{ return CreateMutexW(attr, (int)initial_owner, name); }
+
inline unsigned long wait_for_single_object(void *handle, unsigned long time)
{ return WaitForSingleObject(handle, time); }
@@ -1345,9 +765,15 @@ inline int unmap_view_of_file(void *address)
inline void *open_or_create_semaphore(const char *name, long initial_count, long maximum_count, interprocess_security_attributes *attr)
{ return CreateSemaphoreA(attr, initial_count, maximum_count, name); }
+inline void *open_or_create_semaphore(const wchar_t *name, long initial_count, long maximum_count, interprocess_security_attributes *attr)
+{ return CreateSemaphoreW(attr, initial_count, maximum_count, name); }
+
inline void *open_semaphore(const char *name)
{ return OpenSemaphoreA(semaphore_all_access, 0, name); }
+inline void *open_semaphore(const wchar_t *name)
+{ return OpenSemaphoreW(semaphore_all_access, 0, name); }
+
inline int release_semaphore(void *handle, long release_count, long *prev_count)
{ return ReleaseSemaphore(handle, release_count, prev_count); }
@@ -1361,14 +787,14 @@ class interprocess_all_access_security
interprocess_all_access_security()
: initialized(false)
{
- if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision))
+ if(!boost::winapi::InitializeSecurityDescriptor(&sd, security_descriptor_revision))
return;
- if(!SetSecurityDescriptorDacl(&sd, true, 0, false))
+ if(!boost::winapi::SetSecurityDescriptorDacl(&sd, true, 0, false))
return;
sa.lpSecurityDescriptor = &sd;
sa.nLength = sizeof(interprocess_security_attributes);
sa.bInheritHandle = false;
- initialized = false;
+ initialized = true;
}
interprocess_security_attributes *get_attributes()
@@ -1377,24 +803,36 @@ class interprocess_all_access_security
inline void * create_file_mapping (void * handle, unsigned long access, ::boost::ulong_long_type file_offset, const char * name, interprocess_security_attributes *psec)
{
- const unsigned long high_size(file_offset >> 32), low_size((boost::uint32_t)file_offset);
+ const boost::winapi::DWORD_ high_size = boost::winapi::DWORD_(file_offset >> 32);
+ const boost::winapi::DWORD_ low_size = boost::winapi::DWORD_(file_offset);
return CreateFileMappingA (handle, psec, access, high_size, low_size, name);
}
+inline void * create_file_mapping (void * handle, unsigned long access, ::boost::ulong_long_type file_offset, const wchar_t * name, interprocess_security_attributes *psec)
+{
+ const boost::winapi::DWORD_ high_size = boost::winapi::DWORD_(file_offset >> 32);
+ const boost::winapi::DWORD_ low_size = boost::winapi::DWORD_(file_offset);
+ return CreateFileMappingW (handle, psec, access, high_size, low_size, name);
+}
+
inline void * open_file_mapping (unsigned long access, const char *name)
{ return OpenFileMappingA (access, 0, name); }
+inline void * open_file_mapping (unsigned long access, const wchar_t *name)
+{ return OpenFileMappingW (access, 0, name); }
+
inline void *map_view_of_file_ex(void *handle, unsigned long file_access, ::boost::ulong_long_type offset, std::size_t numbytes, void *base_addr)
{
- const unsigned long offset_low = (unsigned long)(offset & ((::boost::ulong_long_type)0xFFFFFFFF));
- const unsigned long offset_high = offset >> 32;
+ const boost::winapi::DWORD_ offset_low = boost::winapi::DWORD_(offset & ((::boost::ulong_long_type)0xFFFFFFFF));
+ const boost::winapi::DWORD_ offset_high = boost::winapi::DWORD_(offset >> 32);
return MapViewOfFileEx(handle, file_access, offset_high, offset_low, numbytes, base_addr);
}
-inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec)
+template<class CharT>
+inline void *create_file(const CharT *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec)
{
for (unsigned int attempt(0); attempt < error_sharing_violation_tries; ++attempt){
- void * const handle = CreateFileA(name, access,
+ void * const handle = boost::winapi::create_file(name, access,
file_share_read | file_share_write | file_share_delete,
psec, creation_flags, attributes, 0);
bool const invalid(invalid_handle_value == handle);
@@ -1409,59 +847,68 @@ inline void *create_file(const char *name, unsigned long access, unsigned long c
return invalid_handle_value;
}
-inline void get_system_info(system_info *info)
-{ GetSystemInfo(info); }
+inline void get_system_info(interprocess_system_info *info)
+{ boost::ipwinapiext::GetSystemInfo(info); }
inline bool flush_view_of_file(void *base_addr, std::size_t numbytes)
-{ return 0 != FlushViewOfFile(base_addr, numbytes); }
+{ return 0 != boost::winapi::FlushViewOfFile(base_addr, numbytes); }
inline bool virtual_unlock(void *base_addr, std::size_t numbytes)
-{ return 0 != VirtualUnlock(base_addr, numbytes); }
+{ return 0 != boost::ipwinapiext::VirtualUnlock(base_addr, numbytes); }
inline bool virtual_protect(void *base_addr, std::size_t numbytes, unsigned long flNewProtect, unsigned long &lpflOldProtect)
-{ return 0 != VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); }
+{ return 0 != boost::ipwinapiext::VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); }
inline bool flush_file_buffers(void *handle)
-{ return 0 != FlushFileBuffers(handle); }
+{ return 0 != boost::ipwinapiext::FlushFileBuffers(handle); }
inline bool get_file_size(void *handle, __int64 &size)
-{ return 0 != GetFileSizeEx(handle, (large_integer*)&size); }
+{ return 0 != boost::winapi::GetFileSizeEx(handle, (boost::winapi::LARGE_INTEGER_*)&size); }
-inline bool create_directory(const char *name)
+template<class CharT>
+inline bool create_directory(const CharT *name)
{
interprocess_all_access_security sec;
- return 0 != CreateDirectoryA(name, sec.get_attributes());
+ return 0 != boost::winapi::create_directory(name, sec.get_attributes());
}
-inline bool remove_directory(const char *lpPathName)
-{ return 0 != RemoveDirectoryA(lpPathName); }
+template<class CharT>
+inline bool remove_directory(const CharT *lpPathName)
+{ return 0 != boost::winapi::remove_directory(lpPathName); }
-inline unsigned long get_temp_path(unsigned long length, char *buffer)
-{ return GetTempPathA(length, buffer); }
+template<class CharT>
+inline unsigned long get_temp_path(unsigned long length, CharT *buffer)
+{ return boost::winapi::get_temp_path(length, buffer); }
inline int set_end_of_file(void *handle)
-{ return 0 != SetEndOfFile(handle); }
+{ return 0 != boost::winapi::SetEndOfFile(handle); }
-inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method)
+inline bool set_file_pointer(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method)
{
- large_integer d; d.QuadPart = distance;
- return 0 != SetFilePointerEx(handle, d, (large_integer*)new_file_pointer, move_method);
+ boost::winapi::LONG_ highPart = boost::winapi::LONG_(distance >> 32u);
+ boost::winapi::DWORD_ r = boost::winapi::SetFilePointer(handle, (long)distance, &highPart, move_method);
+ bool br = r != boost::winapi::INVALID_SET_FILE_POINTER_ || boost::winapi::GetLastError() != 0;
+ if (br && new_file_pointer){
+ *new_file_pointer = (__int64)r + ((__int64)highPart << 32);
+ }
+
+ return br;
}
inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
-{ return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); }
+{ return 0 != boost::winapi::LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); }
inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
-{ return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); }
+{ return 0 != boost::winapi::UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); }
inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped)
-{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
+{ return 0 != boost::winapi::WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
inline bool read_file(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped)
-{ return 0 != ReadFile(hnd, buffer, bytes_to_read, bytes_read, overlapped); }
+{ return 0 != boost::winapi::ReadFile(hnd, buffer, bytes_to_read, bytes_read, overlapped); }
inline bool get_file_information_by_handle(void *hnd, interprocess_by_handle_file_information *info)
-{ return 0 != GetFileInformationByHandle(hnd, info); }
+{ return 0 != boost::winapi::GetFileInformationByHandle(hnd, info); }
inline long interlocked_increment(long volatile *addr)
{ return BOOST_INTERLOCKED_INCREMENT(const_cast<long*>(addr)); }
@@ -1480,28 +927,35 @@ inline long interlocked_exchange(long volatile* addend, long value)
//Forward functions
inline hmodule load_library(const char *name)
-{ return LoadLibraryA(name); }
+{ return boost::winapi::LoadLibraryA(name); }
inline bool free_library(hmodule module)
-{ return 0 != FreeLibrary(module); }
+{ return 0 != boost::winapi::FreeLibrary(module); }
inline farproc_t get_proc_address(hmodule module, const char *name)
-{ return GetProcAddress(module, name); }
+{ return boost::winapi::GetProcAddress(module, name); }
inline void *get_current_process()
-{ return GetCurrentProcess(); }
+{ return boost::winapi::GetCurrentProcess(); }
inline hmodule get_module_handle(const char *name)
-{ return GetModuleHandleA(name); }
+{ return boost::winapi::GetModuleHandleA(name); }
inline long reg_open_key_ex(hkey hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult)
-{ return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
+{ return boost::ipwinapiext::RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
+
+inline long reg_open_key_ex(hkey hKey, const wchar_t *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult)
+{ return boost::ipwinapiext::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
+
inline long reg_query_value_ex(hkey hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData)
-{ return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
+{ return boost::ipwinapiext::RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
+
+inline long reg_query_value_ex(hkey hKey, const wchar_t *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData)
+{ return boost::ipwinapiext::RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
inline long reg_close_key(hkey hKey)
-{ return RegCloseKey(hKey); }
+{ return boost::ipwinapiext::RegCloseKey(hKey); }
inline void initialize_object_attributes
( object_attributes_t *pobject_attr, unicode_string_t *name
@@ -1535,9 +989,6 @@ struct function_address_holder
, NtOpenFile
, NtClose
, NtQueryTimerResolution
- , NtSetTimerResolution
- , QueryPerformanceCounter
- , QueryPerformanceFrequency
, NumFunction
};
enum { NtDll_dll, Kernel32_dll, NumModule };
@@ -1618,9 +1069,6 @@ const char *function_address_holder<Dummy>::FunctionNames[function_address_holde
"NtOpenFile",
"NtClose",
"NtQueryTimerResolution",
- "NtSetTimerResolution",
- "QueryPerformanceCounter",
- "QueryPerformanceFrequency"
};
template<int Dummy>
@@ -1634,16 +1082,12 @@ unsigned int function_address_holder<Dummy>::FunctionModules[function_address_ho
NtDll_dll,
NtDll_dll,
NtDll_dll,
- NtDll_dll,
- Kernel32_dll,
- Kernel32_dll
};
template<int Dummy>
const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] =
{
- "ntdll.dll",
- "kernel32.dll"
+ "ntdll.dll"//, "kernel32.dll"
};
@@ -1675,8 +1119,8 @@ struct library_unloader
inline bool get_system_time_of_day_information(system_timeofday_information &info)
{
- NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t)
- dll_func::get(dll_func::NtQuerySystemInformation);
+ NtQuerySystemInformation_t pNtQuerySystemInformation = reinterpret_cast<NtQuerySystemInformation_t>
+ (dll_func::get(dll_func::NtQuerySystemInformation));
unsigned long res;
long status = pNtQuerySystemInformation(system_time_of_day_information, &info, sizeof(info), &res);
if(status){
@@ -1780,17 +1224,6 @@ class handle_closer
{ close_handle(handle_); }
};
-class eventlog_handle_closer
-{
- void *handle_;
- eventlog_handle_closer(const handle_closer &);
- eventlog_handle_closer& operator=(const eventlog_handle_closer &);
- public:
- explicit eventlog_handle_closer(void *handle) : handle_(handle){}
- ~eventlog_handle_closer()
- { CloseEventLog(handle_); }
-};
-
union ntquery_mem_t
{
object_name_information_t name;
@@ -1807,11 +1240,11 @@ class nt_query_mem_deleter
offsetof(ntquery_mem_t, name.Name.Buffer);
// Timestamp process id atomic count
static const std::size_t rename_suffix =
- (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2;
+ (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::winapi::DWORD_))*2;
public:
- explicit nt_query_mem_deleter(std::size_t object_name_information_size)
- : m_size(object_name_information_size + rename_offset + rename_suffix)
+ explicit nt_query_mem_deleter(std::size_t object_name_info_size)
+ : m_size(object_name_info_size + rename_offset + rename_suffix)
, m_buf(new char [m_size])
{}
@@ -1859,10 +1292,10 @@ class c_heap_deleter
void realloc_mem(std::size_t num_bytes)
{
- void *buf = ::realloc(m_buf, num_bytes);
- if(!buf){
- free(m_buf);
- m_buf = 0;
+ void *oldBuf = m_buf;
+ m_buf = ::realloc(m_buf, num_bytes);
+ if (!m_buf){
+ free(oldBuf);
}
}
@@ -1873,7 +1306,8 @@ class c_heap_deleter
void *m_buf;
};
-inline bool unlink_file(const char *filename)
+template<class CharT>
+inline bool unlink_file(const CharT *filename)
{
//Don't try to optimize doing a DeleteFile first
//as there are interactions with permissions and
@@ -1890,11 +1324,11 @@ inline bool unlink_file(const char *filename)
//- Close the handle. If there are no file users, it will be deleted.
// Otherwise it will be used by already connected handles but the
// file name can't be used to open this file again
- try{
+ BOOST_TRY{
NtSetInformationFile_t pNtSetInformationFile =
- (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile);
+ reinterpret_cast<NtSetInformationFile_t>(dll_func::get(dll_func::NtSetInformationFile));
- NtQueryObject_t pNtQueryObject = (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
+ NtQueryObject_t pNtQueryObject = reinterpret_cast<NtQueryObject_t>(dll_func::get(dll_func::NtQueryObject));
//First step: Obtain a handle to the file using Win32 rules. This resolves relative paths
void *fh = create_file(filename, generic_read | delete_access, open_existing, 0, 0);
@@ -1920,7 +1354,7 @@ inline bool unlink_file(const char *filename)
ntquery_mem_t *pmem = nt_query_mem.query_mem();
file_rename_information_t *pfri = &pmem->ren.info;
const std::size_t RenMaxNumChars =
- (((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
+ std::size_t(((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
//Copy filename to the rename member
std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
@@ -1966,8 +1400,8 @@ inline bool unlink_file(const char *filename)
{
//Don't use pNtSetInformationFile with file_disposition_information as it can return STATUS_CANNOT_DELETE
//if the file is still mapped. Reopen it with NtOpenFile and file_delete_on_close
- NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile);
- NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose);
+ NtOpenFile_t pNtOpenFile = reinterpret_cast<NtOpenFile_t>(dll_func::get(dll_func::NtOpenFile));
+ NtClose_t pNtClose = reinterpret_cast<NtClose_t>(dll_func::get(dll_func::NtClose));
const wchar_t empty_str [] = L"";
unicode_string_t ustring = { sizeof(empty_str) - sizeof (wchar_t) //length in bytes without null
, sizeof(empty_str) //total size in bytes of memory allocated for Buffer.
@@ -1984,9 +1418,9 @@ inline bool unlink_file(const char *filename)
return true;
}
}
- catch(...){
+ BOOST_CATCH(...){
return false;
- }
+ } BOOST_CATCH_END
return true;
}
@@ -1997,7 +1431,8 @@ struct reg_closer
~reg_closer(){ reg_close_key(key_); }
};
-inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, const char *value_name, void *buf, std::size_t &buflen)
+template <class CharT>
+inline bool get_registry_value_buffer(hkey key_type, const CharT *subkey_name, const CharT *value_name, void *buf, std::size_t &buflen)
{
bool bret = false;
hkey key;
@@ -2019,7 +1454,8 @@ inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, co
return bret;
}
-inline bool get_registry_value_string(hkey key_type, const char *subkey_name, const char *value_name, std::string &s)
+template<class CharT>
+inline bool get_registry_value_string(hkey key_type, const CharT *subkey_name, const CharT *value_name, std::basic_string<CharT> &s)
{
bool bret = false;
s.clear();
@@ -2037,7 +1473,7 @@ inline bool get_registry_value_string(hkey key_type, const char *subkey_name, co
long err = reg_query_value_ex( key, value_name, 0, &type, 0, &size);
if((reg_sz == type || reg_expand_sz == type) && !err){
//Size includes terminating NULL
- s.resize(size);
+ s.resize(size/sizeof(CharT));
err = reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)(&s[0]), &size);
if(!err){
s.erase(s.end()-1);
@@ -2049,28 +1485,25 @@ inline bool get_registry_value_string(hkey key_type, const char *subkey_name, co
return bret;
}
-inline void get_shared_documents_folder(std::string &s)
+template<class CharT>
+inline void get_shared_documents_folder(std::basic_string<CharT> &s)
{
- #if 1 //Original registry search code
get_registry_value_string( hkey_local_machine
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
, "Common AppData"
, s);
- #else //registry alternative: SHGetFolderPath
- const int BIPC_CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data
- const int BIPC_CSIDL_FLAG_CREATE = 0x8000; // new for Win2K, or this in to force creation of folder
- const int BIPC_SHGFP_TYPE_CURRENT = 0; // current value for user, verify it exists
-
- s.clear();
- char szPath[max_path];
- if(0 == SHGetFolderPathA(0, BIPC_CSIDL_COMMON_APPDATA | BIPC_CSIDL_FLAG_CREATE, 0, BIPC_SHGFP_TYPE_CURRENT, szPath)){
- s = szPath;
- }
+}
- #endif
+inline void get_shared_documents_folder(std::wstring &s)
+{
+ get_registry_value_string( hkey_local_machine
+ , L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ , L"Common AppData"
+ , s);
}
-inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s)
+template<class CharT>
+inline void get_registry_value(const CharT *folder, const CharT *value_key, std::vector<unsigned char> &s)
{
s.clear();
hkey key;
@@ -2099,191 +1532,201 @@ inline void get_registry_value(const char *folder, const char *value_key, std::v
}
}
-#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME)
+inline bool is_directory(const char *path)
+{
+ unsigned long attrib = GetFileAttributesA(path);
-struct co_uninitializer
+ return (attrib != invalid_file_attributes &&
+ (attrib & file_attribute_directory));
+}
+
+inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
{
- co_uninitializer(bool b_uninitialize)
- : m_b_uninitialize(b_uninitialize)
- {}
+ NtQuerySection_t pNtQuerySection =
+ reinterpret_cast<NtQuerySection_t>(dll_func::get(dll_func::NtQuerySection));
+ //Obtain file name
+ interprocess_section_basic_information info;
+ long ntstatus =
+ pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0);
+ size = info.section_size;
+ return !ntstatus;
+}
- ~co_uninitializer()
- {
- if(m_b_uninitialize){
- CoUninitialize();
- }
- }
+inline bool get_semaphore_info(void *handle, long &count, long &limit)
+{
+ winapi::interprocess_semaphore_basic_information info;
+ winapi::NtQuerySemaphore_t pNtQuerySemaphore =
+ reinterpret_cast<winapi::NtQuerySemaphore_t>(dll_func::get(winapi::dll_func::NtQuerySemaphore));
+ unsigned int ret_len;
+ long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
+ count = (long)info.count;
+ limit = (long)info.limit;
+ return !status;
+}
- private:
- const bool m_b_uninitialize;
-};
+inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres)
+{
+ winapi::NtQueryTimerResolution_t pNtQueryTimerResolution =
+ reinterpret_cast<winapi::NtQueryTimerResolution_t>(dll_func::get(winapi::dll_func::NtQueryTimerResolution));
+ return !pNtQueryTimerResolution(lowres, highres, curres);
+}
-template<class Object>
-struct com_releaser
+inline bool query_performance_counter(__int64 *lpPerformanceCount)
{
- Object *&object_;
- com_releaser(Object *&object) : object_(object) {}
- ~com_releaser() { object_->Release(); object_ = 0; }
-};
+ return 0 != boost::winapi::QueryPerformanceCounter(reinterpret_cast<boost::winapi::LARGE_INTEGER_*>(lpPerformanceCount));
+}
-inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var)
+inline bool query_performance_frequency(__int64 *lpFrequency)
{
- //See example http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx
- //
- //See BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL definition if you need to change the
- //default value of this macro in your application
- long co_init_ret = CoInitializeEx(0, BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL);
- if(co_init_ret != S_OK_BIPC && co_init_ret != S_FALSE_BIPC && co_init_ret != RPC_E_CHANGED_MODE_BIPC)
- return false;
- co_uninitializer co_initialize_end(co_init_ret != RPC_E_CHANGED_MODE_BIPC);
- (void)co_initialize_end;
-
- bool bRet = false;
- long sec_init_ret = CoInitializeSecurity
- ( 0 //pVoid
- ,-1 //cAuthSvc
- , 0 //asAuthSvc
- , 0 //pReserved1
- , RPC_C_AUTHN_LEVEL_PKT_BIPC //dwAuthnLevel
- , RPC_C_IMP_LEVEL_IMPERSONATE_BIPC //dwImpLevel
- , 0 //pAuthList
- , EOAC_NONE_BIPC //dwCapabilities
- , 0 //pReserved3
- );
- if( 0 == sec_init_ret || RPC_E_TOO_LATE_BIPC == sec_init_ret)
- {
- IWbemLocator_BIPC * pIWbemLocator = 0;
- const wchar_t * bstrNamespace = L"root\\cimv2";
-
- if( 0 != CoCreateInstance(
- CLSID_WbemAdministrativeLocator,
- 0,
- CLSCTX_INPROC_SERVER_BIPC | CLSCTX_LOCAL_SERVER_BIPC,
- IID_IUnknown, (void **)&pIWbemLocator)){
- return false;
- }
+ return 0 != boost::winapi::QueryPerformanceFrequency(reinterpret_cast<boost::winapi::LARGE_INTEGER_*>(lpFrequency));
+}
- com_releaser<IWbemLocator_BIPC> IWbemLocator_releaser(pIWbemLocator);
-
- IWbemServices_BIPC *pWbemServices = 0;
-
- if( 0 != pIWbemLocator->ConnectServer(
- (bstr)bstrNamespace, // Namespace
- 0, // Userid
- 0, // PW
- 0, // Locale
- 0, // flags
- 0, // Authority
- 0, // Context
- &pWbemServices
- )
- ){
- return false;
- }
+inline unsigned long get_tick_count()
+{ return GetTickCount(); }
- if( S_OK_BIPC != CoSetProxyBlanket(
- pWbemServices,
- RPC_C_AUTHN_DEFAULT_BIPC,
- RPC_C_AUTHZ_DEFAULT_BIPC,
- 0,
- RPC_C_AUTHN_LEVEL_PKT_BIPC,
- RPC_C_IMP_LEVEL_IMPERSONATE_BIPC,
- 0,
- EOAC_NONE_BIPC
- )
- ){
- return false;
- }
- com_releaser<IWbemServices_BIPC> IWbemServices_releaser(pWbemServices);
-
- strValue.clear();
- strValue += L"Select ";
- strValue += wmi_class_var;
- strValue += L" from ";
- strValue += wmi_class;
-
- IEnumWbemClassObject_BIPC * pEnumObject = 0;
-
- if ( 0 != pWbemServices->ExecQuery(
- (bstr)L"WQL",
- (bstr)strValue.c_str(),
- //WBEM_FLAG_RETURN_IMMEDIATELY_BIPC,
- WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC | WBEM_FLAG_FORWARD_ONLY_BIPC,
- 0,
- &pEnumObject
- )
- ){
- return false;
- }
+template<class CharT>
+struct winapi_traits;
- com_releaser<IEnumWbemClassObject_BIPC> IEnumWbemClassObject_releaser(pEnumObject);
+template<>
+struct winapi_traits<char>
+{
+ static int cmp(const char *a, const char *b)
+ { return std::strcmp(a, b); }
+};
+
+template<>
+struct winapi_traits<wchar_t>
+{
+ static int cmp(const wchar_t *a, const wchar_t *b)
+ { return std::wcscmp(a, b); }
+};
+
+
+#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED)
- //WBEM_FLAG_FORWARD_ONLY_BIPC incompatible with Reset
- //if ( 0 != pEnumObject->Reset() ){
- //return false;
- //}
- wchar_variant vwchar;
- unsigned long uCount = 1, uReturned;
- IWbemClassObject_BIPC * pClassObject = 0;
- while( 0 == pEnumObject->Next( WBEM_INFINITE_BIPC, uCount, &pClassObject, &uReturned ) )
+inline bool get_last_bootup_time(std::string &stamp)
+{
+ unsigned dword_val = 0;
+ std::size_t dword_size = sizeof(dword_val);
+ bool b_ret = get_registry_value_buffer( hkey_local_machine
+ , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
+ , "BootId", &dword_val, dword_size);
+ if (b_ret)
+ {
+ char dword_str[sizeof(dword_val)*2u+1];
+ buffer_to_narrow_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = '\0';
+ stamp = dword_str;
+
+ b_ret = get_registry_value_buffer( hkey_local_machine
+ , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power"
+ , "HybridBootAnimationTime", &dword_val, dword_size);
+ //Old Windows versions have no HybridBootAnimationTime
+ if(b_ret)
{
- com_releaser<IWbemClassObject_BIPC> IWbemClassObject_releaser(pClassObject);
- if ( 0 == pClassObject->Get( (bstr)L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){
- bRet = true;
- strValue = (wchar_t*)vwchar.bstrVal;
- VariantClear(&vwchar );
- break;
- }
+ buffer_to_narrow_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = '\0';
+ stamp += "_";
+ stamp += dword_str;
}
+ b_ret = true;
}
- return bRet;
+ return b_ret;
}
-//Obtains the bootup time from WMI LastBootUpTime.
-//This time seems to change with hibernation and clock synchronization so avoid it.
-inline bool get_last_bootup_time( std::wstring& strValue )
+inline bool get_last_bootup_time(std::wstring &stamp)
{
- bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime");
- std::size_t timezone = strValue.find(L'+');
- if(timezone != std::wstring::npos){
- strValue.erase(timezone);
- }
- timezone = strValue.find(L'-');
- if(timezone != std::wstring::npos){
- strValue.erase(timezone);
- }
- return ret;
-}
+ unsigned dword_val = 0;
+ std::size_t dword_size = sizeof(dword_val);
+ bool b_ret = get_registry_value_buffer( hkey_local_machine
+ , L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
+ , L"BootId", &dword_val, dword_size);
+ if (b_ret)
+ {
+ wchar_t dword_str[sizeof(dword_val)*2u+1];
+ buffer_to_wide_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = L'\0';
+ stamp = dword_str;
-inline bool get_last_bootup_time( std::string& str )
-{
- std::wstring wstr;
- bool ret = get_last_bootup_time(wstr);
- str.resize(wstr.size());
- for(std::size_t i = 0, max = str.size(); i != max; ++i){
- str[i] = '0' + (wstr[i]-L'0');
+ b_ret = get_registry_value_buffer( hkey_local_machine
+ , L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power"
+ , L"HybridBootAnimationTime", &dword_val, dword_size);
+ //Old Windows versions have no HybridBootAnimationTime
+ if(b_ret)
+ {
+ buffer_to_wide_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = L'\0';
+ stamp += L"_";
+ stamp += dword_str;
+ }
+ b_ret = true;
}
- return ret;
+ return b_ret;
}
-#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
+#elif defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED)
-#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED)
+static const unsigned long eventlog_sequential_read = 0x0001;
+static const unsigned long eventlog_backwards_read = 0x0008;
+
+struct interprocess_eventlogrecord
+{
+ unsigned long Length; // Length of full record
+ unsigned long Reserved; // Used by the service
+ unsigned long RecordNumber; // Absolute record number
+ unsigned long TimeGenerated; // Seconds since 1-1-1970
+ unsigned long TimeWritten; // Seconds since 1-1-1970
+ unsigned long EventID;
+ unsigned short EventType;
+ unsigned short NumStrings;
+ unsigned short EventCategory;
+ unsigned short ReservedFlags; // For use with paired events (auditing)
+ unsigned long ClosingRecordNumber; // For use with paired events (auditing)
+ unsigned long StringOffset; // Offset from beginning of record
+ unsigned long UserSidLength;
+ unsigned long UserSidOffset;
+ unsigned long DataLength;
+ unsigned long DataOffset; // Offset from beginning of record
+ //
+ // Then follow:
+ //
+ // wchar_t SourceName[]
+ // wchar_t Computername[]
+ // SID UserSid
+ // wchar_t Strings[]
+ // BYTE Data[]
+ // CHAR Pad[]
+ // unsigned long Length;
+ //
+};
+
+class eventlog_handle_closer
+{
+ void *handle_;
+ eventlog_handle_closer(const handle_closer &);
+ eventlog_handle_closer& operator=(const eventlog_handle_closer &);
+ public:
+ explicit eventlog_handle_closer(void *handle) : handle_(handle){}
+ ~eventlog_handle_closer()
+ { CloseEventLog(handle_); }
+};
// Loop through the buffer and obtain the contents of the
// requested record in the buffer.
-inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const char *provider_name
+template<class CharT>
+inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const CharT *provider_name
, unsigned int id_to_find, interprocess_eventlogrecord *&pevent_log_record)
{
const unsigned char * pRecord = static_cast<const unsigned char*>(pBuffer);
const unsigned char * pEndOfRecords = pRecord + dwBytesRead;
while (pRecord < pEndOfRecords){
- interprocess_eventlogrecord *pTypedRecord = (interprocess_eventlogrecord*)pRecord;
+ interprocess_eventlogrecord *pTypedRecord = (interprocess_eventlogrecord*)(void*)pRecord;
// Check provider, written at the end of the fixed-part of the record
- if (0 == std::strcmp(provider_name, (char*)(pRecord + sizeof(interprocess_eventlogrecord))))
+
+ if (0 == winapi_traits<CharT>::cmp(provider_name, (CharT*)(void*)(pRecord + sizeof(interprocess_eventlogrecord))))
{
// Check event id
if(id_to_find == (pTypedRecord->EventID & 0xFFFF)){
@@ -2366,104 +1809,74 @@ inline bool get_last_bootup_time(std::string &stamp)
return true;
}
-#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
-
-#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED)
-
-inline bool get_last_bootup_time(std::string &stamp)
-{
- unsigned dword_val = 0;
- std::size_t dword_size = sizeof(dword_val);
- bool b_ret = get_registry_value_buffer( hkey_local_machine
- , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
- , "BootId", &dword_val, dword_size);
- if (b_ret)
- {
- char dword_str[sizeof(dword_val)*2u+1];
- buffer_to_narrow_str(&dword_val, dword_size, dword_str);
- dword_str[sizeof(dword_val)*2] = '\0';
- stamp = dword_str;
-
- b_ret = get_registry_value_buffer( hkey_local_machine
- , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power"
- , "HybridBootAnimationTime", &dword_val, dword_size);
- //Old Windows versions have no HybridBootAnimationTime
- if(b_ret)
- {
- buffer_to_narrow_str(&dword_val, dword_size, dword_str);
- dword_str[sizeof(dword_val)*2] = '\0';
- stamp += "_";
- stamp += dword_str;
- }
- b_ret = true;
- }
- return b_ret;
-}
-
-#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
-
-inline bool is_directory(const char *path)
-{
- unsigned long attrib = GetFileAttributesA(path);
-
- return (attrib != invalid_file_attributes &&
- (attrib & file_attribute_directory));
-}
-
-inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
-{
- NtQuerySection_t pNtQuerySection =
- (NtQuerySection_t)dll_func::get(dll_func::NtQuerySection);
- //Obtain file name
- interprocess_section_basic_information info;
- unsigned long ntstatus =
- pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0);
- size = info.section_size;
- return !ntstatus;
-}
-inline bool get_semaphore_info(void *handle, long &count, long &limit)
+inline bool get_last_bootup_time(std::wstring &stamp)
{
- winapi::interprocess_semaphore_basic_information info;
- winapi::NtQuerySemaphore_t pNtQuerySemaphore =
- (winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore);
- unsigned int ret_len;
- long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
- count = info.count;
- limit = info.limit;
- return !status;
-}
+ const wchar_t *source_name = L"System";
+ const wchar_t *provider_name = L"EventLog";
+ const unsigned short event_id = 6005u;
-inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres)
-{
- winapi::NtQueryTimerResolution_t pNtQueryTimerResolution =
- (winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution);
- return !pNtQueryTimerResolution(lowres, highres, curres);
-}
+ unsigned long status = 0;
+ unsigned long dwBytesToRead = 0;
+ unsigned long dwBytesRead = 0;
+ unsigned long dwMinimumBytesToRead = 0;
-inline bool set_timer_resolution(unsigned long RequestedResolution, int Set, unsigned long* ActualResolution)
-{
- winapi::NtSetTimerResolution_t pNtSetTimerResolution =
- (winapi::NtSetTimerResolution_t)dll_func::get(winapi::dll_func::NtSetTimerResolution);
- return !pNtSetTimerResolution(RequestedResolution, Set, ActualResolution);
-}
+ // The source name (provider) must exist as a subkey of Application.
+ void *hEventLog = OpenEventLogW(0, source_name);
+ if (hEventLog){
+ eventlog_handle_closer hnd_closer(hEventLog); (void)hnd_closer;
+ // Allocate an initial block of memory used to read event records. The number
+ // of records read into the buffer will vary depending on the size of each event.
+ // The size of each event will vary based on the size of the user-defined
+ // data included with each event, the number and length of insertion
+ // strings, and other data appended to the end of the event record.
+ dwBytesToRead = max_record_buffer_size;
+ c_heap_deleter heap_deleter(dwBytesToRead);
-inline bool query_performance_counter(__int64 *lpPerformanceCount)
-{
- QueryPerformanceCounter_t pQueryPerformanceCounter = (QueryPerformanceCounter_t)
- dll_func::get(dll_func::QueryPerformanceCounter);
- return 0 != pQueryPerformanceCounter(lpPerformanceCount);
+ // Read blocks of records until you reach the end of the log or an
+ // error occurs. The records are read from newest to oldest. If the buffer
+ // is not big enough to hold a complete event record, reallocate the buffer.
+ if (heap_deleter.get() != 0){
+ while (0 == status){
+ if (!ReadEventLogW(hEventLog,
+ eventlog_sequential_read | eventlog_backwards_read,
+ 0,
+ heap_deleter.get(),
+ dwBytesToRead,
+ &dwBytesRead,
+ &dwMinimumBytesToRead)) {
+ status = get_last_error();
+ if (error_insufficient_buffer == status) {
+ status = 0;
+ dwBytesToRead = dwMinimumBytesToRead;
+ heap_deleter.realloc_mem(dwMinimumBytesToRead);
+ if (!heap_deleter.get()){
+ return false;
+ }
+ }
+ else{ //Not found or EOF
+ return false;
+ }
+ }
+ else
+ {
+ interprocess_eventlogrecord *pTypedRecord;
+ // Print the contents of each record in the buffer.
+ if(find_record_in_buffer(heap_deleter.get(), dwBytesRead, provider_name, event_id, pTypedRecord)){
+ wchar_t stamp_str[sizeof(unsigned long)*3+1];
+ std::swprintf(&stamp_str[0], L"%u", ((unsigned int)pTypedRecord->TimeGenerated));
+ stamp = stamp_str;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return true;
}
-inline bool query_performance_frequency(__int64 *lpFrequency)
-{
- QueryPerformanceCounter_t pQueryPerformanceFrequency = (QueryPerformanceFrequency_t)
- dll_func::get(dll_func::QueryPerformanceFrequency);
- return 0 != pQueryPerformanceFrequency(lpFrequency);
-}
+#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
-inline unsigned long get_tick_count()
-{ return GetTickCount(); }
} //namespace winapi
} //namespace interprocess
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/windows_intermodule_singleton.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/windows_intermodule_singleton.hpp
index 12ad2015e3..67ce199b85 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/windows_intermodule_singleton.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/windows_intermodule_singleton.hpp
@@ -138,7 +138,7 @@ class windows_semaphore_based_map
name = "bipc_gmap_sem_map_";
name += pid_creation_time;
success = success && m_sem_map.open_or_create
- (name.c_str(), initial_count, max_count, perm, created);
+ (name.c_str(), (long)initial_count, (long)max_count, perm, created);
if(!success){
delete m;
//winapi_xxx wrappers do the cleanup...
@@ -163,8 +163,8 @@ class windows_semaphore_based_map
boost::uint32_t addr_uint32;
} caster;
caster.addr = 0;
- caster.addr_uint32 = m_sem_map.limit();
- caster.addr_uint32 = caster.addr_uint32 << 2;
+ caster.addr_uint32 = boost::uint32_t(m_sem_map.limit());
+ caster.addr_uint32 = caster.addr_uint32 << 2u;
return *static_cast<map_type*>(caster.addr);
}
else{
@@ -173,11 +173,12 @@ class windows_semaphore_based_map
void *addr;
boost::uint64_t addr_uint64;
} caster;
- boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value());
+ boost::uint32_t max_count(boost::uint32_t(m_sem_map.limit()))
+ , initial_count(boost::uint32_t(m_sem_map.value()));
//Clear quasi-top bit
max_count &= boost::uint32_t(0xBFFFFFFF);
caster.addr_uint64 = max_count;
- caster.addr_uint64 = caster.addr_uint64 << 32;
+ caster.addr_uint64 = caster.addr_uint64 << 32u;
caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
return *static_cast<map_type*>(caster.addr);
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/workaround.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/workaround.hpp
index 53cd3eb2c4..01b6c6eb05 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/workaround.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/detail/workaround.hpp
@@ -19,12 +19,18 @@
# pragma once
#endif
+#if defined(BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION) && defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+#error "BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION && BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION can't be defined at the same time"
+#endif
+
+//#define BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION
+
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define BOOST_INTERPROCESS_WINDOWS
- #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
+ #if !defined(BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+ #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
+ #endif
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
- //Define this to connect with shared memory created with versions < 1.54
- //#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
#else
#include <unistd.h>
@@ -49,17 +55,12 @@
//Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
#if defined(__CYGWIN__)
#define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
- //Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support.
#elif defined(__APPLE__)
- #include "TargetConditionals.h"
- //Check we're on Mac OS target
- #if defined(TARGET_OS_MAC)
- #include "AvailabilityMacros.h"
- //If minimum target for this compilation is older than Mac Os Lion, then we are out of luck
- #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
- #endif
- #endif
+ //The pthreads implementation of darwin stores a pointer to a mutex inside the condition
+ //structure so real sharing between processes is broken. See:
+ //https://opensource.apple.com/source/libpthread/libpthread-301.30.1/src/pthread_cond.c.auto.html
+ //in method pthread_cond_wait
+ #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
#endif
//If buggy _POSIX_THREAD_PROCESS_SHARED is detected avoid using it
@@ -71,6 +72,13 @@
#endif
//////////////////////////////////////////////////////
+ // BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ //////////////////////////////////////////////////////
+ #if (_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L)
+ #define BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ #endif
+
+ //////////////////////////////////////////////////////
// _POSIX_SHARED_MEMORY_OBJECTS (POSIX.1b/POSIX.4)
//////////////////////////////////////////////////////
#if ( defined(_POSIX_SHARED_MEMORY_OBJECTS) && ((_POSIX_SHARED_MEMORY_OBJECTS + 0) > 0) ) ||\
@@ -154,6 +162,14 @@
(defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
#define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
#endif
+
+ //////////////////////////////////////////////////////
+ //posix_fallocate
+ //////////////////////////////////////////////////////
+ #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+ #define BOOST_INTERPROCESS_POSIX_FALLOCATE
+ #endif
+
#endif //!defined(BOOST_INTERPROCESS_WINDOWS)
#if defined(BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_POSIX_MAPPED_FILES)
@@ -175,6 +191,18 @@
#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
#endif
+
+// Max open or create tries with managed memory segments
+#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES
+ #define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES 20u
+#endif
+
+// Maximum timeout in seconds with open or create tries with managed memory segments
+// waiting the creator to initialize the shared memory
+#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC
+ #define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC 300u
+#endif
+
//Other switches
//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX
//message queue uses a circular queue as index instead of an array (better performance)
@@ -195,14 +223,40 @@
#define BOOST_INTERPROCESS_FORCEINLINE inline
#elif defined(BOOST_INTERPROCESS_FORCEINLINE_IS_BOOST_FORCELINE)
#define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
-#elif defined(BOOST_MSVC) && defined(_DEBUG)
- //"__forceinline" and MSVC seems to have some bugs in debug mode
+#elif defined(BOOST_MSVC) && (_MSC_VER < 1900 || defined(_DEBUG))
+ //"__forceinline" and MSVC seems to have some bugs in old versions and in debug mode
#define BOOST_INTERPROCESS_FORCEINLINE inline
-#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
+#elif defined(BOOST_GCC) && (__GNUC__ <= 5)
//Older GCCs have problems with forceinline
#define BOOST_INTERPROCESS_FORCEINLINE inline
#else
#define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
#endif
+#ifdef BOOST_WINDOWS
+
+#define BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES
+
+#ifdef __clang__
+ #define BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+ #define BOOST_INTERPROCESS_RESTORE_WARNING _Pragma("clang diagnostic pop")
+#else // __clang__
+ #define BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING __pragma(warning(push)) \
+ __pragma(warning(disable : 4996))
+ #define BOOST_INTERPROCESS_RESTORE_WARNING __pragma(warning(pop))
+#endif // __clang__
+
+#endif
+
+#if defined(BOOST_HAS_THREADS)
+# if defined(_MSC_VER) || defined(__MWERKS__) || defined(__MINGW32__) || defined(__BORLANDC__)
+ //no reentrant posix functions (eg: localtime_r)
+# elif (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT)))
+# define BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS
+# endif
+#endif
+
+#include <boost/core/no_exceptions_support.hpp>
+
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/errors.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/errors.hpp
index 46dc417a59..95bca55a17 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/errors.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/errors.hpp
@@ -34,14 +34,13 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <stdarg.h>
#include <string>
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
-# include <errno.h> //Errors
+# include <cerrno> //Errors
# include <cstring> //strerror
# else //ifdef BOOST_HAS_UNISTD_H
# error Unknown platform
@@ -57,7 +56,7 @@ namespace interprocess {
inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
- return winapi::get_last_error();
+ return (int)winapi::get_last_error();
#else
return errno; // GCC 3.1 won't accept ::errno
#endif
@@ -68,22 +67,27 @@ inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
inline void fill_system_message(int sys_err_code, std::string &str)
{
void *lpMsgBuf;
- winapi::format_message(
+ unsigned long ret = winapi::format_message(
winapi::format_message_allocate_buffer |
winapi::format_message_from_system |
winapi::format_message_ignore_inserts,
0,
- sys_err_code,
+ (unsigned long)sys_err_code,
winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
reinterpret_cast<char *>(&lpMsgBuf),
0,
0
);
- str += static_cast<const char*>(lpMsgBuf);
- winapi::local_free( lpMsgBuf ); // free the buffer
- while ( str.size()
- && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
- str.erase( str.size()-1 );
+ if (ret != 0){
+ str += static_cast<const char*>(lpMsgBuf);
+ winapi::local_free( lpMsgBuf ); // free the buffer
+ while ( str.size()
+ && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
+ str.erase( str.size()-1 );
+ }
+ else{
+ str += "WinApi FormatMessage returned error";
+ }
}
# else
inline void fill_system_message( int system_error, std::string &str)
@@ -119,7 +123,8 @@ enum error_code_t
invalid_argument,
timeout_when_locking_error,
timeout_when_waiting_error,
- owner_dead_error
+ owner_dead_error,
+ not_recoverable
};
typedef int native_error_t;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/exceptions.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/exceptions.hpp
index eb4ddf2d67..3eeb9f6e0b 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/exceptions.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/exceptions.hpp
@@ -36,17 +36,17 @@ namespace interprocess {
class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
{
public:
- interprocess_exception(const char *err)
+ interprocess_exception(const char *err) BOOST_NOEXCEPT
: m_err(other_error)
{
- try { m_str = err; }
- catch (...) {}
+ BOOST_TRY { m_str = err; }
+ BOOST_CATCH(...) {} BOOST_CATCH_END
}
interprocess_exception(const error_info &err_info, const char *str = 0)
: m_err(err_info)
{
- try{
+ BOOST_TRY{
if(m_err.get_native_error() != 0){
fill_system_message(m_err.get_native_error(), m_str);
}
@@ -57,18 +57,18 @@ class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
m_str = "boost::interprocess_exception::library_error";
}
}
- catch(...){}
+ BOOST_CATCH(...){} BOOST_CATCH_END
}
- virtual ~interprocess_exception(){}
+ ~interprocess_exception() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE {}
- virtual const char * what() const noexcept
+ const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return m_str.c_str(); }
- native_error_t get_native_error()const { return m_err.get_native_error(); }
+ native_error_t get_native_error() const BOOST_NOEXCEPT { return m_err.get_native_error(); }
// Note: a value of other_error implies a library (rather than system) error
- error_code_t get_error_code() const { return m_err.get_error_code(); }
+ error_code_t get_error_code() const BOOST_NOEXCEPT { return m_err.get_error_code(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -82,11 +82,11 @@ class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
class BOOST_SYMBOL_VISIBLE lock_exception : public interprocess_exception
{
public:
- lock_exception()
- : interprocess_exception(lock_error)
+ lock_exception(error_code_t err = lock_error) BOOST_NOEXCEPT
+ : interprocess_exception(err)
{}
- virtual const char* what() const noexcept
+ const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return "boost::interprocess::lock_exception"; }
};
@@ -96,9 +96,10 @@ class BOOST_SYMBOL_VISIBLE lock_exception : public interprocess_exception
class BOOST_SYMBOL_VISIBLE bad_alloc : public interprocess_exception
{
public:
- bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc"){}
- virtual const char* what() const noexcept
- { return "boost::interprocess::bad_alloc"; }
+ bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc") {}
+
+ const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
+ { return "boost::interprocess::bad_alloc"; }
};
} // namespace interprocess {
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/mapped_region.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/mapped_region.hpp
index 1fb64086b5..1ef284522f 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/mapped_region.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/mapped_region.hpp
@@ -47,7 +47,6 @@
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
-# include <boost/interprocess/sync/windows/sync_utils.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
# include <fcntl.h>
@@ -136,11 +135,11 @@ class mapped_region
//!Default constructor. Address will be 0 (nullptr).
//!Size will be 0.
//!Does not throw
- mapped_region();
+ mapped_region() BOOST_NOEXCEPT;
//!Move constructor. *this will be constructed taking ownership of "other"'s
//!region and "other" will be left in default constructor state.
- mapped_region(BOOST_RV_REF(mapped_region) other)
+ mapped_region(BOOST_RV_REF(mapped_region) other) BOOST_NOEXCEPT
#if defined (BOOST_INTERPROCESS_WINDOWS)
: m_base(0), m_size(0)
, m_page_offset(0)
@@ -157,7 +156,7 @@ class mapped_region
//!Move assignment. If *this owns a memory mapped region, it will be
//!destroyed and it will take ownership of "other"'s memory mapped region.
- mapped_region &operator=(BOOST_RV_REF(mapped_region) other)
+ mapped_region &operator=(BOOST_RV_REF(mapped_region) other) BOOST_NOEXCEPT
{
mapped_region tmp(boost::move(other));
this->swap(tmp);
@@ -166,18 +165,18 @@ class mapped_region
//!Swaps the mapped_region with another
//!mapped region
- void swap(mapped_region &other);
+ void swap(mapped_region &other) BOOST_NOEXCEPT;
//!Returns the size of the mapping. Never throws.
- std::size_t get_size() const;
+ std::size_t get_size() const BOOST_NOEXCEPT;
//!Returns the base address of the mapping.
//!Never throws.
- void* get_address() const;
+ void* get_address() const BOOST_NOEXCEPT;
//!Returns the mode of the mapping used to construct the mapped region.
//!Never throws.
- mode_t get_mode() const;
+ mode_t get_mode() const BOOST_NOEXCEPT;
//!Flushes to the disk a byte range within the mapped memory.
//!If 'async' is true, the function will return before flushing operation is completed
@@ -190,7 +189,7 @@ class mapped_region
//!mapped memory page, accessing that page can trigger a segmentation fault.
//!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage
//!and free a portion of the virtual address space (e.g.POSIX) or this
- //!function can release some physical memory wihout freeing any virtual address space(Windows).
+ //!function can release some physical memory without freeing any virtual address space(Windows).
//!Returns true on success. Never throws.
bool shrink_by(std::size_t bytes, bool from_back = true);
@@ -225,7 +224,7 @@ class mapped_region
//!Returns the size of the page. This size is the minimum memory that
//!will be used by the system when mapping a memory mappable source and
//!will restrict the address and the offset to map.
- static std::size_t get_page_size();
+ static std::size_t get_page_size() BOOST_NOEXCEPT;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -269,19 +268,19 @@ class mapped_region
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-inline void swap(mapped_region &x, mapped_region &y)
+inline void swap(mapped_region &x, mapped_region &y) BOOST_NOEXCEPT
{ x.swap(y); }
inline mapped_region::~mapped_region()
{ this->priv_close(); }
-inline std::size_t mapped_region::get_size() const
+inline std::size_t mapped_region::get_size() const BOOST_NOEXCEPT
{ return m_size; }
-inline mode_t mapped_region::get_mode() const
+inline mode_t mapped_region::get_mode() const BOOST_NOEXCEPT
{ return m_mode; }
-inline void* mapped_region::get_address() const
+inline void* mapped_region::get_address() const BOOST_NOEXCEPT
{ return m_base; }
inline void* mapped_region::priv_map_address() const
@@ -297,7 +296,7 @@ inline bool mapped_region::priv_flush_param_check
if(m_base == 0)
return false;
- if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
+ if(mapping_offset >= m_size || numbytes > (m_size - size_t(mapping_offset))){
return false;
}
@@ -346,14 +345,14 @@ inline void mapped_region::priv_size_from_mapping_size
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
{
//Check if mapping size fits in the user address space
- //as offset_t is the maximum file size and its signed.
+ //as offset_t is the maximum file size and it's signed.
if(mapping_size < offset ||
boost::uintmax_t(mapping_size - (offset - page_offset)) >
boost::uintmax_t(std::size_t(-1))){
error_info err(size_error);
throw interprocess_exception(err);
}
- size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
+ size = static_cast<std::size_t>(mapping_size - offset);
}
inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
@@ -365,17 +364,17 @@ inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, cons
//We calculate the difference between demanded and valid offset
//(always less than a page in std::size_t, thus, representable by std::size_t)
const std::size_t page_offset =
- static_cast<std::size_t>(offset - (offset / page_size) * page_size);
+ static_cast<std::size_t>(offset - (offset / offset_t(page_size)) * offset_t(page_size));
//Update the mapping address
if(address){
address = static_cast<const char*>(address) - page_offset;
}
- return page_offset;
+ return offset_t(page_offset);
}
#if defined (BOOST_INTERPROCESS_WINDOWS)
-inline mapped_region::mapped_region()
+inline mapped_region::mapped_region() BOOST_NOEXCEPT
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only)
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
{}
@@ -383,7 +382,7 @@ inline mapped_region::mapped_region()
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
{
- winapi::system_info info;
+ winapi::interprocess_system_info info;
winapi::get_system_info(&info);
return std::size_t(info.dwAllocationGranularity);
}
@@ -442,11 +441,11 @@ inline mapped_region::mapped_region
//Create mapping handle
native_mapping_handle = winapi::create_file_mapping
( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle())
- , protection, 0, 0, 0);
+ , protection, 0, (char*)0, 0);
//Check if all is correct
if(!native_mapping_handle){
- error_info err = winapi::get_last_error();
+ error_info err ((int)winapi::get_last_error());
throw interprocess_exception(err);
}
handle_to_close = native_mapping_handle;
@@ -466,7 +465,7 @@ inline mapped_region::mapped_region
if(size == 0){
offset_t mapping_size;
if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){
- error_info err = winapi::get_last_error();
+ error_info err((int)winapi::get_last_error());
throw interprocess_exception(err);
}
//This can throw
@@ -477,18 +476,18 @@ inline mapped_region::mapped_region
void *base = winapi::map_view_of_file_ex
(native_mapping_handle,
map_access,
- offset - page_offset,
+ ::boost::ulong_long_type(offset - page_offset),
static_cast<std::size_t>(page_offset + size),
const_cast<void*>(address));
//Check error
if(!base){
- error_info err = winapi::get_last_error();
+ error_info err((int)winapi::get_last_error());
throw interprocess_exception(err);
}
//Calculate new base for the user
m_base = static_cast<char*>(base) + page_offset;
- m_page_offset = page_offset;
+ m_page_offset = static_cast<std::size_t>(page_offset);
m_size = size;
}
//Windows shared memory needs the duplication of the handle if we want to
@@ -496,7 +495,7 @@ inline mapped_region::mapped_region
//
//For mapped files, we duplicate the file handle to be able to FlushFileBuffers
if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){
- error_info err = winapi::get_last_error();
+ error_info err((int)winapi::get_last_error());
this->priv_close();
throw interprocess_exception(err);
}
@@ -573,7 +572,7 @@ inline void mapped_region::dont_close_on_destruction()
#else //#if defined (BOOST_INTERPROCESS_WINDOWS)
-inline mapped_region::mapped_region()
+inline mapped_region::mapped_region() BOOST_NOEXCEPT
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
{}
@@ -696,7 +695,7 @@ inline mapped_region::mapped_region
//Map it to the address space
void* base = mmap ( const_cast<void*>(address)
- , static_cast<std::size_t>(page_offset + size)
+ , static_cast<std::size_t>(page_offset) + size
, prot
, flags
, mapping.get_mapping_handle().handle
@@ -710,7 +709,7 @@ inline mapped_region::mapped_region
//Calculate new base for the user
m_base = static_cast<char*>(base) + page_offset;
- m_page_offset = page_offset;
+ m_page_offset = static_cast<std::size_t>(page_offset);
m_size = size;
//Check for fixed mapping error
@@ -852,7 +851,7 @@ template<int dummy>
const std::size_t mapped_region::page_size_holder<dummy>::PageSize
= mapped_region::page_size_holder<dummy>::get_page_size();
-inline std::size_t mapped_region::get_page_size()
+inline std::size_t mapped_region::get_page_size() BOOST_NOEXCEPT
{
if(!page_size_holder<0>::PageSize)
return page_size_holder<0>::get_page_size();
@@ -860,7 +859,7 @@ inline std::size_t mapped_region::get_page_size()
return page_size_holder<0>::PageSize;
}
-inline void mapped_region::swap(mapped_region &other)
+inline void mapped_region::swap(mapped_region &other) BOOST_NOEXCEPT
{
::boost::adl_move_swap(this->m_base, other.m_base);
::boost::adl_move_swap(this->m_size, other.m_size);
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
index eda4cf1be3..c036ce9490 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
@@ -35,6 +35,8 @@
#include <boost/container/detail/placement_new.hpp>
// move
#include <boost/move/utility_core.hpp>
+// move/detail
+#include <boost/move/detail/force_ptr.hpp>
// other boost
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
@@ -289,10 +291,10 @@ class memory_algorithm_common
max_value(ceil_units(nbytes) + AllocatedCtrlUnits, size_type(MinBlockUnits));
//We can create a new block in the end of the segment
if(old_size >= (first_min_units + MinBlockUnits)){
- block_ctrl *second = reinterpret_cast<block_ctrl *>
+ block_ctrl *second = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(first) + Alignment*first_min_units);
- first->m_size = first_min_units;
- second->m_size = old_size - first->m_size;
+ first->m_size = first_min_units & block_ctrl::size_mask;
+ second->m_size = (old_size - first->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(first);
memory_algo->priv_mark_new_allocated_block(second);
@@ -326,7 +328,8 @@ class memory_algorithm_common
(reinterpret_cast<char*>(first) + first->m_size*Alignment));
//Set the new size of the first block
size_type old_size = first->m_size;
- first->m_size = (size_type)(reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment;
+ first->m_size = size_type(size_type(reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment
+ & block_ctrl::size_mask);
memory_algo->priv_mark_new_allocated_block(first);
//Now check if we can create a new buffer in the end
@@ -346,15 +349,15 @@ class memory_algorithm_common
if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){
//Now obtain the address of the end block
block_ctrl *third = new (reinterpret_cast<char*>(second) + Alignment*second_min_units)block_ctrl;
- second->m_size = second_min_units;
- third->m_size = old_size - first->m_size - second->m_size;
+ second->m_size = second_min_units & block_ctrl::size_mask;
+ third->m_size = (old_size - first->m_size - second->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(third->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(second);
memory_algo->priv_mark_new_allocated_block(third);
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(third));
}
else{
- second->m_size = old_size - first->m_size;
+ second->m_size = (old_size - first->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(second);
}
@@ -437,15 +440,15 @@ class memory_algorithm_common
return true;
//Now we can just rewrite the size of the old buffer
- block->m_size = (received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits;
+ block->m_size = ((received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits) & block_ctrl::size_mask;
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
//We create the new block
- block_ctrl *new_block = reinterpret_cast<block_ctrl*>
+ block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(block) + block->m_size*Alignment);
//Write control data to simulate this new block was previously allocated
//and deallocate it
- new_block->m_size = old_block_units - block->m_size;
+ new_block->m_size = (old_block_units - block->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits);
memory_algo->priv_mark_new_allocated_block(block);
memory_algo->priv_mark_new_allocated_block(new_block);
@@ -520,7 +523,7 @@ class memory_algorithm_common
break;
total_request_units -= elem_units;
//This is the position where the new block must be created
- block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address);
+ block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>(block_address);
assert_alignment(new_block);
//The last block should take all the remaining space
@@ -531,7 +534,7 @@ class memory_algorithm_common
: max_value(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units))
> received_units)){
//By default, the new block will use the rest of the buffer
- new_block->m_size = received_units - total_used_units;
+ new_block->m_size = (received_units - total_used_units) & block_ctrl::size_mask;
memory_algo->priv_mark_new_allocated_block(new_block);
//If the remaining units are bigger than needed and we can
@@ -557,7 +560,7 @@ class memory_algorithm_common
}
}
else{
- new_block->m_size = elem_units;
+ new_block->m_size = elem_units & block_ctrl::size_mask;
memory_algo->priv_mark_new_allocated_block(new_block);
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/permissions.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/permissions.hpp
index 87fea28be7..0b21a685aa 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/permissions.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/permissions.hpp
@@ -29,6 +29,10 @@
#include <boost/interprocess/detail/win32_api.hpp>
+#else
+
+#include <sys/stat.h>
+
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -70,7 +74,7 @@ class permissions
#if defined(BOOST_INTERPROCESS_WINDOWS)
typedef void* os_permissions_type;
#else
- typedef int os_permissions_type;
+ typedef ::mode_t os_permissions_type;
#endif
os_permissions_type m_perm;
@@ -79,20 +83,20 @@ class permissions
public:
//!Constructs a permissions object from a user provided os-dependent
//!permissions.
- permissions(os_permissions_type type)
+ permissions(os_permissions_type type) BOOST_NOEXCEPT
: m_perm(type)
{}
//!Constructs a default permissions object:
//!A null security attributes pointer for windows or 0644
//!for UNIX.
- permissions()
+ permissions() BOOST_NOEXCEPT
{ set_default(); }
//!Sets permissions to default values:
//!A null security attributes pointer for windows or 0644
//!for UNIX.
- void set_default()
+ void set_default() BOOST_NOEXCEPT
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = 0;
@@ -103,7 +107,7 @@ class permissions
//!Sets permissions to unrestricted access:
//!A null DACL for windows or 0666 for UNIX.
- void set_unrestricted()
+ void set_unrestricted() BOOST_NOEXCEPT
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = &ipcdetail::unrestricted_permissions_holder<0>::unrestricted;
@@ -114,12 +118,12 @@ class permissions
//!Sets permissions from a user provided os-dependent
//!permissions.
- void set_permissions(os_permissions_type perm)
+ void set_permissions(os_permissions_type perm) BOOST_NOEXCEPT
{ m_perm = perm; }
//!Returns stored os-dependent
//!permissions
- os_permissions_type get_permissions() const
+ os_permissions_type get_permissions() const BOOST_NOEXCEPT
{ return m_perm; }
};
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/shared_memory_object.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/shared_memory_object.hpp
index 34a695d461..2d429efcb1 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/shared_memory_object.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/shared_memory_object.hpp
@@ -28,13 +28,14 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/shared_dir_helpers.hpp>
+#include <boost/interprocess/detail/char_wchar_holder.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <cstddef>
-#include <string>
#if defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
-# include <fcntl.h> //O_CREAT, O_*...
+# include <string>
+# include <fcntl.h> //posix_fallocate, O_CREAT, O_*...
# include <sys/mman.h> //shm_xxx
# include <unistd.h> //ftruncate, close
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
@@ -64,7 +65,7 @@ class shared_memory_object
public:
//!Default constructor. Represents an empty shared_memory_object.
- shared_memory_object();
+ shared_memory_object() BOOST_NOEXCEPT;
//!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
//!If the file previously exists, throws an error.*/
@@ -82,10 +83,39 @@ class shared_memory_object
shared_memory_object(open_only_t, const char *name, mode_t mode)
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
+ #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+ //!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
+ //!If the file previously exists, throws an error.
+ //!
+ //!Note: This function is only available on operating systems with
+ //! native wchar_t APIs (e.g. Windows).
+ shared_memory_object(create_only_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
+ { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); }
+
+ //!Tries to create a shared memory object with name "name" and mode "mode", with the
+ //!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
+ //!Otherwise throws an error.
+ //!
+ //!Note: This function is only available on operating systems with
+ //! native wchar_t APIs (e.g. Windows).
+ shared_memory_object(open_or_create_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
+ { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); }
+
+ //!Tries to open a shared memory object with name "name", with the access mode "mode".
+ //!If the file does not previously exist, it throws an error.
+ //!
+ //!Note: This function is only available on operating systems with
+ //! native wchar_t APIs (e.g. Windows).
+ shared_memory_object(open_only_t, const wchar_t*name, mode_t mode)
+ { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
+
+ #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
//!Does not throw
- shared_memory_object(BOOST_RV_REF(shared_memory_object) moved)
+ shared_memory_object(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{ this->swap(moved); }
@@ -93,7 +123,7 @@ class shared_memory_object
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
- shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved)
+ shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
{
shared_memory_object tmp(boost::move(moved));
this->swap(tmp);
@@ -101,12 +131,23 @@ class shared_memory_object
}
//!Swaps the shared_memory_objects. Does not throw
- void swap(shared_memory_object &moved);
+ void swap(shared_memory_object &moved) BOOST_NOEXCEPT;
//!Erases a shared memory object from the system.
//!Returns false on error. Never throws
static bool remove(const char *name);
+ #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+ //!Erases a shared memory object from the system.
+ //!Returns false on error. Never throws
+ //!
+ //!Note: This function is only available on operating systems with
+ //! native wchar_t APIs (e.g. Windows).
+ static bool remove(const wchar_t *name);
+
+ #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
//!Sets the size of the shared memory mapping
void truncate(offset_t length);
@@ -120,17 +161,17 @@ class shared_memory_object
~shared_memory_object();
//!Returns the name of the shared memory object.
- const char *get_name() const;
+ const char *get_name() const BOOST_NOEXCEPT;
//!Returns true if the size of the shared memory object
//!can be obtained and writes the size in the passed reference
- bool get_size(offset_t &size) const;
+ bool get_size(offset_t &size) const BOOST_NOEXCEPT;
//!Returns access mode
- mode_t get_mode() const;
+ mode_t get_mode() const BOOST_NOEXCEPT;
//!Returns mapping handle. Never throws.
- mapping_handle_t get_mapping_handle() const;
+ mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -139,17 +180,18 @@ class shared_memory_object
void priv_close();
//!Opens or creates a shared memory object.
- bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
+ template<class CharT>
+ bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm);
- file_handle_t m_handle;
- mode_t m_mode;
- std::string m_filename;
+ file_handle_t m_handle;
+ mode_t m_mode;
+ char_wchar_holder m_filename;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-inline shared_memory_object::shared_memory_object()
+inline shared_memory_object::shared_memory_object() BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{}
@@ -158,34 +200,35 @@ inline shared_memory_object::~shared_memory_object()
{ this->priv_close(); }
-inline const char *shared_memory_object::get_name() const
-{ return m_filename.c_str(); }
+inline const char *shared_memory_object::get_name() const BOOST_NOEXCEPT
+{ return m_filename.getn(); }
-inline bool shared_memory_object::get_size(offset_t &size) const
+inline bool shared_memory_object::get_size(offset_t &size) const BOOST_NOEXCEPT
{ return ipcdetail::get_file_size((file_handle_t)m_handle, size); }
-inline void shared_memory_object::swap(shared_memory_object &other)
+inline void shared_memory_object::swap(shared_memory_object &other) BOOST_NOEXCEPT
{
boost::adl_move_swap(m_handle, other.m_handle);
boost::adl_move_swap(m_mode, other.m_mode);
m_filename.swap(other.m_filename);
}
-inline mapping_handle_t shared_memory_object::get_mapping_handle() const
+inline mapping_handle_t shared_memory_object::get_mapping_handle() const BOOST_NOEXCEPT
{
return ipcdetail::mapping_handle_from_file_handle(m_handle);
}
-inline mode_t shared_memory_object::get_mode() const
+inline mode_t shared_memory_object::get_mode() const BOOST_NOEXCEPT
{ return m_mode; }
#if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
+template<class CharT>
inline bool shared_memory_object::priv_open_or_create
- (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm)
+ (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm)
{
m_filename = filename;
- std::string shmfile;
+ std::basic_string<CharT> shmfile;
ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile);
//Set accesses
@@ -222,22 +265,39 @@ inline bool shared_memory_object::priv_open_or_create
return true;
}
+#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES)
+
+inline bool shared_memory_object::remove(const wchar_t *filename)
+{
+ BOOST_TRY{
+ //Make sure a temporary path is created for shared memory
+ std::wstring shmfile;
+ ipcdetail::shared_filepath(filename, shmfile);
+ return ipcdetail::delete_file(shmfile.c_str());
+ }
+ BOOST_CATCH(...){
+ return false;
+ } BOOST_CATCH_END
+}
+
+#endif
+
inline bool shared_memory_object::remove(const char *filename)
{
- try{
+ BOOST_TRY{
//Make sure a temporary path is created for shared memory
std::string shmfile;
ipcdetail::shared_filepath(filename, shmfile);
return ipcdetail::delete_file(shmfile.c_str());
}
- catch(...){
+ BOOST_CATCH(...){
return false;
- }
+ } BOOST_CATCH_END
}
inline void shared_memory_object::truncate(offset_t length)
{
- if(!ipcdetail::truncate_file(m_handle, length)){
+ if(!ipcdetail::truncate_file(m_handle, (std::size_t)length)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
@@ -275,9 +335,10 @@ inline bool use_filesystem_based_posix()
} //shared_memory_object_detail
+template<class CharT>
inline bool shared_memory_object::priv_open_or_create
(ipcdetail::create_enum_t type,
- const char *filename,
+ const CharT *filename,
mode_t mode, const permissions &perm)
{
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
@@ -287,11 +348,12 @@ inline bool shared_memory_object::priv_open_or_create
#else
const bool add_leading_slash = true;
#endif
+ std::basic_string<CharT> fname;
if(add_leading_slash){
- ipcdetail::add_leading_slash(filename, m_filename);
+ ipcdetail::add_leading_slash(filename, fname);
}
else{
- ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, m_filename);
+ ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, fname);
}
//Create new mapping
@@ -306,19 +368,19 @@ inline bool shared_memory_object::priv_open_or_create
error_info err(mode_error);
throw interprocess_exception(err);
}
- int unix_perm = perm.get_permissions();
+ ::mode_t unix_perm = perm.get_permissions();
switch(type){
case ipcdetail::DoOpen:
{
//No oflag addition
- m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ m_handle = shm_open(fname.c_str(), oflag, unix_perm);
}
break;
case ipcdetail::DoCreate:
{
oflag |= (O_CREAT | O_EXCL);
- m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ m_handle = shm_open(fname.c_str(), oflag, unix_perm);
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
}
@@ -328,16 +390,16 @@ inline bool shared_memory_object::priv_open_or_create
{
//We need a create/open loop to change permissions correctly using fchmod, since
//with "O_CREAT" only we don't know if we've created or opened the shm.
- while(1){
+ while(true){
//Try to create shared memory
- m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
+ m_handle = shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
//If successful change real permissions
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
}
//If already exists, try to open
else if(errno == EEXIST){
- m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
+ m_handle = shm_open(fname.c_str(), oflag, unix_perm);
//If open fails and errno tells the file does not exist
//(shm was removed between creation and opening tries), just retry
if(m_handle < 0 && errno == ENOENT){
@@ -370,7 +432,7 @@ inline bool shared_memory_object::priv_open_or_create
inline bool shared_memory_object::remove(const char *filename)
{
- try{
+ BOOST_TRY{
std::string filepath;
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
const bool add_leading_slash = false;
@@ -387,14 +449,30 @@ inline bool shared_memory_object::remove(const char *filename)
}
return 0 == shm_unlink(filepath.c_str());
}
- catch(...){
+ BOOST_CATCH(...){
return false;
- }
+ } BOOST_CATCH_END
}
inline void shared_memory_object::truncate(offset_t length)
{
- if(0 != ftruncate(m_handle, length)){
+ #ifdef BOOST_INTERPROCESS_POSIX_FALLOCATE
+ int ret = EINTR;
+ while (EINTR == ret) {
+ ret = posix_fallocate(m_handle, 0, length);
+ }
+
+ if (ret && ret != EOPNOTSUPP && ret != ENODEV){
+ error_info err(ret);
+ throw interprocess_exception(err);
+ }
+ //ftruncate fallback
+ #endif //BOOST_INTERPROCESS_POSIX_FALLOCATE
+
+ handle_eintr:
+ if (0 != ftruncate(m_handle, length)){
+ if (errno == EINTR)
+ goto handle_eintr;
error_info err(system_error_code());
throw interprocess_exception(err);
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/deleter.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/deleter.hpp
index 3cd469df8b..bc0f8c8aaf 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/deleter.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/deleter.hpp
@@ -52,7 +52,7 @@ class deleter
segment_manager_pointer mp_mngr;
public:
- deleter(segment_manager_pointer pmngr)
+ deleter(segment_manager_pointer pmngr) BOOST_NOEXCEPT
: mp_mngr(pmngr)
{}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
index 30866adefe..e2ce9a78d8 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp
@@ -36,7 +36,7 @@ class bad_weak_ptr
{
public:
- virtual char const * what() const noexcept
+ virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return "boost::interprocess::bad_weak_ptr"; }
};
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/shared_count.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/shared_count.hpp
index 61cf9ea198..9b0244e423 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/shared_count.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/shared_count.hpp
@@ -25,7 +25,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/checked_delete.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
@@ -47,18 +46,21 @@ template<class T, class VoidAllocator, class Deleter>
class shared_count
{
public:
+
+ typedef typename boost::container::
+ allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
- rebind_pointer<T>::type pointer;
+ pointer_traits<void_ptr>::template
+ rebind_pointer<T>::type pointer;
private:
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<counted_impl>::type counted_impl_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<sp_counted_base>::type counted_base_ptr;
typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits;
@@ -67,11 +69,11 @@ class shared_count
portable_rebind_alloc<counted_impl>::type counted_impl_allocator;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<const Deleter>::type const_deleter_pointer;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
pointer m_px;
@@ -229,8 +231,10 @@ template<class T, class VoidAllocator, class Deleter>
class weak_count
{
public:
+ typedef typename boost::container::
+ allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<T>::type pointer;
private:
@@ -238,10 +242,10 @@ class weak_count
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<counted_impl>::type counted_impl_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<sp_counted_base>::type counted_base_ptr;
pointer m_px;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
index a025309bd5..ed1d72706f 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
@@ -43,17 +43,19 @@ namespace ipcdetail {
template <class Allocator>
struct scoped_ptr_dealloc_functor
{
- typedef typename Allocator::pointer pointer;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::pointer pointer;
+
typedef ipcdetail::integral_constant<unsigned,
boost::interprocess::version<Allocator>::value> alloc_version;
typedef ipcdetail::integral_constant<unsigned, 1> allocator_v1;
typedef ipcdetail::integral_constant<unsigned, 2> allocator_v2;
private:
- void priv_deallocate(const typename Allocator::pointer &p, allocator_v1)
+ void priv_deallocate(const pointer &p, allocator_v1)
{ m_alloc.deallocate(p, 1); }
- void priv_deallocate(const typename Allocator::pointer &p, allocator_v2)
+ void priv_deallocate(const pointer &p, allocator_v2)
{ m_alloc.deallocate_one(p); }
public:
@@ -85,7 +87,11 @@ class sp_counted_impl_pd
allocator_traits<A>::template
portable_rebind_alloc
< const this_type >::type const_this_allocator;
- typedef typename this_allocator::pointer this_pointer;
+ typedef typename boost::container::
+ allocator_traits<this_allocator>
+ ::pointer this_pointer;
+ typedef typename boost::container::
+ allocator_traits<A>::pointer a_pointer;
typedef typename boost::intrusive::
pointer_traits<this_pointer> this_pointer_traits;
@@ -93,10 +99,10 @@ class sp_counted_impl_pd
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
typedef typename boost::intrusive::
- pointer_traits<typename A::pointer>::template
+ pointer_traits<a_pointer>::template
rebind_pointer<const D>::type const_deleter_pointer;
typedef typename boost::intrusive::
- pointer_traits<typename A::pointer>::template
+ pointer_traits<a_pointer>::template
rebind_pointer<const A>::type const_allocator_pointer;
typedef typename D::pointer pointer;
@@ -127,8 +133,7 @@ class sp_counted_impl_pd
//Do it now!
scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
deleter_ptr(this_ptr, a_copy);
- typedef typename this_allocator::value_type value_type;
- ipcdetail::to_raw_pointer(this_ptr)->~value_type();
+ ipcdetail::to_raw_pointer(this_ptr)->~this_type();
}
void release() // nothrow
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/scoped_ptr.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/scoped_ptr.hpp
index 5506040b63..f480428ca8 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/scoped_ptr.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/scoped_ptr.hpp
@@ -91,49 +91,49 @@ class scoped_ptr
//!Assigns internal pointer as 0 and returns previous pointer. This will
//!avoid deletion on destructor
- pointer release()
+ pointer release() BOOST_NOEXCEPT
{ pointer tmp(m_ptr); m_ptr = 0; return tmp; }
//!Returns a reference to the object pointed to by the stored pointer.
//!Never throws.
- reference operator*() const
+ reference operator*() const BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return *m_ptr; }
//!Returns the internal stored pointer.
//!Never throws.
- pointer &operator->()
+ pointer &operator->() BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return m_ptr; }
//!Returns the internal stored pointer.
//!Never throws.
- const pointer &operator->() const
+ const pointer &operator->() const BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return m_ptr; }
//!Returns the stored pointer.
//!Never throws.
- pointer & get()
+ pointer & get() BOOST_NOEXCEPT
{ return m_ptr; }
//!Returns the stored pointer.
//!Never throws.
- const pointer & get() const
+ const pointer & get() const BOOST_NOEXCEPT
{ return m_ptr; }
typedef pointer this_type::*unspecified_bool_type;
//!Conversion to bool
//!Never throws
- operator unspecified_bool_type() const
+ operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return m_ptr == 0? 0: &this_type::m_ptr; }
//!Returns true if the stored pointer is 0.
//!Never throws.
- bool operator! () const // never throws
+ bool operator! () const BOOST_NOEXCEPT // never throws
{ return m_ptr == 0; }
//!Exchanges the internal pointer and deleter with other scoped_ptr
//!Never throws.
- void swap(scoped_ptr & b) // never throws
+ void swap(scoped_ptr & b) BOOST_NOEXCEPT // never throws
{
::boost::adl_move_swap(static_cast<Deleter&>(*this), static_cast<Deleter&>(b));
::boost::adl_move_swap(m_ptr, b.m_ptr);
@@ -148,7 +148,7 @@ class scoped_ptr
//!Exchanges the internal pointer and deleter with other scoped_ptr
//!Never throws.
template<class T, class D> inline
-void swap(scoped_ptr<T, D> & a, scoped_ptr<T, D> & b)
+void swap(scoped_ptr<T, D> & a, scoped_ptr<T, D> & b) BOOST_NOEXCEPT
{ a.swap(b); }
//!Returns a copy of the stored pointer
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp
index 67aa597c4d..c50f2cbf7e 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp
@@ -103,18 +103,20 @@ class shared_ptr
typedef T element_type;
typedef T value_type;
+ typedef typename boost::container::
+ allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<T>::type pointer;
typedef typename ipcdetail::add_reference
<value_type>::type reference;
typedef typename ipcdetail::add_reference
<const value_type>::type const_reference;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<const Deleter>::type const_deleter_pointer;
typedef typename boost::intrusive::
- pointer_traits<typename VoidAllocator::pointer>::template
+ pointer_traits<void_ptr>::template
rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
@@ -395,16 +397,16 @@ template<class T, class ManagedMemory>
inline typename managed_shared_ptr<T, ManagedMemory>::type
make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
{
- try{
+ BOOST_TRY{
return typename managed_shared_ptr<T, ManagedMemory>::type
( constructed_object
, managed_memory.template get_allocator<void>()
, managed_memory.template get_deleter<T>()
);
}
- catch(...){
+ BOOST_CATCH(...){
return typename managed_shared_ptr<T, ManagedMemory>::type();
- }
+ } BOOST_CATCH_END
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/weak_ptr.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/weak_ptr.hpp
index c6e52ddabe..e4873122d8 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/weak_ptr.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/smart_ptr/weak_ptr.hpp
@@ -63,8 +63,10 @@ class weak_ptr
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T, A, D> this_type;
+ typedef typename boost::container::
+ allocator_traits<A>::pointer alloc_ptr;
typedef typename boost::intrusive::
- pointer_traits<typename A::pointer>::template
+ pointer_traits<alloc_ptr>::template
rebind_pointer<T>::type pointer;
typedef typename ipcdetail::add_reference
<T>::type reference;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/streams/bufferstream.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/streams/bufferstream.hpp
index 51f52b09e0..51987233c4 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/streams/bufferstream.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/streams/bufferstream.hpp
@@ -88,7 +88,7 @@ class basic_bufferbuf
: basic_streambuf_t(), m_mode(mode), m_buffer(buf), m_length(length)
{ this->set_pointers(); }
- virtual ~basic_bufferbuf(){}
+ virtual ~basic_bufferbuf() BOOST_OVERRIDE {}
public:
//!Returns the pointer and size of the internal buffer.
@@ -115,14 +115,14 @@ class basic_bufferbuf
}
protected:
- virtual int_type underflow()
+ virtual int_type underflow() BOOST_OVERRIDE
{
// Precondition: gptr() >= egptr(). Returns a character, if available.
return this->gptr() != this->egptr() ?
CharTraits::to_int_type(*this->gptr()) : CharTraits::eof();
}
- virtual int_type pbackfail(int_type c = CharTraits::eof())
+ virtual int_type pbackfail(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(this->gptr() != this->eback()) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -132,7 +132,7 @@ class basic_bufferbuf
}
else if(m_mode & std::ios_base::out) {
this->gbump(-1);
- *this->gptr() = c;
+ *this->gptr() = CharTraits::to_char_type(c);
return c;
}
else
@@ -147,7 +147,7 @@ class basic_bufferbuf
return CharTraits::eof();
}
- virtual int_type overflow(int_type c = CharTraits::eof())
+ virtual int_type overflow(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(m_mode & std::ios_base::out) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -181,7 +181,7 @@ class basic_bufferbuf
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
+ = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{
bool in = false;
bool out = false;
@@ -238,7 +238,7 @@ class basic_bufferbuf
return pos_type(off_type(-1));
else {
this->setp(this->pbase(), this->pbase() + n);
- this->pbump(off);
+ this->pbump(static_cast<int>(off));
}
}
@@ -246,7 +246,7 @@ class basic_bufferbuf
}
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
+ = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{ return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); }
private:
@@ -308,7 +308,7 @@ class basic_ibufferstream :
, basic_streambuf_t(this)
{}
- ~basic_ibufferstream(){};
+ ~basic_ibufferstream(){}
public:
//!Returns the address of the stored
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/cv_status.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/cv_status.hpp
new file mode 100644
index 0000000000..afbcdf6fd7
--- /dev/null
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/cv_status.hpp
@@ -0,0 +1,29 @@
+// cv_status.hpp
+//
+// Copyright (C) 2011 Vicente J. Botet Escriba
+// Copyright (C) 2021 Ion Gaztanaga
+//
+// 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_INTERPROCESS_CV_STATUS_HPP
+#define BOOST_INTERPROCESS_CV_STATUS_HPP
+
+#include <boost/core/scoped_enum.hpp>
+
+namespace boost {
+namespace interprocess {
+
+ // enum class cv_status;
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status)
+ {
+ no_timeout,
+ timeout
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(cv_status)
+
+} //namespace interprocess
+} //namespace boost
+
+#endif // header
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/common_algorithms.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/common_algorithms.hpp
index 87739b8121..3cb1d1a17d 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/common_algorithms.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/common_algorithms.hpp
@@ -23,16 +23,17 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/spin/wait.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
-template<class MutexType>
-bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time)
+template<class MutexType, class TimePoint>
+bool try_based_timed_lock(MutexType &m, const TimePoint &abs_time)
{
//Same as lock()
- if(abs_time == boost::posix_time::pos_infin){
+ if(is_pos_infinity(abs_time)){
m.lock();
return true;
}
@@ -45,7 +46,7 @@ bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time
}
else{
spin_wait swait;
- while(microsec_clock::universal_time() < abs_time){
+ while(microsec_clock<TimePoint>::universal_time() < abs_time){
if(m.try_lock()){
return true;
}
@@ -73,46 +74,19 @@ void try_based_lock(MutexType &m)
}
template<class MutexType>
-void timed_based_lock(MutexType &m, unsigned const uCheckPeriodSec)
-{
- const boost::posix_time::time_duration dur(0, 0, uCheckPeriodSec);
- boost::posix_time::ptime deadline(microsec_clock::universal_time()+dur);
- if(!m.timed_lock(deadline)){
- spin_wait swait;
- do{
- deadline = microsec_clock::universal_time()+dur;
- if(m.timed_lock(deadline)){
- break;
- }
- else{
- swait.yield();
- }
- }
- while(1);
- }
-}
-
-template<class MutexType>
-void timed_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time, unsigned const uCheckPeriodSec)
+void timeout_when_locking_aware_lock(MutexType &m)
{
- const boost::posix_time::time_duration dur(0, 0, uCheckPeriodSec);
- boost::posix_time::ptime deadline(microsec_clock::universal_time()+dur);
- if(abs_time <= deadline){
- m.timed_lock(abs_time);
- }
- else if(!m.timed_lock(deadline)){
- spin_wait swait;
- do{
- deadline = microsec_clock::universal_time()+dur;
- if(m.timed_lock(deadline)){
- break;
- }
- else{
- swait.yield();
- }
+ #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
+ if (!m.timed_lock(microsec_clock<ustime>::universal_time()
+ + usduration_milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS)))
+ {
+ throw interprocess_exception(timeout_when_locking_error
+ , "Interprocess mutex timeout when locking. Possible deadlock: "
+ "owner died without unlocking?");
}
- while(1);
- }
+ #else
+ m.lock();
+ #endif
}
} //namespace ipcdetail
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
index 9978309b96..a4cce7ba7e 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
@@ -193,130 +193,124 @@ class condition_algorithm_8a
typedef typename ConditionMembers::integer_type integer_type;
public:
- template<class Lock>
- static bool wait ( ConditionMembers &data, Lock &lock
- , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
- static void signal(ConditionMembers &data, bool broadcast);
-};
-
-template<class ConditionMembers>
-inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast)
-{
- integer_type nsignals_to_issue;
-
+ template<bool TimeoutEnabled, class Lock, class TimePoint>
+ static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &abs_time)
{
- scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
-
- if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
- if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- return;
- }
- if (broadcast) {
- data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
- data.get_nwaiters_blocked() = 0;
- }
- else {
- nsignals_to_issue = 1;
- data.get_nwaiters_to_unblock()++;
- data.get_nwaiters_blocked()--;
+ //Initialize to avoid warnings
+ integer_type nsignals_was_left = 0;
+ integer_type nwaiters_was_gone = 0;
+
+ data.get_sem_block_lock().wait();
+ ++data.get_nwaiters_blocked();
+ data.get_sem_block_lock().post();
+
+ //Unlock external lock and program for relock
+ lock_inverter<Lock> inverted_lock(lock);
+ scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+
+ bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_<TimeoutEnabled>());
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+ if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
+ if ( bTimedOut ) { // timeout (or canceled)
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_nwaiters_blocked()--;
+ }
+ else {
+ data.get_nwaiters_gone()++; // count spurious wakeups.
+ }
+ }
+ if ( 0 == --data.get_nwaiters_to_unblock() ) {
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_sem_block_lock().post(); // open the gate.
+ nsignals_was_left = 0; // do not open the gate below again.
+ }
+ else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
+ data.get_nwaiters_gone() = 0;
+ }
+ }
}
- }
- else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
- data.get_sem_block_lock().wait(); // close the gate
- if ( 0 != data.get_nwaiters_gone() ) {
- data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
+ else if ( (std::numeric_limits<integer_type>::max)()/2
+ == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
+ data.get_sem_block_lock().wait();
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-)
+ data.get_sem_block_lock().post();
data.get_nwaiters_gone() = 0;
}
- if (broadcast) {
- nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
- data.get_nwaiters_blocked() = 0;
- }
- else {
- nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
- data.get_nwaiters_blocked()--;
- }
- }
- else { // NO-OP
//locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- return;
}
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- }
- data.get_sem_block_queue().post(nsignals_to_issue);
-}
-template<class ConditionMembers>
-template<class Lock>
-inline bool condition_algorithm_8a<ConditionMembers>::wait
- ( ConditionMembers &data
- , Lock &lock
- , bool tout_enabled
- , const boost::posix_time::ptime &abs_time
- )
-{
- //Initialize to avoid warnings
- integer_type nsignals_was_left = 0;
- integer_type nwaiters_was_gone = 0;
-
- data.get_sem_block_lock().wait();
- ++data.get_nwaiters_blocked();
- data.get_sem_block_lock().post();
+ if ( 1 == nsignals_was_left ) {
+ if ( 0 != nwaiters_was_gone ) {
+ // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
+ while ( nwaiters_was_gone-- ) {
+ data.get_sem_block_queue().wait(); // better now than spurious later
+ }
+ }
+ data.get_sem_block_lock().post(); // open the gate
+ }
- //Unlock external lock and program for relock
- lock_inverter<Lock> inverted_lock(lock);
- scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
+ //lock.lock(); called from unlocker destructor
- bool bTimedOut = tout_enabled
- ? !data.get_sem_block_queue().timed_wait(abs_time)
- : (data.get_sem_block_queue().wait(), false);
+ return ( bTimedOut ) ? false : true;
+ }
+ static void signal(ConditionMembers &data, bool broadcast)
{
- scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
- if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
- if ( bTimedOut ) { // timeout (or canceled)
- if ( 0 != data.get_nwaiters_blocked() ) {
- data.get_nwaiters_blocked()--;
+ integer_type nsignals_to_issue;
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+
+ if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
+ if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
+ }
+ if (broadcast) {
+ data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
}
else {
- data.get_nwaiters_gone()++; // count spurious wakeups.
+ nsignals_to_issue = 1;
+ data.get_nwaiters_to_unblock()++;
+ data.get_nwaiters_blocked()--;
}
}
- if ( 0 == --data.get_nwaiters_to_unblock() ) {
- if ( 0 != data.get_nwaiters_blocked() ) {
- data.get_sem_block_lock().post(); // open the gate.
- nsignals_was_left = 0; // do not open the gate below again.
- }
- else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
+ else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
+ data.get_sem_block_lock().wait(); // close the gate
+ if ( 0 != data.get_nwaiters_gone() ) {
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
data.get_nwaiters_gone() = 0;
}
+ if (broadcast) {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
+ }
+ else {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
+ data.get_nwaiters_blocked()--;
+ }
}
- }
- else if ( (std::numeric_limits<integer_type>::max)()/2
- == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
- data.get_sem_block_lock().wait();
- data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-)
- data.get_sem_block_lock().post();
- data.get_nwaiters_gone() = 0;
- }
- //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
- }
-
- if ( 1 == nsignals_was_left ) {
- if ( 0 != nwaiters_was_gone ) {
- // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
- while ( nwaiters_was_gone-- ) {
- data.get_sem_block_queue().wait(); // better now than spurious later
+ else { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
}
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
}
- data.get_sem_block_lock().post(); // open the gate
+ data.get_sem_block_queue().post(nsignals_to_issue);
}
- //lock.lock(); called from unlocker destructor
-
- return ( bTimedOut ) ? false : true;
-}
+ private:
+ template<class TimePoint>
+ static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_<true>)
+ { return sem.timed_wait(abs_time); }
+ template<class TimePoint>
+ static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_<false>)
+ { sem.wait(); return true; }
+};
template<class ConditionMembers>
class condition_8a_wrapper
@@ -326,7 +320,7 @@ class condition_8a_wrapper
condition_8a_wrapper &operator=(const condition_8a_wrapper &);
ConditionMembers m_data;
- typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
+ typedef condition_algorithm_8a<ConditionMembers> algo_type;
public:
@@ -352,7 +346,7 @@ class condition_8a_wrapper
{
if (!lock)
throw lock_exception();
- algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ algo_type::template wait<false>(m_data, lock, 0);
}
template <typename L, typename Pr>
@@ -362,24 +356,24 @@ class condition_8a_wrapper
throw lock_exception();
while (!pred())
- algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
+ algo_type::template wait<false>(m_data, lock, 0);
}
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ template <typename L, class TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
- return algo_type::wait(m_data, lock, true, abs_time);
+ return algo_type::template wait<true>(m_data, lock, abs_time);
}
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ template <typename L, class TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred()){
- if (!algo_type::wait(m_data, lock, true, abs_time))
+ if (!algo_type::template wait<true>(m_data, lock, abs_time))
return pred();
}
return true;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/locks.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/locks.hpp
index 88d9c0cb48..a2beb8917c 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/locks.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/detail/locks.hpp
@@ -35,18 +35,18 @@ class internal_mutex_lock
typedef typename Lock::mutex_type::internal_mutex_type mutex_type;
- internal_mutex_lock(Lock &l)
+ BOOST_INTERPROCESS_FORCEINLINE internal_mutex_lock(Lock &l)
: l_(l)
{}
- mutex_type* mutex() const
+ BOOST_INTERPROCESS_FORCEINLINE mutex_type* mutex() const
{ return l_ ? &l_.mutex()->internal_mutex() : 0; }
- void lock() { l_.lock(); }
+ BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock(); }
- void unlock() { l_.unlock(); }
+ BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock(); }
- operator unspecified_bool_type() const
+ BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const
{ return l_ ? &internal_mutex_lock::lock : 0; }
private:
@@ -58,11 +58,13 @@ class lock_inverter
{
Lock &l_;
public:
- lock_inverter(Lock &l)
+ BOOST_INTERPROCESS_FORCEINLINE lock_inverter(Lock &l)
: l_(l)
{}
- void lock() { l_.unlock(); }
- void unlock() { l_.lock(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.unlock(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.lock(); }
};
template <class Lock>
@@ -71,12 +73,15 @@ class lock_to_sharable
Lock &l_;
public:
- explicit lock_to_sharable(Lock &l)
+ BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_sharable(Lock &l)
: l_(l)
{}
- void lock() { l_.lock_sharable(); }
- bool try_lock(){ return l_.try_lock_sharable(); }
- void unlock() { l_.unlock_sharable(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock_sharable(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE bool try_lock(){ return l_.try_lock_sharable(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock_sharable(); }
};
template <class Lock>
@@ -85,11 +90,16 @@ class lock_to_wait
Lock &l_;
public:
- explicit lock_to_wait(Lock &l)
+ BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_wait(Lock &l)
: l_(l)
{}
- void lock() { l_.wait(); }
- bool try_lock(){ return l_.try_wait(); }
+ BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.wait(); }
+
+ BOOST_INTERPROCESS_FORCEINLINE bool try_lock() { return l_.try_wait(); }
+
+ template<class TimePoint>
+ BOOST_INTERPROCESS_FORCEINLINE bool timed_lock(const TimePoint &abs_time)
+ { return l_.timed_wait(abs_time); }
};
} //namespace ipcdetail
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_condition.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_condition.hpp
index c98ece8821..24ca5b5f0f 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_condition.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_condition.hpp
@@ -24,23 +24,23 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
-#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <boost/interprocess/sync/posix/condition.hpp>
- #define BOOST_INTERPROCESS_USE_POSIX
+ #define BOOST_INTERPROCESS_CONDITION_USE_POSIX
//Experimental...
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/sync/windows/condition.hpp>
- #define BOOST_INTERPROCESS_USE_WINDOWS
-#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+ #define BOOST_INTERPROCESS_CONDITION_USE_WINAPI
+#else
+ //spin_condition is used
#include <boost/interprocess/sync/spin/condition.hpp>
- #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -49,14 +49,6 @@
//!Describes process-shared variables interprocess_condition class
namespace boost {
-
-#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-
-namespace posix_time
-{ class ptime; }
-
-#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-
namespace interprocess {
class named_condition;
@@ -121,8 +113,8 @@ class interprocess_condition
//!this->notify_one() or this->notify_all(), or until time abs_time is reached,
//!and then reacquires the lock.
//!Returns: false if time abs_time is reached, otherwise true.
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ template <typename L, class TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_condition.timed_wait(internal_lock, abs_time);
@@ -131,28 +123,48 @@ class interprocess_condition
//!The same as: while (!pred()) {
//! if (!timed_wait(lock, abs_time)) return pred();
//! } return true;
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ template <typename L, class TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_condition.timed_wait(internal_lock, abs_time, pred);
}
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface.
+ template <typename L, class TimePoint>
+ cv_status wait_until(L& lock, const TimePoint &abs_time)
+ { return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
+
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface.
+ template <typename L, class TimePoint, typename Pr>
+ bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
+ { return this->timed_wait(lock, abs_time, pred); }
+
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface and uses relative timeouts.
+ template <typename L, class Duration>
+ cv_status wait_for(L& lock, const Duration &dur)
+ { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
+
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface and uses relative timeouts
+ template <typename L, class Duration, typename Pr>
+ bool wait_for(L& lock, const Duration &dur, Pr pred)
+ { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
+
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
- #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
- #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
- ipcdetail::spin_condition m_condition;
- #elif defined(BOOST_INTERPROCESS_USE_POSIX)
- #undef BOOST_INTERPROCESS_USE_POSIX
+ #if defined(BOOST_INTERPROCESS_CONDITION_USE_POSIX)
ipcdetail::posix_condition m_condition;
- #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
- #undef BOOST_INTERPROCESS_USE_WINDOWS
- ipcdetail::windows_condition m_condition;
+ #elif defined(BOOST_INTERPROCESS_CONDITION_USE_WINAPI)
+ ipcdetail::winapi_condition m_condition;
#else
- #error "Unknown platform for interprocess_mutex"
+ ipcdetail::spin_condition m_condition;
#endif
+
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_mutex.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_mutex.hpp
index 8bfc02c15d..4eb1f592c8 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_mutex.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/interprocess_mutex.hpp
@@ -28,30 +28,28 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/assert.hpp>
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <boost/interprocess/sync/posix/mutex.hpp>
- #define BOOST_INTERPROCESS_USE_POSIX
-//Experimental...
+ #define BOOST_INTERPROCESS_MUTEX_USE_POSIX
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ //Experimental...
+ #define BOOST_INTERPROCESS_MUTEX_USE_WINAPI
#include <boost/interprocess/sync/windows/mutex.hpp>
- #define BOOST_INTERPROCESS_USE_WINDOWS
-#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+#else
+ //spin_mutex is used
#include <boost/interprocess/sync/spin/mutex.hpp>
- #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+ namespace boost {
+ namespace interprocess {
+ namespace ipcdetail{
+ namespace robust_emulation_helpers {
-namespace boost {
-namespace interprocess {
-namespace ipcdetail{
-namespace robust_emulation_helpers {
-
-template<class T>
-class mutex_traits;
-
-}}}}
+ template<class T>
+ class mutex_traits;
+ }}}}
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -76,21 +74,16 @@ class interprocess_mutex
friend class interprocess_condition;
public:
- #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
- #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
+ #if defined(BOOST_INTERPROCESS_MUTEX_USE_POSIX)
+ typedef ipcdetail::posix_mutex internal_mutex_type;
+ #elif defined(BOOST_INTERPROCESS_MUTEX_USE_WINAPI)
+ typedef ipcdetail::winapi_mutex internal_mutex_type;
+ #else
typedef ipcdetail::spin_mutex internal_mutex_type;
private:
friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
void take_ownership(){ m_mutex.take_ownership(); }
public:
- #elif defined(BOOST_INTERPROCESS_USE_POSIX)
- #undef BOOST_INTERPROCESS_USE_POSIX
- typedef ipcdetail::posix_mutex internal_mutex_type;
- #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
- #undef BOOST_INTERPROCESS_USE_WINDOWS
- typedef ipcdetail::windows_mutex internal_mutex_type;
- #else
- #error "Unknown platform for interprocess_mutex"
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -104,20 +97,34 @@ class interprocess_mutex
//!the result is undefined. Does not throw.
~interprocess_mutex();
+ //!Requires: The calling thread does not own the mutex.
+ //!
//!Effects: The calling thread tries to obtain ownership of the mutex, and
//! if another thread has ownership of the mutex, it waits until it can
//! obtain the ownership. If a thread takes ownership of the mutex the
//! mutex must be unlocked by the same mutex.
//!Throws: interprocess_exception on error.
+ //!
+ //!Note: A program may deadlock if the thread that has ownership calls
+ //! this function. If the implementation can detect the deadlock,
+ //! an exception could be thrown.
void lock();
+ //!Requires: The calling thread does not own the mutex.
+ //!
//!Effects: The calling thread tries to obtain ownership of the mutex, and
//! if another thread has ownership of the mutex returns immediately.
//!Returns: If the thread acquires ownership of the mutex, returns true, if
//! the another thread has ownership of the mutex, returns false.
//!Throws: interprocess_exception on error.
+ //!
+ //!Note: A program may deadlock if the thread that has ownership calls
+ //! this function. If the implementation can detect the deadlock,
+ //! an exception could be thrown.
bool try_lock();
+ //!Requires: The calling thread does not own the mutex.
+ //!
//!Effects: The calling thread will try to obtain exclusive ownership of the
//! mutex if it can do so in until the specified time is reached. If the
//! mutex supports recursive locking, the mutex must be unlocked the same
@@ -125,7 +132,22 @@ class interprocess_mutex
//!Returns: If the thread acquires ownership of the mutex, returns true, if
//! the timeout expires returns false.
//!Throws: interprocess_exception on error.
- bool timed_lock(const boost::posix_time::ptime &abs_time);
+ //!
+ //!Note: A program may deadlock if the thread that has ownership calls
+ //! this function. If the implementation can detect the deadlock,
+ //! an exception could be thrown.
+ template<class TimePoint>
+ bool timed_lock(const TimePoint &abs_time);
+
+ //!Same as `timed_lock`, but this function is modeled after the
+ //!standard library interface.
+ template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
+ { return this->timed_lock(abs_time); }
+
+ //!Same as `timed_lock`, but this function is modeled after the
+ //!standard library interface.
+ template<class Duration> bool try_lock_for(const Duration &dur)
+ { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: interprocess_exception on error.
@@ -155,26 +177,13 @@ inline interprocess_mutex::interprocess_mutex(){}
inline interprocess_mutex::~interprocess_mutex(){}
inline void interprocess_mutex::lock()
-{
- #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
- boost::posix_time::ptime wait_time
- = microsec_clock::universal_time()
- + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
- if (!m_mutex.timed_lock(wait_time))
- {
- throw interprocess_exception(timeout_when_locking_error
- , "Interprocess mutex timeout when locking. Possible deadlock: "
- "owner died without unlocking?");
- }
- #else
- m_mutex.lock();
- #endif
-}
+{ ipcdetail::timeout_when_locking_aware_lock(m_mutex); }
inline bool interprocess_mutex::try_lock()
{ return m_mutex.try_lock(); }
-inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+template <class TimePoint>
+inline bool interprocess_mutex::timed_lock(const TimePoint &abs_time)
{ return m_mutex.timed_lock(abs_time); }
inline void interprocess_mutex::unlock()
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/lock_options.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/lock_options.hpp
index 981ff5b6d3..a79159a480 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/lock_options.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/lock_options.hpp
@@ -26,14 +26,6 @@
//!Describes the lock options with associated with interprocess_mutex lock constructors.
namespace boost {
-
-#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-
-namespace posix_time
-{ class ptime; }
-
-#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
-
namespace interprocess {
//!Type to indicate to a mutex lock constructor that must not lock the mutex.
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/condition.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/condition.hpp
index 5372d96891..f151a5b98c 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/condition.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/condition.hpp
@@ -22,11 +22,12 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/cv_status.hpp>
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
-#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/sync/posix/mutex.hpp>
#include <boost/assert.hpp>
@@ -84,13 +85,13 @@ class posix_condition
//!this->notify_one() or this->notify_all(), or until time abs_time is reached,
//!and then reacquires the lock.
//!Returns: false if time abs_time is reached, otherwise true.
- template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ template <typename L, typename TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
//Posix does not support infinity absolute time so handle it here
- if(abs_time == boost::posix_time::pos_infin){
+ if(ipcdetail::is_pos_infinity(abs_time)){
this->wait(lock);
return true;
}
@@ -100,13 +101,13 @@ class posix_condition
//!The same as: while (!pred()) {
//! if (!timed_wait(lock, abs_time)) return pred();
//! } return true;
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ template <typename L, typename TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
//Posix does not support infinity absolute time so handle it here
- if(abs_time == boost::posix_time::pos_infin){
+ if(ipcdetail::is_pos_infinity(abs_time)){
this->wait(lock, pred);
return true;
}
@@ -117,10 +118,30 @@ class posix_condition
return true;
}
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface.
+ template <typename L, class TimePoint>
+ cv_status wait_until(L& lock, const TimePoint &abs_time)
+ { return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
+
+ //!Same as `timed_wait`, but this function is modeled after the
+ //!standard library interface.
+ template <typename L, class TimePoint, typename Pr>
+ bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
+ { return this->timed_wait(lock, abs_time, pred); }
+
+ template <typename L, class Duration>
+ cv_status wait_for(L& lock, const Duration &dur)
+ { return this->wait_until(lock, duration_to_ustime(dur)) ? cv_status::no_timeout : cv_status::timeout; }
+
+ template <typename L, class Duration, typename Pr>
+ bool wait_for(L& lock, const Duration &dur, Pr pred)
+ { return this->wait_until(lock, duration_to_ustime(dur), pred); }
void do_wait(posix_mutex &mut);
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, posix_mutex &mut);
+ template<class TimePoint>
+ bool do_timed_wait(const TimePoint &abs_time, posix_mutex &mut);
private:
pthread_cond_t m_condition;
@@ -175,10 +196,11 @@ inline void posix_condition::do_wait(posix_mutex &mut)
BOOST_ASSERT(res == 0); (void)res;
}
+template<class TimePoint>
inline bool posix_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, posix_mutex &mut)
+ (const TimePoint &abs_time, posix_mutex &mut)
{
- timespec ts = ptime_to_timespec(abs_time);
+ timespec ts = timepoint_to_timespec(abs_time);
pthread_mutex_t* pmutex = &mut.m_mut;
int res = 0;
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/mutex.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/mutex.hpp
index 70adc23c96..69cc1626ea 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/mutex.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/mutex.hpp
@@ -41,10 +41,11 @@
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/exceptions.hpp>
-#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
+
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
# include <boost/interprocess/detail/os_thread_functions.hpp>
@@ -69,7 +70,14 @@ class posix_mutex
void lock();
bool try_lock();
- bool timed_lock(const boost::posix_time::ptime &abs_time);
+ template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
+
+ template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
+ { return this->timed_lock(abs_time); }
+
+ template<class Duration> bool try_lock_for(const Duration &dur)
+ { return this->timed_lock(duration_to_ustime(dur)); }
+
void unlock();
friend class posix_condition;
@@ -93,28 +101,66 @@ inline posix_mutex::~posix_mutex()
inline void posix_mutex::lock()
{
- if (pthread_mutex_lock(&m_mut) != 0)
+ int res = pthread_mutex_lock(&m_mut);
+ #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ if (res == EOWNERDEAD)
+ {
+ //We can't inform the application and data might
+ //corrupted, so be safe and mark the mutex as not recoverable
+ //so applications can act accordingly.
+ pthread_mutex_unlock(&m_mut);
+ throw lock_exception(not_recoverable);
+ }
+ else if (res == ENOTRECOVERABLE)
+ throw lock_exception(not_recoverable);
+ #endif
+ if (res != 0)
throw lock_exception();
}
inline bool posix_mutex::try_lock()
{
int res = pthread_mutex_trylock(&m_mut);
+ #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ if (res == EOWNERDEAD)
+ {
+ //We can't inform the application and data might
+ //corrupted, so be safe and mark the mutex as not recoverable
+ //so applications can act accordingly.
+ pthread_mutex_unlock(&m_mut);
+ throw lock_exception(not_recoverable);
+ }
+ else if (res == ENOTRECOVERABLE)
+ throw lock_exception(not_recoverable);
+ #endif
if (!(res == 0 || res == EBUSY))
throw lock_exception();
return res == 0;
}
-inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+template<class TimePoint>
+inline bool posix_mutex::timed_lock(const TimePoint &abs_time)
{
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
//Posix does not support infinity absolute time so handle it here
- if(abs_time == boost::posix_time::pos_infin){
+ if(ipcdetail::is_pos_infinity(abs_time)){
this->lock();
return true;
}
- timespec ts = ptime_to_timespec(abs_time);
+ timespec ts = timepoint_to_timespec(abs_time);
int res = pthread_mutex_timedlock(&m_mut, &ts);
+ #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ if (res == EOWNERDEAD)
+ {
+ //We can't inform the application and data might
+ //corrupted, so be safe and mark the mutex as not recoverable
+ //so applications can act accordingly.
+ pthread_mutex_unlock(&m_mut);
+ throw lock_exception(not_recoverable);
+ }
+ else if (res == ENOTRECOVERABLE)
+ throw lock_exception(not_recoverable);
+ #endif
if (res != 0 && res != ETIMEDOUT)
throw lock_exception();
return res == 0;
@@ -128,8 +174,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
inline void posix_mutex::unlock()
{
- int res = 0;
- res = pthread_mutex_unlock(&m_mut);
+ int res = pthread_mutex_unlock(&m_mut);
(void)res;
BOOST_ASSERT(res == 0);
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/pthread_helpers.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/pthread_helpers.hpp
index c615c851eb..f247d5e596 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/pthread_helpers.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/pthread_helpers.hpp
@@ -41,8 +41,12 @@ namespace ipcdetail{
if(pthread_mutexattr_init(&m_attr)!=0 ||
pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 ||
(recursive &&
- pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 ))
- throw interprocess_exception("pthread_mutexattr_xxxx failed");
+ pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE) != 0 )
+ #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
+ || pthread_mutexattr_setrobust(&m_attr, PTHREAD_MUTEX_ROBUST) != 0
+ #endif
+ )
+ throw interprocess_exception("pthread_mutexattr_xxxx failed");
}
//!Destructor
@@ -144,7 +148,7 @@ namespace ipcdetail{
//!Constructor. Takes barrier attributes to initialize the barrier
barrier_initializer(pthread_barrier_t &mut,
pthread_barrierattr_t &mut_attr,
- int count)
+ unsigned int count)
: mp_barrier(&mut)
{
if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0)
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp
deleted file mode 100644
index 5aa09e0c19..0000000000
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2005-2012. 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)
-//
-// See http://www.boost.org/libs/interprocess for documentation.
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
-#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
-
-#ifndef BOOST_CONFIG_HPP
-# include <boost/config.hpp>
-#endif
-#
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-# pragma once
-#endif
-
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
-
-namespace boost {
-
-namespace interprocess {
-
-namespace ipcdetail {
-
-inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm)
-{
- const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
- //Avoid negative absolute times
- boost::posix_time::time_duration duration = (tm <= epoch) ? boost::posix_time::time_duration(epoch - epoch)
- : boost::posix_time::time_duration(tm - epoch);
- timespec ts;
- ts.tv_sec = duration.total_seconds();
- ts.tv_nsec = duration.total_nanoseconds() % 1000000000;
- return ts;
-}
-
-} //namespace ipcdetail {
-
-} //namespace interprocess {
-
-} //namespace boost {
-
-#endif //ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/timepoint_to_timespec.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/timepoint_to_timespec.hpp
new file mode 100644
index 0000000000..297fe8adf7
--- /dev/null
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/posix/timepoint_to_timespec.hpp
@@ -0,0 +1,87 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP
+#define BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
+
+namespace boost {
+
+namespace interprocess {
+
+namespace ipcdetail {
+
+template<class TimePoint>
+inline timespec timepoint_to_timespec ( const TimePoint &tm
+ , typename enable_if_ptime<TimePoint>::type * = 0)
+{
+ typedef typename TimePoint::date_type date_type;
+ typedef typename TimePoint::time_duration_type time_duration_type;
+
+ const TimePoint epoch(date_type(1970,1,1));
+
+ //Avoid negative absolute times
+ time_duration_type duration = (tm <= epoch) ? time_duration_type(epoch - epoch)
+ : time_duration_type(tm - epoch);
+ timespec ts;
+ ts.tv_sec = static_cast<time_t>(duration.total_seconds());
+ ts.tv_nsec = static_cast<long>(duration.total_nanoseconds() % 1000000000);
+ return ts;
+}
+
+inline timespec timepoint_to_timespec (const ustime &tm)
+{
+ timespec ts;
+ ts.tv_sec = static_cast<time_t>(tm.get_microsecs()/1000000u);
+ ts.tv_nsec = static_cast<long>((tm.get_microsecs()%1000000u)*1000u);
+ return ts;
+}
+
+template<class TimePoint>
+inline timespec timepoint_to_timespec ( const TimePoint &tm
+ , typename enable_if_time_point<TimePoint>::type * = 0)
+{
+ typedef typename TimePoint::duration duration_t;
+ duration_t d(tm.time_since_epoch());
+
+ timespec ts;
+ BOOST_IF_CONSTEXPR(duration_t::period::num == 1 && duration_t::period::den == 1000000000)
+ {
+ ts.tv_sec = static_cast<time_t>(d.count()/duration_t::period::den);
+ ts.tv_nsec = static_cast<long>(d.count()%duration_t::period::den);
+ }
+ else
+ {
+ const double factor = double(duration_t::period::num)/double(duration_t::period::den);
+ const double res = d.count()*factor;
+ ts.tv_sec = static_cast<time_t>(res);
+ ts.tv_nsec = static_cast<long>(res - double(ts.tv_sec));
+ }
+ return ts;
+}
+
+} //namespace ipcdetail {
+
+} //namespace interprocess {
+
+} //namespace boost {
+
+#endif //ifndef BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/scoped_lock.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/scoped_lock.hpp
index 97986f0361..35e1cc4cf7 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/scoped_lock.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/scoped_lock.hpp
@@ -32,7 +32,6 @@
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/move/utility_core.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/simple_swap.hpp>
//!\file
@@ -67,7 +66,7 @@ class scoped_lock
//!Effects: Default constructs a scoped_lock.
//!Postconditions: owns() == false and mutex() == 0.
- scoped_lock()
+ scoped_lock() BOOST_NOEXCEPT
: mp_mutex(0), m_locked(false)
{}
@@ -114,7 +113,8 @@ class scoped_lock
//! handles recursive locking depends upon the mutex. If the mutex_type
//! does not support try_lock, this constructor will fail at compile
//! time if instantiated, but otherwise have no effect.
- scoped_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
+ template<class TimePoint>
+ scoped_lock(mutex_type& m, const TimePoint& abs_time)
: mp_mutex(&m), m_locked(mp_mutex->timed_lock(abs_time))
{}
@@ -128,7 +128,7 @@ class scoped_lock
//! can be moved with the expression: "boost::move(lock);". This
//! constructor does not alter the state of the mutex, only potentially
//! who owns it.
- scoped_lock(BOOST_RV_REF(scoped_lock) scop)
+ scoped_lock(BOOST_RV_REF(scoped_lock) scop) BOOST_NOEXCEPT
: mp_mutex(0), m_locked(scop.owns())
{ mp_mutex = scop.release(); }
@@ -202,8 +202,8 @@ class scoped_lock
//! "write lock". If the "read lock" isn't held in the first place, the mutex
//! merely changes type to an unlocked "write lock". If the "read lock" is held,
//! then mutex transfer occurs only if it can do so in a non-blocking manner.
- template<class T>
- scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, boost::posix_time::ptime &abs_time
+ template<class T, class TimePoint>
+ scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, const TimePoint &abs_time
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
: mp_mutex(0), m_locked(false)
{
@@ -253,8 +253,8 @@ class scoped_lock
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
~scoped_lock()
{
- try{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
- catch(...){}
+ BOOST_TRY{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
+ BOOST_CATCH(...){} BOOST_CATCH_END
}
//!Effects: If owns() before the call, then unlock() is called on mutex().
@@ -307,7 +307,8 @@ class scoped_lock
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
- bool timed_lock(const boost::posix_time::ptime& abs_time)
+ template<class TimePoint>
+ bool timed_lock(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
@@ -315,6 +316,38 @@ class scoped_lock
return m_locked;
}
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls try_lock_until(abs_time) on the referenced mutex.
+ //!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
+ //!Notes: The scoped_lock changes from a state of not owning the mutex, to
+ //! owning the mutex, but only if it can obtain ownership by the specified
+ //! time. If the mutex_type does not support timed_lock (), this function
+ //! will fail at compile time if instantiated, but otherwise have no effect.*/
+ template<class TimePoint>
+ bool try_lock_until(const TimePoint& abs_time)
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->try_lock_until(abs_time);
+ return m_locked;
+ }
+
+ //!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
+ //! exception. Calls try_lock_until(abs_time) on the referenced mutex.
+ //!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
+ //!Notes: The scoped_lock changes from a state of not owning the mutex, to
+ //! owning the mutex, but only if it can obtain ownership by the specified
+ //! time. If the mutex_type does not support timed_lock (), this function
+ //! will fail at compile time if instantiated, but otherwise have no effect.*/
+ template<class Duration>
+ bool try_lock_for(const Duration& dur)
+ {
+ if(!mp_mutex || m_locked)
+ throw lock_exception();
+ m_locked = mp_mutex->try_lock_for(dur);
+ return m_locked;
+ }
+
//!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
//! exception. Calls unlock() on the referenced mutex.
//!Postconditions: owns() == false.
@@ -330,23 +363,23 @@ class scoped_lock
//!Effects: Returns true if this scoped_lock has acquired
//!the referenced mutex.
- bool owns() const
+ bool owns() const BOOST_NOEXCEPT
{ return m_locked && mp_mutex; }
//!Conversion to bool.
//!Returns owns().
- operator unspecified_bool_type() const
+ operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return m_locked? &this_type::m_locked : 0; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if
//!there is no mutex to reference.
- mutex_type* mutex() const
+ mutex_type* mutex() const BOOST_NOEXCEPT
{ return mp_mutex; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
//! mutex to reference.
//!Postconditions: mutex() == 0 and owns() == false.
- mutex_type* release()
+ mutex_type* release() BOOST_NOEXCEPT
{
mutex_type *mut = mp_mutex;
mp_mutex = 0;
@@ -356,7 +389,7 @@ class scoped_lock
//!Effects: Swaps state with moved lock.
//!Throws: Nothing.
- void swap( scoped_lock<mutex_type> &other)
+ void swap( scoped_lock<mutex_type> &other) BOOST_NOEXCEPT
{
(simple_swap)(mp_mutex, other.mp_mutex);
(simple_swap)(m_locked, other.m_locked);
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/condition.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/condition.hpp
index 1a1878b8ac..cf3a15970f 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/condition.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/condition.hpp
@@ -21,12 +21,14 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/spin/mutex.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/cstdint.hpp>
@@ -39,261 +41,253 @@ class spin_condition
{
spin_condition(const spin_condition &);
spin_condition &operator=(const spin_condition &);
+
public:
- spin_condition();
- ~spin_condition();
+ spin_condition()
+ {
+ //Note that this class is initialized to zero.
+ //So zeroed memory can be interpreted as an initialized
+ //condition variable
+ m_command = SLEEP;
+ m_num_waiters = 0;
+ }
+
+ ~spin_condition()
+ {
+ //Notify all waiting threads
+ //to allow POSIX semantics on condition destruction
+ this->notify_all();
+ }
- void notify_one();
- void notify_all();
+ void notify_one()
+ { this->notify(NOTIFY_ONE); }
+
+ void notify_all()
+ { this->notify(NOTIFY_ALL); }
template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
+ void wait(L& lock)
+ {
+ if (!lock)
+ throw lock_exception();
+ this->do_timed_wait_impl<false>(0, *lock.mutex());
+ }
+
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred)
+ {
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred())
+ this->do_timed_wait_impl<false>(0, *lock.mutex());
+ }
+
+ template <typename L, typename TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
//Handle infinity absolute time here to avoid complications in do_timed_wait
- if(abs_time == boost::posix_time::pos_infin){
+ if(is_pos_infinity(abs_time)){
this->wait(lock);
return true;
}
- return this->do_timed_wait(abs_time, *lock.mutex());
+ return this->do_timed_wait_impl<true>(abs_time, *lock.mutex());
}
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+ template <typename L, typename TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
//Handle infinity absolute time here to avoid complications in do_timed_wait
- if(abs_time == boost::posix_time::pos_infin){
+ if(is_pos_infinity(abs_time)){
this->wait(lock, pred);
return true;
}
while (!pred()){
- if (!this->do_timed_wait(abs_time, *lock.mutex()))
+ if (!this->do_timed_wait_impl<true>(abs_time, *lock.mutex()))
return pred();
}
return true;
}
- template <typename L>
- void wait(L& lock)
- {
- if (!lock)
- throw lock_exception();
- do_wait(*lock.mutex());
- }
-
- template <typename L, typename Pr>
- void wait(L& lock, Pr pred)
- {
- if (!lock)
- throw lock_exception();
+ template <typename L, class TimePoint>
+ cv_status wait_until(L& lock, const TimePoint &abs_time)
+ { return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
- while (!pred())
- do_wait(*lock.mutex());
- }
+ template <typename L, class TimePoint, typename Pr>
+ bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
+ { return this->timed_wait(lock, abs_time, pred); }
- template<class InterprocessMutex>
- void do_wait(InterprocessMutex &mut);
+ template <typename L, class Duration>
+ cv_status wait_for(L& lock, const Duration &dur)
+ { return this->wait_until(lock, duration_to_ustime(dur)); }
- template<class InterprocessMutex>
- bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ template <typename L, class Duration, typename Pr>
+ bool wait_for(L& lock, const Duration &dur, Pr pred)
+ { return this->wait_until(lock, duration_to_ustime(dur), pred); }
private:
- template<class InterprocessMutex>
- bool do_timed_wait(bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
-
- enum { SLEEP = 0, NOTIFY_ONE, NOTIFY_ALL };
- spin_mutex m_enter_mut;
- volatile boost::uint32_t m_command;
- volatile boost::uint32_t m_num_waiters;
- void notify(boost::uint32_t command);
-};
-inline spin_condition::spin_condition()
-{
- //Note that this class is initialized to zero.
- //So zeroed memory can be interpreted as an initialized
- //condition variable
- m_command = SLEEP;
- m_num_waiters = 0;
-}
-
-inline spin_condition::~spin_condition()
-{
- //Notify all waiting threads
- //to allow POSIX semantics on condition destruction
- this->notify_all();
-}
+ template<bool TimeoutEnabled, class InterprocessMutex, class TimePoint>
+ bool do_timed_wait_impl(const TimePoint &abs_time, InterprocessMutex &mut)
+ {
+ typedef boost::interprocess::scoped_lock<spin_mutex> InternalLock;
+ //The enter mutex guarantees that while executing a notification,
+ //no other thread can execute the do_timed_wait method.
+ {
+ //---------------------------------------------------------------
+ InternalLock lock;
+ get_lock(bool_<TimeoutEnabled>(), m_enter_mut, lock, abs_time);
+
+ if(!lock)
+ return false;
+ //---------------------------------------------------------------
+ //We increment the waiting thread count protected so that it will be
+ //always constant when another thread enters the notification logic.
+ //The increment marks this thread as "waiting on spin_condition"
+ atomic_inc32(const_cast<boost::uint32_t*>(&m_num_waiters));
+
+ //We unlock the external mutex atomically with the increment
+ mut.unlock();
+ }
-inline void spin_condition::notify_one()
-{
- this->notify(NOTIFY_ONE);
-}
+ //By default, we suppose that no timeout has happened
+ bool timed_out = false, unlock_enter_mut= false;
+
+ //Loop until a notification indicates that the thread should
+ //exit or timeout occurs
+ while(1){
+ //The thread sleeps/spins until a spin_condition commands a notification
+ //Notification occurred, we will lock the checking mutex so that
+ spin_wait swait;
+ while(atomic_read32(&m_command) == SLEEP){
+ swait.yield();
+
+ //Check for timeout
+ if(TimeoutEnabled){
+ TimePoint now = get_now<TimePoint>(bool_<TimeoutEnabled>());
+
+ if(now >= abs_time){
+ //If we can lock the mutex it means that no notification
+ //is being executed in this spin_condition variable
+ timed_out = m_enter_mut.try_lock();
+
+ //If locking fails, indicates that another thread is executing
+ //notification, so we play the notification game
+ if(!timed_out){
+ //There is an ongoing notification, we will try again later
+ continue;
+ }
+ //No notification in execution, since enter mutex is locked.
+ //We will execute time-out logic, so we will decrement count,
+ //release the enter mutex and return false.
+ break;
+ }
+ }
+ }
-inline void spin_condition::notify_all()
-{
- this->notify(NOTIFY_ALL);
-}
+ //If a timeout occurred, the mutex will not execute checking logic
+ if(TimeoutEnabled && timed_out){
+ //Decrement wait count
+ atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ unlock_enter_mut = true;
+ break;
+ }
+ else{
+ boost::uint32_t result = atomic_cas32
+ (const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ONE);
+ if(result == SLEEP){
+ //Other thread has been notified and since it was a NOTIFY one
+ //command, this thread must sleep again
+ continue;
+ }
+ else if(result == NOTIFY_ONE){
+ //If it was a NOTIFY_ONE command, only this thread should
+ //exit. This thread has atomically marked command as sleep before
+ //so no other thread will exit.
+ //Decrement wait count.
+ unlock_enter_mut = true;
+ atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ break;
+ }
+ else{
+ //If it is a NOTIFY_ALL command, all threads should return
+ //from do_timed_wait function. Decrement wait count.
+ unlock_enter_mut = 1 == atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
+ //Check if this is the last thread of notify_all waiters
+ //Only the last thread will release the mutex
+ if(unlock_enter_mut){
+ atomic_cas32(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ALL);
+ }
+ break;
+ }
+ }
+ }
-inline void spin_condition::notify(boost::uint32_t command)
-{
- //This mutex guarantees that no other thread can enter to the
- //do_timed_wait method logic, so that thread count will be
- //constant until the function writes a NOTIFY_ALL command.
- //It also guarantees that no other notification can be signaled
- //on this spin_condition before this one ends
- m_enter_mut.lock();
-
- //Return if there are no waiters
- if(!atomic_read32(&m_num_waiters)) {
- m_enter_mut.unlock();
- return;
- }
+ //Unlock the enter mutex if it is a single notification, if this is
+ //the last notified thread in a notify_all or a timeout has occurred
+ if(unlock_enter_mut){
+ m_enter_mut.unlock();
+ }
- //Notify that all threads should execute wait logic
- spin_wait swait;
- while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
- swait.yield();
+ //Lock external again before returning from the method
+ mut.lock();
+ return !timed_out;
}
- //The enter mutex will rest locked until the last waiting thread unlocks it
-}
-template<class InterprocessMutex>
-inline void spin_condition::do_wait(InterprocessMutex &mut)
-{
- this->do_timed_wait(false, boost::posix_time::ptime(), mut);
-}
+ template <class TimePoint>
+ static TimePoint get_now(bool_<true>)
+ { return microsec_clock<TimePoint>::universal_time(); }
-template<class InterprocessMutex>
-inline bool spin_condition::do_timed_wait
- (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{
- return this->do_timed_wait(true, abs_time, mut);
-}
+ template <class TimePoint>
+ static TimePoint get_now(bool_<false>)
+ { return TimePoint(); }
-template<class InterprocessMutex>
-inline bool spin_condition::do_timed_wait(bool tout_enabled,
- const boost::posix_time::ptime &abs_time,
- InterprocessMutex &mut)
-{
- boost::posix_time::ptime now = microsec_clock::universal_time();
+ template <class Mutex, class Lock, class TimePoint>
+ static void get_lock(bool_<true>, Mutex &m, Lock &lck, const TimePoint &abs_time)
+ {
+ Lock dummy(m, abs_time);
+ lck = boost::move(dummy);
+ }
- if(tout_enabled){
- if(now >= abs_time) return false;
+ template <class Mutex, class Lock, class TimePoint>
+ static void get_lock(bool_<false>, Mutex &m, Lock &lck, const TimePoint &)
+ {
+ Lock dummy(m);
+ lck = boost::move(dummy);
}
- typedef boost::interprocess::scoped_lock<spin_mutex> InternalLock;
- //The enter mutex guarantees that while executing a notification,
- //no other thread can execute the do_timed_wait method.
+ void notify(boost::uint32_t command)
{
- //---------------------------------------------------------------
- InternalLock lock;
- if(tout_enabled){
- InternalLock dummy(m_enter_mut, abs_time);
- lock = boost::move(dummy);
- }
- else{
- InternalLock dummy(m_enter_mut);
- lock = boost::move(dummy);
+ //This mutex guarantees that no other thread can enter to the
+ //do_timed_wait method logic, so that thread count will be
+ //constant until the function writes a NOTIFY_ALL command.
+ //It also guarantees that no other notification can be signaled
+ //on this spin_condition before this one ends
+ m_enter_mut.lock();
+
+ //Return if there are no waiters
+ if(!atomic_read32(&m_num_waiters)) {
+ m_enter_mut.unlock();
+ return;
}
- if(!lock)
- return false;
- //---------------------------------------------------------------
- //We increment the waiting thread count protected so that it will be
- //always constant when another thread enters the notification logic.
- //The increment marks this thread as "waiting on spin_condition"
- atomic_inc32(const_cast<boost::uint32_t*>(&m_num_waiters));
-
- //We unlock the external mutex atomically with the increment
- mut.unlock();
- }
-
- //By default, we suppose that no timeout has happened
- bool timed_out = false, unlock_enter_mut= false;
-
- //Loop until a notification indicates that the thread should
- //exit or timeout occurs
- while(1){
- //The thread sleeps/spins until a spin_condition commands a notification
- //Notification occurred, we will lock the checking mutex so that
+ //Notify that all threads should execute wait logic
spin_wait swait;
- while(atomic_read32(&m_command) == SLEEP){
+ while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
swait.yield();
-
- //Check for timeout
- if(tout_enabled){
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- //If we can lock the mutex it means that no notification
- //is being executed in this spin_condition variable
- timed_out = m_enter_mut.try_lock();
-
- //If locking fails, indicates that another thread is executing
- //notification, so we play the notification game
- if(!timed_out){
- //There is an ongoing notification, we will try again later
- continue;
- }
- //No notification in execution, since enter mutex is locked.
- //We will execute time-out logic, so we will decrement count,
- //release the enter mutex and return false.
- break;
- }
- }
- }
-
- //If a timeout occurred, the mutex will not execute checking logic
- if(tout_enabled && timed_out){
- //Decrement wait count
- atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
- unlock_enter_mut = true;
- break;
- }
- else{
- boost::uint32_t result = atomic_cas32
- (const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ONE);
- if(result == SLEEP){
- //Other thread has been notified and since it was a NOTIFY one
- //command, this thread must sleep again
- continue;
- }
- else if(result == NOTIFY_ONE){
- //If it was a NOTIFY_ONE command, only this thread should
- //exit. This thread has atomically marked command as sleep before
- //so no other thread will exit.
- //Decrement wait count.
- unlock_enter_mut = true;
- atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
- break;
- }
- else{
- //If it is a NOTIFY_ALL command, all threads should return
- //from do_timed_wait function. Decrement wait count.
- unlock_enter_mut = 1 == atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
- //Check if this is the last thread of notify_all waiters
- //Only the last thread will release the mutex
- if(unlock_enter_mut){
- atomic_cas32(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ALL);
- }
- break;
- }
}
+ //The enter mutex will rest locked until the last waiting thread unlocks it
}
- //Unlock the enter mutex if it is a single notification, if this is
- //the last notified thread in a notify_all or a timeout has occurred
- if(unlock_enter_mut){
- m_enter_mut.unlock();
- }
-
- //Lock external again before returning from the method
- mut.lock();
- return !timed_out;
-}
+ enum { SLEEP = 0, NOTIFY_ONE, NOTIFY_ALL };
+ spin_mutex m_enter_mut;
+ volatile boost::uint32_t m_command;
+ volatile boost::uint32_t m_num_waiters;
+};
} //namespace ipcdetail
} //namespace interprocess
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/mutex.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/mutex.hpp
index 7663673433..ce9f87fe79 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/mutex.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/spin/mutex.hpp
@@ -21,7 +21,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/assert.hpp>
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/cstdint.hpp>
@@ -43,11 +42,37 @@ class spin_mutex
void lock();
bool try_lock();
- bool timed_lock(const boost::posix_time::ptime &abs_time);
+ template<class TimePoint>
+ bool timed_lock(const TimePoint &abs_time);
+
+ template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
+ { return this->timed_lock(abs_time); }
+
+ template<class Duration> bool try_lock_for(const Duration &dur)
+ { return this->timed_lock(duration_to_ustime(dur)); }
+
void unlock();
- void take_ownership(){};
+ void take_ownership(){}
private:
volatile boost::uint32_t m_s;
+
+ struct common_lock_wrapper
+ {
+ common_lock_wrapper(spin_mutex &sp)
+ : m_sp(sp)
+ {}
+
+ void lock()
+ {
+ ipcdetail::try_based_lock(m_sp);
+ }
+
+ template<class TimePoint>
+ bool timed_lock(const TimePoint &abs_time)
+ { return m_sp.timed_lock(abs_time); }
+
+ spin_mutex &m_sp;
+ };
};
inline spin_mutex::spin_mutex()
@@ -64,7 +89,10 @@ inline spin_mutex::~spin_mutex()
}
inline void spin_mutex::lock(void)
-{ return ipcdetail::try_based_lock(*this); }
+{
+ common_lock_wrapper clw(*this);
+ ipcdetail::timeout_when_locking_aware_lock(clw);
+}
inline bool spin_mutex::try_lock(void)
{
@@ -72,7 +100,8 @@ inline bool spin_mutex::try_lock(void)
return m_s == 1 && prev_s == 0;
}
-inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+template<class TimePoint>
+inline bool spin_mutex::timed_lock(const TimePoint &abs_time)
{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
inline void spin_mutex::unlock(void)
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/condition.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/condition.hpp
index 58a43e25a5..255cb69c16 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/condition.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/condition.hpp
@@ -21,8 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -35,17 +35,17 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
-class windows_condition
+class winapi_condition
{
- windows_condition(const windows_condition &);
- windows_condition &operator=(const windows_condition &);
+ winapi_condition(const winapi_condition &);
+ winapi_condition &operator=(const winapi_condition &);
public:
- windows_condition()
+ winapi_condition()
: m_condition_data()
{}
- ~windows_condition()
+ ~winapi_condition()
{
//Notify all waiting threads
//to allow POSIX semantics on condition destruction
@@ -59,14 +59,6 @@ class windows_condition
{ m_condition_data.notify_all(); }
template <typename L>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
- { return m_condition_data.timed_wait(lock, abs_time); }
-
- template <typename L, typename Pr>
- bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
- { return m_condition_data.timed_wait(lock, abs_time, pred); }
-
- template <typename L>
void wait(L& lock)
{ m_condition_data.wait(lock); }
@@ -74,13 +66,38 @@ class windows_condition
void wait(L& lock, Pr pred)
{ m_condition_data.wait(lock, pred); }
+
+ template <typename L, typename TimePoint>
+ bool timed_wait(L& lock, const TimePoint &abs_time)
+ { return m_condition_data.timed_wait(lock, abs_time); }
+
+ template <typename L, typename TimePoint, typename Pr>
+ bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
+ { return m_condition_data.timed_wait(lock, abs_time, pred); }
+
+ template <typename L, class TimePoint>
+ cv_status wait_until(L& lock, const TimePoint &abs_time)
+ { return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
+
+ template <typename L, class TimePoint, typename Pr>
+ bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
+ { return this->timed_wait(lock, abs_time, pred); }
+
+ template <typename L, class Duration>
+ cv_status wait_for(L& lock, const Duration &dur)
+ { return this->wait_until(lock, duration_to_ustime(dur)); }
+
+ template <typename L, class Duration, typename Pr>
+ bool wait_for(L& lock, const Duration &dur, Pr pred)
+ { return this->wait_until(lock, duration_to_ustime(dur), pred); }
+
private:
struct condition_data
{
- typedef boost::int32_t integer_type;
- typedef windows_semaphore semaphore_type;
- typedef windows_mutex mutex_type;
+ typedef unsigned int integer_type;
+ typedef winapi_semaphore semaphore_type;
+ typedef winapi_mutex mutex_type;
condition_data()
: m_nwaiters_blocked(0)
@@ -109,12 +126,12 @@ class windows_condition
mutex_type &get_mtx_unblock_lock()
{ return m_mtx_unblock_lock; }
- boost::int32_t m_nwaiters_blocked;
- boost::int32_t m_nwaiters_gone;
- boost::int32_t m_nwaiters_to_unblock;
- windows_semaphore m_sem_block_queue;
- windows_semaphore m_sem_block_lock;
- windows_mutex m_mtx_unblock_lock;
+ integer_type m_nwaiters_blocked;
+ integer_type m_nwaiters_gone;
+ integer_type m_nwaiters_to_unblock;
+ semaphore_type m_sem_block_queue;
+ semaphore_type m_sem_block_lock;
+ mutex_type m_mtx_unblock_lock;
};
ipcdetail::condition_8a_wrapper<condition_data> m_condition_data;
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/mutex.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/mutex.hpp
index 4747d0cc66..e1bd190803 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/mutex.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/mutex.hpp
@@ -21,7 +21,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#include <boost/interprocess/sync/windows/sync_utils.hpp>
@@ -33,18 +32,25 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
-class windows_mutex
+class winapi_mutex
{
- windows_mutex(const windows_mutex &);
- windows_mutex &operator=(const windows_mutex &);
+ winapi_mutex(const winapi_mutex &);
+ winapi_mutex &operator=(const winapi_mutex &);
public:
- windows_mutex();
- ~windows_mutex();
+ winapi_mutex();
+ ~winapi_mutex();
void lock();
bool try_lock();
- bool timed_lock(const boost::posix_time::ptime &abs_time);
+ template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
+
+ template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
+ { return this->timed_lock(abs_time); }
+
+ template<class Duration> bool try_lock_for(const Duration &dur)
+ { return this->timed_lock(duration_to_ustime(dur)); }
+
void unlock();
void take_ownership(){};
@@ -52,60 +58,61 @@ class windows_mutex
const sync_id id_;
};
-inline windows_mutex::windows_mutex()
- : id_(this)
+inline winapi_mutex::winapi_mutex()
+ : id_()
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//Create mutex with the initial count
bool open_or_created;
- (void)handles.obtain_mutex(this->id_, &open_or_created);
+ (void)handles.obtain_mutex(this->id_, this, &open_or_created);
//The mutex must be created, never opened
BOOST_ASSERT(open_or_created);
BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
-inline windows_mutex::~windows_mutex()
+inline winapi_mutex::~winapi_mutex()
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
- handles.destroy_handle(this->id_);
+ handles.destroy_handle(this->id_, this);
}
-inline void windows_mutex::lock(void)
+inline void winapi_mutex::lock(void)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this));
mut.lock();
}
-inline bool windows_mutex::try_lock(void)
+inline bool winapi_mutex::try_lock(void)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this));
return mut.try_lock();
}
-inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+template<class TimePoint>
+inline bool winapi_mutex::timed_lock(const TimePoint &abs_time)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this));
return mut.timed_lock(abs_time);
}
-inline void windows_mutex::unlock(void)
+inline void winapi_mutex::unlock(void)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this));
return mut.unlock();
}
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/semaphore.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/semaphore.hpp
index 7a29d962e5..888ab71a0c 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/semaphore.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/semaphore.hpp
@@ -21,7 +21,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#include <boost/interprocess/sync/windows/sync_utils.hpp>
@@ -34,80 +33,83 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
-class windows_semaphore
+class winapi_semaphore
{
- windows_semaphore(const windows_semaphore &);
- windows_semaphore &operator=(const windows_semaphore &);
+ winapi_semaphore(const winapi_semaphore &);
+ winapi_semaphore &operator=(const winapi_semaphore &);
public:
- windows_semaphore(unsigned int initialCount);
- ~windows_semaphore();
+ winapi_semaphore(unsigned int initialCount);
+ ~winapi_semaphore();
- void post(long release_count = 1);
+ void post(unsigned int release_count = 1);
void wait();
bool try_wait();
- bool timed_wait(const boost::posix_time::ptime &abs_time);
+ template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
private:
const sync_id id_;
+ const unsigned initial_count_;
};
-inline windows_semaphore::windows_semaphore(unsigned int initialCount)
- : id_(this)
+inline winapi_semaphore::winapi_semaphore(unsigned int initialCount)
+ : id_(), initial_count_(initialCount)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//Force smeaphore creation with the initial count
bool open_or_created;
- handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
+ handles.obtain_semaphore(this->id_, this, initialCount, &open_or_created);
//The semaphore must be created, never opened
BOOST_ASSERT(open_or_created);
BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
(void)open_or_created;
}
-inline windows_semaphore::~windows_semaphore()
+inline winapi_semaphore::~winapi_semaphore()
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
- handles.destroy_handle(this->id_);
+ handles.destroy_handle(this->id_, this);
}
-inline void windows_semaphore::wait(void)
+inline void winapi_semaphore::wait()
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
sem.wait();
}
-inline bool windows_semaphore::try_wait(void)
+inline bool winapi_semaphore::try_wait()
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
return sem.try_wait();
}
-inline bool windows_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+template<class TimePoint>
+inline bool winapi_semaphore::timed_wait(const TimePoint &abs_time)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
//This can throw
- winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
return sem.timed_wait(abs_time);
}
-inline void windows_semaphore::post(long release_count)
+inline void winapi_semaphore::post(unsigned release_count)
{
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
- winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
- sem.post(release_count);
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
+ sem.post(static_cast<long>(release_count));
}
+
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/sync_utils.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/sync_utils.hpp
index 8e054660ca..04106318cf 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/sync_utils.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/sync_utils.hpp
@@ -30,11 +30,10 @@
//Shield against external warnings
#include <boost/interprocess/detail/config_external_begin.hpp>
- #include <boost/unordered/unordered_map.hpp>
+#include <boost/unordered/unordered_map.hpp>
#include <boost/interprocess/detail/config_external_end.hpp>
+#include <boost/container/flat_map.hpp>
-
-#include <boost/container/map.hpp>
#include <cstddef>
namespace boost {
@@ -63,16 +62,36 @@ inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *ou
return true;
}
+inline bool bytes_to_str(const void *mem, const std::size_t mem_length, wchar_t *out_str, std::size_t &out_length)
+{
+ const std::size_t need_mem = mem_length*2+1;
+ if(out_length < need_mem){
+ out_length = need_mem;
+ return false;
+ }
+
+ const wchar_t Characters [] =
+ { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
+ , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
+
+ std::size_t char_counter = 0;
+ const char *buf = (const char *)mem;
+ for(std::size_t i = 0; i != mem_length; ++i){
+ out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
+ out_str[char_counter++] = Characters[(buf[i]&0x0F)];
+ }
+ out_str[char_counter] = 0;
+ return true;
+}
+
class sync_id
{
public:
typedef __int64 internal_type;
- sync_id(const void *map_addr)
- : map_addr_(map_addr)
+ sync_id()
{ winapi::query_performance_counter(&rand_); }
- explicit sync_id(internal_type val, const void *map_addr)
- : map_addr_(map_addr)
+ explicit sync_id(internal_type val)
{ rand_ = val; }
const internal_type &internal_pod() const
@@ -81,18 +100,14 @@ class sync_id
internal_type &internal_pod()
{ return rand_; }
- const void *map_address() const
- { return map_addr_; }
-
friend std::size_t hash_value(const sync_id &m)
{ return boost::hash_value(m.rand_); }
friend bool operator==(const sync_id &l, const sync_id &r)
- { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; }
+ { return l.rand_ == r.rand_; }
private:
internal_type rand_;
- const void * const map_addr_;
};
class sync_handles
@@ -101,19 +116,15 @@ class sync_handles
enum type { MUTEX, SEMAPHORE };
private:
- struct address_less
- {
- bool operator()(sync_id const * const l, sync_id const * const r) const
- { return l->map_address() < r->map_address(); }
- };
+ //key: id -> mapped: HANDLE. Hash map to allow efficient sync operations
typedef boost::unordered_map<sync_id, void*> umap_type;
- typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> map_type;
+ //key: ordered address of the sync type -> iterator from umap_type. Ordered map to allow closing handles when unmapping
+ typedef boost::container::flat_map<const void*, umap_type::iterator> map_type;
static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
typedef char NameBuf[StrSize];
-
void fill_name(NameBuf &name, const sync_id &id)
{
const char *n = "Global\\boost.ipc";
@@ -129,7 +140,7 @@ class sync_handles
void throw_if_error(void *hnd_val)
{
if(!hnd_val){
- error_info err(winapi::get_last_error());
+ error_info err(static_cast<int>(winapi::get_last_error()));
throw interprocess_exception(err);
}
}
@@ -161,41 +172,57 @@ class sync_handles
}
public:
- void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
+ sync_handles()
+ : num_handles_()
+ {}
+
+ ~sync_handles()
+ {
+ BOOST_ASSERT(num_handles_ == 0); //Sanity check that handle we don't leak handles
+ }
+
+ void *obtain_mutex(const sync_id &id, const void *mapping_address, bool *popen_created = 0)
{
umap_type::value_type v(id, (void*)0);
scoped_lock<spin_mutex> lock(mtx_);
umap_type::iterator it = umap_.insert(v).first;
void *&hnd_val = it->second;
if(!hnd_val){
- map_[&it->first] = it;
+ BOOST_ASSERT(map_.find(mapping_address) == map_.end());
+ map_[mapping_address] = it;
hnd_val = open_or_create_mutex(id);
if(popen_created) *popen_created = true;
+ ++num_handles_;
}
else if(popen_created){
+ BOOST_ASSERT(map_.find(mapping_address) != map_.end());
*popen_created = false;
}
+
return hnd_val;
}
- void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
+ void *obtain_semaphore(const sync_id &id, const void *mapping_address, unsigned int initial_count, bool *popen_created = 0)
{
umap_type::value_type v(id, (void*)0);
scoped_lock<spin_mutex> lock(mtx_);
umap_type::iterator it = umap_.insert(v).first;
void *&hnd_val = it->second;
if(!hnd_val){
- map_[&it->first] = it;
+ BOOST_ASSERT(map_.find(mapping_address) == map_.end());
+ map_[mapping_address] = it;
hnd_val = open_or_create_semaphore(id, initial_count);
if(popen_created) *popen_created = true;
+ ++num_handles_;
}
else if(popen_created){
+ BOOST_ASSERT(map_.find(mapping_address) != map_.end());
*popen_created = false;
}
return hnd_val;
}
- void destroy_handle(const sync_id &id)
+ void destroy_handle(const sync_id &id, const void *mapping_address)
{
scoped_lock<spin_mutex> lock(mtx_);
umap_type::iterator it = umap_.find(id);
@@ -203,31 +230,39 @@ class sync_handles
if(it != itend){
winapi::close_handle(it->second);
- const map_type::key_type &k = &it->first;
- map_.erase(k);
+ --num_handles_;
+ std::size_t i = map_.erase(mapping_address);
+ (void)i;
+ BOOST_ASSERT(i == 1); //The entry should be there
umap_.erase(it);
}
}
void destroy_syncs_in_range(const void *addr, std::size_t size)
{
- const sync_id low_id(addr);
- const sync_id hig_id(static_cast<const char*>(addr)+size);
+ const void *low_id(addr);
+ const void *hig_id(static_cast<const char*>(addr)+size);
scoped_lock<spin_mutex> lock(mtx_);
- map_type::iterator itlow(map_.lower_bound(&low_id)),
- ithig(map_.lower_bound(&hig_id));
- while(itlow != ithig){
- void * const hnd = umap_[*itlow->first];
- winapi::close_handle(hnd);
- umap_.erase(*itlow->first);
- itlow = map_.erase(itlow);
+ map_type::iterator itlow(map_.lower_bound(low_id)),
+ ithig(map_.lower_bound(hig_id)),
+ it(itlow);
+ for (; it != ithig; ++it){
+ umap_type::iterator uit = it->second;
+ void * const hnd = uit->second;
+ umap_.erase(uit);
+ int ret = winapi::close_handle(hnd);
+ --num_handles_;
+ BOOST_ASSERT(ret != 0); (void)ret; //Sanity check that handle was ok
}
+
+ map_.erase(itlow, ithig);
}
private:
spin_mutex mtx_;
umap_type umap_;
map_type map_;
+ std::size_t num_handles_;
};
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
index 983e33571d..487571a50b 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
@@ -24,7 +24,6 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -57,7 +56,8 @@ class winapi_mutex_functions
bool try_lock()
{ return winapi_wrapper_try_wait_for_single_object(m_mtx_hnd); }
- bool timed_lock(const boost::posix_time::ptime &abs_time)
+ template<class TimePoint>
+ bool timed_lock(const TimePoint &abs_time)
{ return winapi_wrapper_timed_wait_for_single_object(m_mtx_hnd, abs_time); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
@@ -98,7 +98,8 @@ class winapi_mutex_wrapper
void *handle() const
{ return m_mtx_hnd; }
- bool open_or_create(const char *name, const permissions &perm)
+ template<class CharT>
+ bool open_or_create(const CharT *name, const permissions &perm)
{
if(m_mtx_hnd == 0){
m_mtx_hnd = winapi::open_or_create_mutex
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
index c98224f15d..b8580486af 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
@@ -24,7 +24,6 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -60,7 +59,8 @@ class winapi_semaphore_functions
bool try_wait()
{ return winapi_wrapper_try_wait_for_single_object(m_sem_hnd); }
- bool timed_wait(const boost::posix_time::ptime &abs_time)
+ template<class TimePoint>
+ bool timed_wait(const TimePoint &abs_time)
{ return winapi_wrapper_timed_wait_for_single_object(m_sem_hnd, abs_time); }
long value() const
@@ -115,7 +115,8 @@ class winapi_semaphore_wrapper
void *handle() const
{ return m_sem_hnd; }
- bool open_or_create( const char *name
+ template <class CharT>
+ bool open_or_create( const CharT *name
, long sem_count
, long max_count
, const permissions &perm
diff --git a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_wrapper_common.hpp b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_wrapper_common.hpp
index 428a26eb66..60794903de 100644
--- a/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_wrapper_common.hpp
+++ b/contrib/restricted/boost/interprocess/include/boost/interprocess/sync/windows/winapi_wrapper_common.hpp
@@ -22,70 +22,60 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
-#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/timed_utils.hpp>
#include <limits>
namespace boost {
namespace interprocess {
namespace ipcdetail {
-inline void winapi_wrapper_wait_for_single_object(void *handle)
-{
- unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time);
- if(ret != winapi::wait_object_0){
- if(ret != winapi::wait_abandoned){
- error_info err = system_error_code();
- throw interprocess_exception(err);
- }
- else{ //Special case for orphaned mutexes
- winapi::release_mutex(handle);
- throw interprocess_exception(owner_dead_error);
- }
- }
-}
-
-inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
+inline bool do_winapi_wait(void *handle, unsigned long dwMilliseconds)
{
- unsigned long ret = winapi::wait_for_single_object(handle, 0);
+ unsigned long ret = winapi::wait_for_single_object(handle, dwMilliseconds);
if(ret == winapi::wait_object_0){
return true;
}
else if(ret == winapi::wait_timeout){
return false;
}
+ else if(ret == winapi::wait_abandoned){ //Special case for orphaned mutexes
+ winapi::release_mutex(handle);
+ throw interprocess_exception(owner_dead_error);
+ }
else{
error_info err = system_error_code();
throw interprocess_exception(err);
}
}
-inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time)
+template<class TimePoint>
+inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const TimePoint &abs_time)
{
- //Windows does not support infinity abs_time so check it
- if(abs_time == boost::posix_time::pos_infin){
- winapi_wrapper_wait_for_single_object(handle);
- return true;
- }
- const boost::posix_time::ptime cur_time = microsec_clock::universal_time();
//Windows uses relative wait times so check for negative waits
//and implement as 0 wait to allow try-semantics as POSIX mandates.
- unsigned long ret = winapi::wait_for_single_object
- ( handle
- , (abs_time <= cur_time) ? 0u
- : (abs_time - cur_time).total_milliseconds()
- );
- if(ret == winapi::wait_object_0){
- return true;
- }
- else if(ret == winapi::wait_timeout){
- return false;
+ unsigned long time_ms = 0u;
+ if (ipcdetail::is_pos_infinity(abs_time)){
+ time_ms = winapi::infinite_time;
}
- else{
- error_info err = system_error_code();
- throw interprocess_exception(err);
+ else {
+ const TimePoint cur_time = microsec_clock<TimePoint>::universal_time();
+ if(abs_time > cur_time){
+ time_ms = static_cast<unsigned long>(duration_to_milliseconds(abs_time - cur_time));
+ }
}
+ return do_winapi_wait(handle, time_ms);
+}
+
+inline void winapi_wrapper_wait_for_single_object(void *handle)
+{
+ (void)do_winapi_wait(handle, winapi::infinite_time);
+}
+
+inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
+{
+ return do_winapi_wait(handle, 0u);
}
} //namespace ipcdetail {
@@ -94,4 +84,4 @@ inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boos
#include <boost/interprocess/detail/config_end.hpp>
-#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
+#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP
diff --git a/contrib/restricted/boost/move/include/boost/move/algo/adaptive_sort.hpp b/contrib/restricted/boost/move/include/boost/move/algo/adaptive_sort.hpp
new file mode 100644
index 0000000000..d1aa883cb1
--- /dev/null
+++ b/contrib/restricted/boost/move/include/boost/move/algo/adaptive_sort.hpp
@@ -0,0 +1,654 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ADAPTIVE_SORT_HPP
+#define BOOST_MOVE_ADAPTIVE_SORT_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+#include <boost/core/ignore_unused.hpp>
+
+#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+
+namespace boost {
+namespace movelib {
+
+///@cond
+namespace detail_adaptive {
+
+template<class RandIt>
+void move_data_backward( RandIt cur_pos
+ , typename iter_size<RandIt>::type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ }
+ else{
+ boost::adl_move_swap_ranges_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+template<class RandIt>
+void move_data_forward( RandIt cur_pos
+ , typename iter_size<RandIt>::type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move(cur_pos, cur_pos+l_data, new_pos);
+ }
+ else{
+ boost::adl_move_swap_ranges(cur_pos, cur_pos+l_data, new_pos);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+// build blocks of length 2*l_build_buf. l_build_buf is power of two
+// input: [0, l_build_buf) elements are buffer, rest unsorted elements
+// output: [0, l_build_buf) elements are buffer, blocks 2*l_build_buf and last subblock sorted
+//
+// First elements are merged from right to left until elements start
+// at first. All old elements [first, first + l_build_buf) are placed at the end
+// [first+len-l_build_buf, first+len). To achieve this:
+// - If we have external memory to merge, we save elements from the buffer
+// so that a non-swapping merge is used. Buffer elements are restored
+// at the end of the buffer from the external memory.
+//
+// - When the external memory is not available or it is insufficient
+// for a merge operation, left swap merging is used.
+//
+// Once elements are merged left to right in blocks of l_build_buf, then a single left
+// to right merge step is performed to achieve merged blocks of size 2K.
+// If external memory is available, usual merge is used, swap merging otherwise.
+//
+// As a last step, if auxiliary memory is available in-place merge is performed.
+// until all is merged or auxiliary memory is not large enough.
+template<class RandIt, class Compare, class XBuf>
+typename iter_size<RandIt>::type
+ adaptive_sort_build_blocks
+ ( RandIt const first
+ , typename iter_size<RandIt>::type const len
+ , typename iter_size<RandIt>::type const l_base
+ , typename iter_size<RandIt>::type const l_build_buf
+ , XBuf & xbuf
+ , Compare comp)
+{
+ typedef typename iter_size<RandIt>::type size_type;
+ BOOST_ASSERT(l_build_buf <= len);
+ BOOST_ASSERT(0 == ((l_build_buf / l_base)&(l_build_buf/l_base-1)));
+
+ //Place the start pointer after the buffer
+ RandIt first_block = first + l_build_buf;
+ size_type const elements_in_blocks = size_type(len - l_build_buf);
+
+ //////////////////////////////////
+ // Start of merge to left step
+ //////////////////////////////////
+ size_type l_merged = 0u;
+
+ BOOST_ASSERT(l_build_buf);
+ //If there is no enough buffer for the insertion sort step, just avoid the external buffer
+ size_type kbuf = min_value<size_type>(l_build_buf, size_type(xbuf.capacity()));
+ kbuf = kbuf < l_base ? 0 : kbuf;
+
+ if(kbuf){
+ //Backup internal buffer values in external buffer so they can be overwritten
+ xbuf.move_assign(first+l_build_buf-kbuf, kbuf);
+ l_merged = op_insertion_sort_step_left(first_block, elements_in_blocks, l_base, comp, move_op());
+
+ //Now combine them using the buffer. Elements from buffer can be
+ //overwritten since they've been saved to xbuf
+ l_merged = op_merge_left_step_multiple
+ ( first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, size_type(kbuf - l_merged), comp, move_op());
+
+ //Restore internal buffer from external buffer unless kbuf was l_build_buf,
+ //in that case restoration will happen later
+ if(kbuf != l_build_buf){
+ boost::move(xbuf.data()+kbuf-l_merged, xbuf.data() + kbuf, first_block-l_merged+elements_in_blocks);
+ }
+ }
+ else{
+ l_merged = insertion_sort_step(first_block, elements_in_blocks, l_base, comp);
+ rotate_gcd(first_block-l_merged, first_block, first_block+elements_in_blocks);
+ }
+
+ //Now combine elements using the buffer. Elements from buffer can't be
+ //overwritten since xbuf was not big enough, so merge swapping elements.
+ l_merged = op_merge_left_step_multiple
+ (first_block-l_merged, elements_in_blocks, l_merged, l_build_buf, size_type(l_build_buf - l_merged), comp, swap_op());
+
+ BOOST_ASSERT(l_merged == l_build_buf);
+
+ //////////////////////////////////
+ // Start of merge to right step
+ //////////////////////////////////
+
+ //If kbuf is l_build_buf then we can merge right without swapping
+ //Saved data is still in xbuf
+ if(kbuf && kbuf == l_build_buf){
+ op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, move_op());
+ //Restore internal buffer from external buffer if kbuf was l_build_buf.
+ //as this operation was previously delayed.
+ boost::move(xbuf.data(), xbuf.data() + kbuf, first);
+ }
+ else{
+ op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, swap_op());
+ }
+ xbuf.clear();
+ //2*l_build_buf or total already merged
+ return min_value<size_type>(elements_in_blocks, size_type(2u*l_build_buf));
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class XBuf>
+void adaptive_sort_combine_blocks
+ ( RandItKeys const keys
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iter_size<RandIt>::type const len
+ , typename iter_size<RandIt>::type const l_prev_merged
+ , typename iter_size<RandIt>::type const l_block
+ , bool const use_buf
+ , bool const xbuf_used
+ , XBuf & xbuf
+ , Compare comp
+ , bool merge_left)
+{
+ boost::ignore_unused(xbuf);
+ typedef typename iter_size<RandIt>::type size_type;
+
+ size_type const l_reg_combined = size_type(2u*l_prev_merged);
+ size_type l_irreg_combined = 0;
+ size_type const l_total_combined = calculate_total_combined(len, l_prev_merged, &l_irreg_combined);
+ size_type const n_reg_combined = len/l_reg_combined;
+ RandIt combined_first = first;
+
+ boost::ignore_unused(l_total_combined);
+ BOOST_ASSERT(l_total_combined <= len);
+
+ size_type const max_i = size_type(n_reg_combined + (l_irreg_combined != 0));
+
+ if(merge_left || !use_buf) {
+ for( size_type combined_i = 0; combined_i != max_i; ) {
+ //Now merge blocks
+ bool const is_last = combined_i==n_reg_combined;
+ size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
+
+ range_xbuf<RandIt, size_type, move_op> rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, key_comp, l_cur_combined
+ , l_prev_merged, l_block, rbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
+ if(!use_buf){
+ merge_blocks_bufferless
+ (keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp);
+ }
+ else{
+ merge_blocks_left
+ (keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_L: ", len + l_block);
+ ++combined_i;
+ if(combined_i != max_i)
+ combined_first += l_reg_combined;
+ }
+ }
+ else{
+ combined_first += size_type(l_reg_combined*(max_i-1u));
+ for( size_type combined_i = max_i; combined_i; ) {
+ --combined_i;
+ bool const is_last = combined_i==n_reg_combined;
+ size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
+
+ RandIt const combined_last(combined_first+l_cur_combined);
+ range_xbuf<RandIt, size_type, move_op> rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, key_comp, l_cur_combined
+ , l_prev_merged, l_block, rbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
+ merge_blocks_right
+ (keys, key_comp, combined_first, l_block, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_R: ", len + l_block);
+ if(combined_i)
+ combined_first -= l_reg_combined;
+ }
+ }
+}
+
+//Returns true if buffer is placed in
+//[buffer+len-l_intbuf, buffer+len). Otherwise, buffer is
+//[buffer,buffer+l_intbuf)
+template<class RandIt, class Compare, class XBuf>
+bool adaptive_sort_combine_all_blocks
+ ( RandIt keys
+ , typename iter_size<RandIt>::type &n_keys
+ , RandIt const buffer
+ , typename iter_size<RandIt>::type const l_buf_plus_data
+ , typename iter_size<RandIt>::type l_merged
+ , typename iter_size<RandIt>::type &l_intbuf
+ , XBuf & xbuf
+ , Compare comp)
+{
+ typedef typename iter_size<RandIt>::type size_type;
+
+ RandIt const first = buffer + l_intbuf;
+ size_type const l_data = size_type(l_buf_plus_data - l_intbuf);
+ size_type const l_unique = size_type(l_intbuf + n_keys);
+ //Backup data to external buffer once if possible
+ bool const common_xbuf = l_data > l_merged && l_intbuf && l_intbuf <= xbuf.capacity();
+ if(common_xbuf){
+ xbuf.move_assign(buffer, l_intbuf);
+ }
+
+ bool prev_merge_left = true;
+ size_type l_prev_total_combined = l_merged, l_prev_block = 0;
+ bool prev_use_internal_buf = true;
+
+ for( size_type n = 0; l_data > l_merged
+ ; l_merged = size_type(2u*l_merged)
+ , ++n){
+ //If l_intbuf is non-zero, use that internal buffer.
+ // Implies l_block == l_intbuf && use_internal_buf == true
+ //If l_intbuf is zero, see if half keys can be reused as a reduced emergency buffer,
+ // Implies l_block == n_keys/2 && use_internal_buf == true
+ //Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false)
+ bool use_internal_buf = false;
+ size_type const l_block = lblock_for_combine(l_intbuf, n_keys, size_type(2*l_merged), use_internal_buf);
+ BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf));
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) );
+
+ bool const is_merge_left = (n&1) == 0;
+ size_type const l_total_combined = calculate_total_combined(l_data, l_merged);
+ if(n && prev_use_internal_buf && prev_merge_left){
+ if(is_merge_left || !use_internal_buf){
+ move_data_backward(first-l_prev_block, l_prev_total_combined, first, common_xbuf);
+ }
+ else{
+ //Put the buffer just after l_total_combined
+ RandIt const buf_end = first+l_prev_total_combined;
+ RandIt const buf_beg = buf_end-l_block;
+ if(l_prev_total_combined > l_total_combined){
+ size_type const l_diff = size_type(l_prev_total_combined - l_total_combined);
+ move_data_backward(buf_beg-l_diff, l_diff, buf_end-l_diff, common_xbuf);
+ }
+ else if(l_prev_total_combined < l_total_combined){
+ size_type const l_diff = size_type(l_total_combined - l_prev_total_combined);
+ move_data_forward(buf_end, l_diff, buf_beg, common_xbuf);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After move_data : ", l_data + l_intbuf);
+ }
+
+ //Combine to form l_merged*2 segments
+ if(n_keys){
+ size_type upper_n_keys_this_iter = size_type(2u*l_merged/l_block);
+ if(upper_n_keys_this_iter > 256){
+ adaptive_sort_combine_blocks
+ ( keys, comp, !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ else{
+ unsigned char uint_keys[256];
+ adaptive_sort_combine_blocks
+ ( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ }
+ else{
+ size_type *const uint_keys = xbuf.template aligned_trailing<size_type>();
+ adaptive_sort_combine_blocks
+ ( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(is_merge_left ? " After comb blocks L: " : " After comb blocks R: ", l_data + l_intbuf);
+ prev_merge_left = is_merge_left;
+ l_prev_total_combined = l_total_combined;
+ l_prev_block = l_block;
+ prev_use_internal_buf = use_internal_buf;
+ }
+ BOOST_ASSERT(l_prev_total_combined == l_data);
+ bool const buffer_right = prev_use_internal_buf && prev_merge_left;
+
+ l_intbuf = prev_use_internal_buf ? l_prev_block : 0u;
+ n_keys = size_type(l_unique - l_intbuf);
+ //Restore data from to external common buffer if used
+ if(common_xbuf){
+ if(buffer_right){
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer+l_data);
+ }
+ else{
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer);
+ }
+ }
+ return buffer_right;
+}
+
+
+template<class RandIt, class Compare, class XBuf>
+void adaptive_sort_final_merge( bool buffer_right
+ , RandIt const first
+ , typename iter_size<RandIt>::type const l_intbuf
+ , typename iter_size<RandIt>::type const n_keys
+ , typename iter_size<RandIt>::type const len
+ , XBuf & xbuf
+ , Compare comp)
+{
+ //BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
+ xbuf.clear();
+
+ typedef typename iter_size<RandIt>::type size_type;
+
+ size_type const n_key_plus_buf = size_type(l_intbuf+n_keys);
+ if(buffer_right){
+ //Use stable sort as some buffer elements might not be unique (see non_unique_buf)
+ stable_sort(first+len-l_intbuf, first+len, comp, xbuf);
+ stable_merge( first+n_keys, first+len-l_intbuf, first+len, antistable<Compare>(comp), xbuf);
+ unstable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ //Use stable sort as some buffer elements might not be unique (see non_unique_buf)
+ stable_sort(first, first+n_key_plus_buf, comp, xbuf);
+ if(xbuf.capacity() >= n_key_plus_buf){
+ buffered_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
+ }
+ else if(xbuf.capacity() >= min_value<size_type>(l_intbuf, n_keys)){
+ stable_merge( first+n_keys, first+n_key_plus_buf
+ , first+len, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ stable_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" After final_merge : ", len);
+}
+
+template<class RandIt, class Compare, class Unsigned, class XBuf>
+bool adaptive_sort_build_params
+ (RandIt first, Unsigned const len, Compare comp
+ , Unsigned &n_keys, Unsigned &l_intbuf, Unsigned &l_base, Unsigned &l_build_buf
+ , XBuf & xbuf
+ )
+{
+ typedef typename iter_size<RandIt>::type size_type;
+
+ //Calculate ideal parameters and try to collect needed unique keys
+ l_base = 0u;
+
+ //Try to find a value near sqrt(len) that is 2^N*l_base where
+ //l_base <= AdaptiveSortInsertionSortThreshold. This property is important
+ //as build_blocks merges to the left iteratively duplicating the
+ //merged size and all the buffer must be used just before the final
+ //merge to right step. This guarantees "build_blocks" produces
+ //segments of size l_build_buf*2, maximizing the classic merge phase.
+ l_intbuf = size_type(ceil_sqrt_multiple(len, &l_base));
+
+ //The internal buffer can be expanded if there is enough external memory
+ while(xbuf.capacity() >= l_intbuf*2){
+ l_intbuf = size_type(2u*l_intbuf);
+ }
+
+ //This is the minimum number of keys to implement the ideal algorithm
+ //
+ //l_intbuf is used as buffer plus the key count
+ size_type n_min_ideal_keys = size_type(l_intbuf-1u);
+ while(n_min_ideal_keys >= (len-l_intbuf-n_min_ideal_keys)/l_intbuf){
+ --n_min_ideal_keys;
+ }
+ ++n_min_ideal_keys;
+ BOOST_ASSERT(n_min_ideal_keys <= l_intbuf);
+
+ if(xbuf.template supports_aligned_trailing<size_type>
+ (l_intbuf, size_type((size_type(len-l_intbuf)-1u)/l_intbuf+1u))){
+ n_keys = 0u;
+ l_build_buf = l_intbuf;
+ }
+ else{
+ //Try to achieve a l_build_buf of length l_intbuf*2, so that we can merge with that
+ //l_intbuf*2 buffer in "build_blocks" and use half of them as buffer and the other half
+ //as keys in combine_all_blocks. In that case n_keys >= n_min_ideal_keys but by a small margin.
+ //
+ //If available memory is 2*sqrt(l), then only sqrt(l) unique keys are needed,
+ //(to be used for keys in combine_all_blocks) as the whole l_build_buf
+ //will be backuped in the buffer during build_blocks.
+ bool const non_unique_buf = xbuf.capacity() >= l_intbuf;
+ size_type const to_collect = non_unique_buf ? n_min_ideal_keys : size_type(l_intbuf*2u);
+ size_type collected = collect_unique(first, first+len, to_collect, comp, xbuf);
+
+ //If available memory is 2*sqrt(l), then for "build_params"
+ //the situation is the same as if 2*l_intbuf were collected.
+ if(non_unique_buf && collected == n_min_ideal_keys){
+ l_build_buf = l_intbuf;
+ n_keys = n_min_ideal_keys;
+ }
+ else if(collected == 2*l_intbuf){
+ //l_intbuf*2 elements found. Use all of them in the build phase
+ l_build_buf = size_type(l_intbuf*2);
+ n_keys = l_intbuf;
+ }
+ else if(collected >= (n_min_ideal_keys+l_intbuf)){
+ l_build_buf = l_intbuf;
+ n_keys = size_type(collected - l_intbuf);
+ }
+ //If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix
+ //is possible (due to very low unique keys), then go to a slow sort based on rotations.
+ else{
+ BOOST_ASSERT(collected < (n_min_ideal_keys+l_intbuf));
+ if(collected < 4){ //No combination possible with less that 4 keys
+ return false;
+ }
+ n_keys = l_intbuf;
+ while(n_keys & (n_keys-1u)){
+ n_keys &= size_type(n_keys-1u); // make it power or 2
+ }
+ while(n_keys > collected){
+ n_keys/=2;
+ }
+ //AdaptiveSortInsertionSortThreshold is always power of two so the minimum is power of two
+ l_base = min_value<Unsigned>(n_keys, AdaptiveSortInsertionSortThreshold);
+ l_intbuf = 0;
+ l_build_buf = n_keys;
+ }
+ BOOST_ASSERT((n_keys+l_intbuf) >= l_build_buf);
+ }
+
+ return true;
+}
+
+// Main explanation of the sort algorithm.
+//
+// csqrtlen = ceil(sqrt(len));
+//
+// * First, 2*csqrtlen unique elements elements are extracted from elements to be
+// sorted and placed in the beginning of the range.
+//
+// * Step "build_blocks": In this nearly-classic merge step, 2*csqrtlen unique elements
+// will be used as auxiliary memory, so trailing len-2*csqrtlen elements are
+// are grouped in blocks of sorted 4*csqrtlen elements. At the end of the step
+// 2*csqrtlen unique elements are again the leading elements of the whole range.
+//
+// * Step "combine_blocks": pairs of previously formed blocks are merged with a different
+// ("smart") algorithm to form blocks of 8*csqrtlen elements. This step is slower than the
+// "build_blocks" step and repeated iteratively (forming blocks of 16*csqrtlen, 32*csqrtlen
+// elements, etc) of until all trailing (len-2*csqrtlen) elements are merged.
+//
+// In "combine_blocks" len/csqrtlen elements used are as "keys" (markers) to
+// know if elements belong to the first or second block to be merged and another
+// leading csqrtlen elements are used as buffer. Explanation of the "combine_blocks" step:
+//
+// Iteratively until all trailing (len-2*csqrtlen) elements are merged:
+// Iteratively for each pair of previously merged block:
+// * Blocks are divided groups of csqrtlen elements and
+// 2*merged_block/csqrtlen keys are sorted to be used as markers
+// * Groups are selection-sorted by first or last element (depending whether they are going
+// to be merged to left or right) and keys are reordered accordingly as an imitation-buffer.
+// * Elements of each block pair are merged using the csqrtlen buffer taking into account
+// if they belong to the first half or second half (marked by the key).
+//
+// * In the final merge step leading elements (2*csqrtlen) are sorted and merged with
+// rotations with the rest of sorted elements in the "combine_blocks" step.
+//
+// Corner cases:
+//
+// * If no 2*csqrtlen elements can be extracted:
+//
+// * If csqrtlen+len/csqrtlen are extracted, then only csqrtlen elements are used
+// as buffer in the "build_blocks" step forming blocks of 2*csqrtlen elements. This
+// means that an additional "combine_blocks" step will be needed to merge all elements.
+//
+// * If no csqrtlen+len/csqrtlen elements can be extracted, but still more than a minimum,
+// then reduces the number of elements used as buffer and keys in the "build_blocks"
+// and "combine_blocks" steps. If "combine_blocks" has no enough keys due to this reduction
+// then uses a rotation based smart merge.
+//
+// * If the minimum number of keys can't be extracted, a rotation-based sorting is performed.
+//
+// * If auxiliary memory is more or equal than ceil(len/2), half-copying mergesort is used.
+//
+// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
+// then only csqrtlen elements need to be extracted and "combine_blocks" will use integral
+// keys to combine blocks.
+//
+// * If auxiliary memory is available, the "build_blocks" will be extended to build bigger blocks
+// using classic merge and "combine_blocks" will use bigger blocks when merging.
+template<class RandIt, class Compare, class XBuf>
+void adaptive_sort_impl
+ ( RandIt first
+ , typename iter_size<RandIt>::type const len
+ , Compare comp
+ , XBuf & xbuf
+ )
+{
+ typedef typename iter_size<RandIt>::type size_type;
+
+ //Small sorts go directly to insertion sort
+ if(len <= size_type(AdaptiveSortInsertionSortThreshold)){
+ insertion_sort(first, first + len, comp);
+ }
+ else if((len-len/2) <= xbuf.capacity()){
+ merge_sort(first, first+len, comp, xbuf.data());
+ }
+ else{
+ //Make sure it is at least four
+ BOOST_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
+
+ size_type l_base = 0;
+ size_type l_intbuf = 0;
+ size_type n_keys = 0;
+ size_type l_build_buf = 0;
+
+ //Calculate and extract needed unique elements. If a minimum is not achieved
+ //fallback to a slow stable sort
+ if(!adaptive_sort_build_params(first, len, comp, n_keys, l_intbuf, l_base, l_build_buf, xbuf)){
+ stable_sort(first, first+len, comp, xbuf);
+ }
+ else{
+ BOOST_ASSERT(l_build_buf);
+ //Otherwise, continue the adaptive_sort
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1("\n After collect_unique: ", len);
+ size_type const n_key_plus_buf = size_type(l_intbuf+n_keys);
+ //l_build_buf is always power of two if l_intbuf is zero
+ BOOST_ASSERT(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
+
+ //Classic merge sort until internal buffer and xbuf are exhausted
+ size_type const l_merged = adaptive_sort_build_blocks
+ ( first + n_key_plus_buf-l_build_buf
+ , size_type(len-n_key_plus_buf+l_build_buf)
+ , l_base, l_build_buf, xbuf, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" After build_blocks: ", len);
+
+ //Non-trivial merge
+ bool const buffer_right = adaptive_sort_combine_all_blocks
+ (first, n_keys, first+n_keys, size_type(len-n_keys), l_merged, l_intbuf, xbuf, comp);
+
+ //Sort keys and buffer and merge the whole sequence
+ adaptive_sort_final_merge(buffer_right, first, l_intbuf, n_keys, len, xbuf, comp);
+ }
+ }
+}
+
+} //namespace detail_adaptive {
+
+///@endcond
+
+//! <b>Effects</b>: Sorts the elements in the range [first, last) in ascending order according
+//! to comparison functor "comp". The sort is stable (order of equal elements
+//! is guaranteed to be preserved). Performance is improved if additional raw storage is
+//! provided.
+//!
+//! <b>Requires</b>:
+//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
+//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
+//!
+//! <b>Parameters</b>:
+//! - first, last: the range of elements to sort
+//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
+//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
+//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
+//! is ceil(std::distance(first, last)/2).
+//!
+//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
+//! of dereferenced RandIt throws.
+//!
+//! <b>Complexity</b>: Always K x O(Nxlog(N)) comparisons and move assignments/constructors/swaps.
+//! Comparisons are close to minimum even with no additional memory. Constant factor for data movement is minimized
+//! when uninitialized_len is ceil(std::distance(first, last)/2). Pretty good enough performance is achieved when
+//! ceil(sqrt(std::distance(first, last)))*2.
+//!
+//! <b>Caution</b>: Experimental implementation, not production-ready.
+template<class RandIt, class RandRawIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp
+ , RandRawIt uninitialized
+ , typename iter_size<RandIt>::type uninitialized_len)
+{
+ typedef typename iter_size<RandIt>::type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ ::boost::movelib::adaptive_xbuf<value_type, RandRawIt, size_type> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
+}
+
+template<class RandIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ adaptive_sort(first, last, comp, (value_type*)0, 0u);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
+#pragma GCC diagnostic pop
+#endif
+
+#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
diff --git a/contrib/restricted/boost/move/include/boost/move/algo/detail/pdqsort.hpp b/contrib/restricted/boost/move/include/boost/move/algo/detail/pdqsort.hpp
new file mode 100644
index 0000000000..640f8a3d1b
--- /dev/null
+++ b/contrib/restricted/boost/move/include/boost/move/algo/detail/pdqsort.hpp
@@ -0,0 +1,344 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Orson Peters 2017.
+// (C) Copyright Ion Gaztanaga 2017-2018.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This implementation of Pattern-defeating quicksort (pdqsort) was written
+// by Orson Peters, and discussed in the Boost mailing list:
+// http://boost.2283326.n4.nabble.com/sort-pdqsort-td4691031.html
+//
+// This implementation is the adaptation by Ion Gaztanaga of code originally in GitHub
+// with permission from the author to relicense it under the Boost Software License
+// (see the Boost mailing list for details).
+//
+// The original copyright statement is pasted here for completeness:
+//
+// pdqsort.h - Pattern-defeating quicksort.
+// Copyright (c) 2015 Orson Peters
+// This software is provided 'as-is', without any express or implied warranty. In no event will the
+// authors be held liable for any damages arising from the use of this software.
+// Permission is granted to anyone to use this software for any purpose, including commercial
+// applications, and to alter it and redistribute it freely, subject to the following restrictions:
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the
+// original software. If you use this software in a product, an acknowledgment in the product
+// documentation would be appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
+// being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ALGO_PDQSORT_HPP
+#define BOOST_MOVE_ALGO_PDQSORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <boost/move/algo/detail/heap_sort.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+
+#include <boost/move/adl_move_swap.hpp>
+#include <cstddef>
+
+#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+
+namespace boost {
+namespace movelib {
+
+namespace pdqsort_detail {
+
+ //A simple pair implementation to avoid including <utility>
+ template<class T1, class T2>
+ struct pair
+ {
+ pair()
+ {}
+
+ pair(const T1 &t1, const T2 &t2)
+ : first(t1), second(t2)
+ {}
+
+ T1 first;
+ T2 second;
+ };
+
+ enum {
+ // Partitions below this size are sorted using insertion sort.
+ insertion_sort_threshold = 24,
+
+ // Partitions above this size use Tukey's ninther to select the pivot.
+ ninther_threshold = 128,
+
+ // When we detect an already sorted partition, attempt an insertion sort that allows this
+ // amount of element moves before giving up.
+ partial_insertion_sort_limit = 8,
+
+ // Must be multiple of 8 due to loop unrolling, and < 256 to fit in unsigned char.
+ block_size = 64,
+
+ // Cacheline size, assumes power of two.
+ cacheline_size = 64
+
+ };
+
+ // Returns floor(log2(n)), assumes n > 0.
+ template<class Unsigned>
+ Unsigned log2(Unsigned n) {
+ Unsigned log = 0;
+ while (n >>= 1) ++log;
+ return log;
+ }
+
+ // Attempts to use insertion sort on [begin, end). Will return false if more than
+ // partial_insertion_sort_limit elements were moved, and abort sorting. Otherwise it will
+ // successfully sort and return true.
+ template<class Iter, class Compare>
+ inline bool partial_insertion_sort(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+ typedef typename boost::movelib:: iter_size<Iter>::type size_type;
+ if (begin == end) return true;
+
+ size_type limit = 0;
+ for (Iter cur = begin + 1; cur != end; ++cur) {
+ if (limit > partial_insertion_sort_limit) return false;
+
+ Iter sift = cur;
+ Iter sift_1 = cur - 1;
+
+ // Compare first so we can avoid 2 moves for an element already positioned correctly.
+ if (comp(*sift, *sift_1)) {
+ T tmp = boost::move(*sift);
+
+ do { *sift-- = boost::move(*sift_1); }
+ while (sift != begin && comp(tmp, *--sift_1));
+
+ *sift = boost::move(tmp);
+ limit += size_type(cur - sift);
+ }
+ }
+
+ return true;
+ }
+
+ template<class Iter, class Compare>
+ inline void sort2(Iter a, Iter b, Compare comp) {
+ if (comp(*b, *a)) boost::adl_move_iter_swap(a, b);
+ }
+
+ // Sorts the elements *a, *b and *c using comparison function comp.
+ template<class Iter, class Compare>
+ inline void sort3(Iter a, Iter b, Iter c, Compare comp) {
+ sort2(a, b, comp);
+ sort2(b, c, comp);
+ sort2(a, b, comp);
+ }
+
+ // Partitions [begin, end) around pivot *begin using comparison function comp. Elements equal
+ // to the pivot are put in the right-hand partition. Returns the position of the pivot after
+ // partitioning and whether the passed sequence already was correctly partitioned. Assumes the
+ // pivot is a median of at least 3 elements and that [begin, end) is at least
+ // insertion_sort_threshold long.
+ template<class Iter, class Compare>
+ pdqsort_detail::pair<Iter, bool> partition_right(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+
+ // Move pivot into local for speed.
+ T pivot(boost::move(*begin));
+
+ Iter first = begin;
+ Iter last = end;
+
+ // Find the first element greater than or equal than the pivot (the median of 3 guarantees
+ // this exists).
+ while (comp(*++first, pivot));
+
+ // Find the first element strictly smaller than the pivot. We have to guard this search if
+ // there was no element before *first.
+ if (first - 1 == begin) while (first < last && !comp(*--last, pivot));
+ else while ( !comp(*--last, pivot));
+
+ // If the first pair of elements that should be swapped to partition are the same element,
+ // the passed in sequence already was correctly partitioned.
+ bool already_partitioned = first >= last;
+
+ // Keep swapping pairs of elements that are on the wrong side of the pivot. Previously
+ // swapped pairs guard the searches, which is why the first iteration is special-cased
+ // above.
+ while (first < last) {
+ boost::adl_move_iter_swap(first, last);
+ while (comp(*++first, pivot));
+ while (!comp(*--last, pivot));
+ }
+
+ // Put the pivot in the right place.
+ Iter pivot_pos = first - 1;
+ *begin = boost::move(*pivot_pos);
+ *pivot_pos = boost::move(pivot);
+
+ return pdqsort_detail::pair<Iter, bool>(pivot_pos, already_partitioned);
+ }
+
+ // Similar function to the one above, except elements equal to the pivot are put to the left of
+ // the pivot and it doesn't check or return if the passed sequence already was partitioned.
+ // Since this is rarely used (the many equal case), and in that case pdqsort already has O(n)
+ // performance, no block quicksort is applied here for simplicity.
+ template<class Iter, class Compare>
+ inline Iter partition_left(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+
+ T pivot(boost::move(*begin));
+ Iter first = begin;
+ Iter last = end;
+
+ while (comp(pivot, *--last));
+
+ if (last + 1 == end) while (first < last && !comp(pivot, *++first));
+ else while ( !comp(pivot, *++first));
+
+ while (first < last) {
+ boost::adl_move_iter_swap(first, last);
+ while (comp(pivot, *--last));
+ while (!comp(pivot, *++first));
+ }
+
+ Iter pivot_pos = last;
+ *begin = boost::move(*pivot_pos);
+ *pivot_pos = boost::move(pivot);
+
+ return pivot_pos;
+ }
+
+
+ template<class Iter, class Compare>
+ void pdqsort_loop( Iter begin, Iter end, Compare comp
+ , typename boost::movelib:: iter_size<Iter>::type bad_allowed
+ , bool leftmost = true)
+ {
+ typedef typename boost::movelib:: iter_size<Iter>::type size_type;
+
+ // Use a while loop for tail recursion elimination.
+ while (true) {
+ size_type size = size_type(end - begin);
+
+ // Insertion sort is faster for small arrays.
+ if (size < insertion_sort_threshold) {
+ insertion_sort(begin, end, comp);
+ return;
+ }
+
+ // Choose pivot as median of 3 or pseudomedian of 9.
+ size_type s2 = size / 2;
+ if (size > ninther_threshold) {
+ sort3(begin, begin + s2, end - 1, comp);
+ sort3(begin + 1, begin + (s2 - 1), end - 2, comp);
+ sort3(begin + 2, begin + (s2 + 1), end - 3, comp);
+ sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp);
+ boost::adl_move_iter_swap(begin, begin + s2);
+ } else sort3(begin + s2, begin, end - 1, comp);
+
+ // If *(begin - 1) is the end of the right partition of a previous partition operation
+ // there is no element in [begin, end) that is smaller than *(begin - 1). Then if our
+ // pivot compares equal to *(begin - 1) we change strategy, putting equal elements in
+ // the left partition, greater elements in the right partition. We do not have to
+ // recurse on the left partition, since it's sorted (all equal).
+ if (!leftmost && !comp(*(begin - 1), *begin)) {
+ begin = partition_left(begin, end, comp) + 1;
+ continue;
+ }
+
+ // Partition and get results.
+ pdqsort_detail::pair<Iter, bool> part_result = partition_right(begin, end, comp);
+ Iter pivot_pos = part_result.first;
+ bool already_partitioned = part_result.second;
+
+ // Check for a highly unbalanced partition.
+ size_type l_size = size_type(pivot_pos - begin);
+ size_type r_size = size_type(end - (pivot_pos + 1));
+ bool highly_unbalanced = l_size < size / 8 || r_size < size / 8;
+
+ // If we got a highly unbalanced partition we shuffle elements to break many patterns.
+ if (highly_unbalanced) {
+ // If we had too many bad partitions, switch to heapsort to guarantee O(n log n).
+ if (--bad_allowed == 0) {
+ boost::movelib::heap_sort(begin, end, comp);
+ return;
+ }
+
+ if (l_size >= insertion_sort_threshold) {
+ boost::adl_move_iter_swap(begin, begin + l_size / 4);
+ boost::adl_move_iter_swap(pivot_pos - 1, pivot_pos - l_size / 4);
+
+ if (l_size > ninther_threshold) {
+ boost::adl_move_iter_swap(begin + 1, begin + (l_size / 4 + 1));
+ boost::adl_move_iter_swap(begin + 2, begin + (l_size / 4 + 2));
+ boost::adl_move_iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1));
+ boost::adl_move_iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2));
+ }
+ }
+
+ if (r_size >= insertion_sort_threshold) {
+ boost::adl_move_iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4));
+ boost::adl_move_iter_swap(end - 1, end - r_size / 4);
+
+ if (r_size > ninther_threshold) {
+ boost::adl_move_iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4));
+ boost::adl_move_iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4));
+ boost::adl_move_iter_swap(end - 2, end - (1 + r_size / 4));
+ boost::adl_move_iter_swap(end - 3, end - (2 + r_size / 4));
+ }
+ }
+ } else {
+ // If we were decently balanced and we tried to sort an already partitioned
+ // sequence try to use insertion sort.
+ if (already_partitioned && partial_insertion_sort(begin, pivot_pos, comp)
+ && partial_insertion_sort(pivot_pos + 1, end, comp)) return;
+ }
+
+ // Sort the left partition first using recursion and do tail recursion elimination for
+ // the right-hand partition.
+ pdqsort_loop<Iter, Compare>(begin, pivot_pos, comp, bad_allowed, leftmost);
+ begin = pivot_pos + 1;
+ leftmost = false;
+ }
+ }
+}
+
+
+template<class Iter, class Compare>
+void pdqsort(Iter begin, Iter end, Compare comp)
+{
+ if (begin == end) return;
+ typedef typename boost::movelib:: iter_size<Iter>::type size_type;
+ pdqsort_detail::pdqsort_loop<Iter, Compare>(begin, end, comp, pdqsort_detail::log2(size_type(end - begin)));
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
+#pragma GCC diagnostic pop
+#endif
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //BOOST_MOVE_ALGO_PDQSORT_HPP
diff --git a/contrib/restricted/boost/python/README.md b/contrib/restricted/boost/python/README.md
index c692bb8a66..f57b97505a 100644
--- a/contrib/restricted/boost/python/README.md
+++ b/contrib/restricted/boost/python/README.md
@@ -2,6 +2,8 @@
# Synopsis
+[![Join the chat at https://gitter.im/boostorg/python](https://badges.gitter.im/boostorg/python.svg)](https://gitter.im/boostorg/python?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
Welcome to Boost.Python, a C++ library which enables seamless interoperability between C++ and the Python programming language. The library includes support for:
* References and Pointers
@@ -19,7 +21,7 @@ See the [Boost.Python](http://boostorg.github.io/python) documentation for detai
**Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress.
-# Building ![Build Status](https://travis-ci.org/boostorg/python.svg?branch=develop)
+# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) ![Test Windows](https://github.com/boostorg/python/workflows/Test%20Windows/badge.svg)
While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package.
diff --git a/contrib/restricted/boost/python/include/boost/python/call.hpp b/contrib/restricted/boost/python/include/boost/python/call.hpp
index 5d2d7d2341..c057ee9a12 100644
--- a/contrib/restricted/boost/python/include/boost/python/call.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/call.hpp
@@ -60,7 +60,7 @@ call(PyObject* callable
)
{
PyObject* const result =
- PyEval_CallFunction(
+ PyObject_CallFunction(
callable
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
@@ -69,7 +69,7 @@ call(PyObject* callable
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
- // argument for passing to PyEval_CallFunction, its reference
+ // argument for passing to PyObject_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.
diff --git a/contrib/restricted/boost/python/include/boost/python/call_method.hpp b/contrib/restricted/boost/python/include/boost/python/call_method.hpp
index 410f66820e..424077eab4 100644
--- a/contrib/restricted/boost/python/include/boost/python/call_method.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/call_method.hpp
@@ -69,7 +69,7 @@ call_method(PyObject* self, char const* name
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
- // argument for passing to PyEval_CallFunction, its reference
+ // argument for passing to PyObject_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.
diff --git a/contrib/restricted/boost/python/include/boost/python/def_visitor.hpp b/contrib/restricted/boost/python/include/boost/python/def_visitor.hpp
index 9c8907cd6f..18dd928684 100644
--- a/contrib/restricted/boost/python/include/boost/python/def_visitor.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/def_visitor.hpp
@@ -16,7 +16,7 @@ template <class T, class X1, class X2, class X3> class class_;
class def_visitor_access
{
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
- || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
+ || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends.
public:
@@ -52,7 +52,7 @@ class def_visitor
friend class def_visitor_access;
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
- || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
+ || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends.
public:
diff --git a/contrib/restricted/boost/python/include/boost/python/detail/caller.hpp b/contrib/restricted/boost/python/include/boost/python/detail/caller.hpp
index 1bd30bfb5a..2834d6da99 100644
--- a/contrib/restricted/boost/python/include/boost/python/detail/caller.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/detail/caller.hpp
@@ -109,6 +109,23 @@ struct converter_target_type <void_result_to_python >
return 0;
}
};
+
+// Generation of ret moved from caller_arity<N>::impl::signature to here due to "feature" in MSVC 15.7.2 with /O2
+// which left the ret uninitialized and caused segfaults in Python interpreter.
+template<class Policies, class Sig> const signature_element* get_ret()
+{
+ typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
+ typedef typename select_result_converter<Policies, rtype>::type result_converter;
+
+ static const signature_element ret = {
+ (is_void<rtype>::value ? "void" : type_id<rtype>().name())
+ , &detail::converter_target_type<result_converter>::get_pytype
+ , boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
+ };
+
+ return &ret;
+}
+
#endif
@@ -229,16 +246,12 @@ struct caller_arity<N>
{
const signature_element * sig = detail::signature<Sig>::elements();
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
+ // MSVC 15.7.2, when compiling to /O2 left the static const signature_element ret,
+ // originally defined here, uninitialized. This in turn led to SegFault in Python interpreter.
+ // Issue is resolved by moving the generation of ret to separate function in detail namespace (see above).
+ const signature_element * ret = detail::get_ret<Policies, Sig>();
- typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
- typedef typename select_result_converter<Policies, rtype>::type result_converter;
-
- static const signature_element ret = {
- (is_void<rtype>::value ? "void" : type_id<rtype>().name())
- , &detail::converter_target_type<result_converter>::get_pytype
- , boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
- };
- py_func_sig_info res = {sig, &ret };
+ py_func_sig_info res = {sig, ret };
#else
py_func_sig_info res = {sig, sig };
#endif
diff --git a/contrib/restricted/boost/python/include/boost/python/detail/config.hpp b/contrib/restricted/boost/python/include/boost/python/detail/config.hpp
index acf588311f..8dce9b742e 100644
--- a/contrib/restricted/boost/python/include/boost/python/detail/config.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/detail/config.hpp
@@ -105,7 +105,9 @@
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
-#define BOOST_LIB_NAME boost_python##PY_MAJOR_VERSION##PY_MINOR_VERSION
+#define _BOOST_PYTHON_CONCAT(N, M, m) N ## M ## m
+#define BOOST_PYTHON_CONCAT(N, M, m) _BOOST_PYTHON_CONCAT(N, M, m)
+#define BOOST_LIB_NAME BOOST_PYTHON_CONCAT(boost_python, PY_MAJOR_VERSION, PY_MINOR_VERSION)
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
@@ -118,6 +120,9 @@
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
+#undef BOOST_PYTHON_CONCAT
+#undef _BOOST_PYTHON_CONCAT
+
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition
#endif
diff --git a/contrib/restricted/boost/python/include/boost/python/detail/wrap_python.hpp b/contrib/restricted/boost/python/include/boost/python/detail/wrap_python.hpp
index 9fdb222c68..037e4bf2ec 100644
--- a/contrib/restricted/boost/python/include/boost/python/detail/wrap_python.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/detail/wrap_python.hpp
@@ -47,6 +47,13 @@
# endif
#endif
+// pyconfig.h defines a macro with hypot name, what breaks libstdc++ math headers
+// that Python.h tries to include afterwards.
+#if defined(__MINGW32__)
+# include <cmath>
+# include <math.h>
+#endif
+
# include <pyconfig.h>
# if defined(_SGI_COMPILER_VERSION) && _SGI_COMPILER_VERSION >= 740
# undef _POSIX_C_SOURCE
@@ -83,6 +90,7 @@
// than MSVC on Win32
//
#if defined(_WIN32) || defined(__CYGWIN__)
+
# if defined(__GNUC__) && defined(__CYGWIN__)
# if defined(__LP64__)
@@ -138,19 +146,45 @@ typedef int pid_t;
# undef hypot // undo the evil #define left by Python.
-# elif defined(__BORLANDC__)
+# elif defined(__BORLANDC__) && !defined(__clang__)
# undef HAVE_HYPOT
# define HAVE_HYPOT 1
# endif
#endif // _WIN32
+#if defined(__GNUC__)
+# if defined(__has_warning)
+# define BOOST_PYTHON_GCC_HAS_WREGISTER __has_warning("-Wregister")
+# else
+# define BOOST_PYTHON_GCC_HAS_WREGISTER __GNUC__ >= 7
+# endif
+#else
+# define BOOST_PYTHON_GCC_HAS_WREGISTER 0
+#endif
+
+// Python.h header uses `register` keyword until Python 3.4
+#if BOOST_PYTHON_GCC_HAS_WREGISTER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wregister"
+#elif defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 5033) // 'register' is no longer a supported storage class
+#endif
+
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2 && PY_MICRO_VERSION < 2
# include <boost/python/detail/python22_fixed.h>
#else
# include <Python.h>
#endif
+#if BOOST_PYTHON_GCC_HAS_WREGISTER
+# pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+# pragma warning(pop)
+#endif
+#undef BOOST_PYTHON_GCC_HAS_WREGISTER
+
#ifdef BOOST_PYTHON_ULONG_MAX_UNDEFINED
# undef ULONG_MAX
# undef BOOST_PYTHON_ULONG_MAX_UNDEFINED
@@ -193,7 +227,11 @@ typedef int pid_t;
# define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
+#endif
+#if PY_VERSION_HEX < 0x030900A4
+# define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
+# define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0)
#endif
diff --git a/contrib/restricted/boost/python/include/boost/python/list.hpp b/contrib/restricted/boost/python/include/boost/python/list.hpp
index 10fd40fda5..0d5e2c8fd9 100644
--- a/contrib/restricted/boost/python/include/boost/python/list.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/list.hpp
@@ -73,7 +73,7 @@ class list : public detail::list_base
}
template <class T>
- long count(T const& value) const
+ ssize_t count(T const& value) const
{
return base::count(object(value));
}
diff --git a/contrib/restricted/boost/python/include/boost/python/long.hpp b/contrib/restricted/boost/python/include/boost/python/long.hpp
index 129c61f9e4..c15604c91c 100644
--- a/contrib/restricted/boost/python/include/boost/python/long.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/long.hpp
@@ -24,8 +24,8 @@ namespace detail
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_base, object)
private:
- static detail::new_non_null_reference call(object const&);
- static detail::new_non_null_reference call(object const&, object const&);
+ static detail::new_reference call(object const&);
+ static detail::new_reference call(object const&, object const&);
};
}
diff --git a/contrib/restricted/boost/python/include/boost/python/object/iterator.hpp b/contrib/restricted/boost/python/include/boost/python/object/iterator.hpp
index e2f65721fb..874950365d 100644
--- a/contrib/restricted/boost/python/include/boost/python/object/iterator.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/object/iterator.hpp
@@ -25,7 +25,7 @@
# include <boost/type.hpp>
-# include <boost/detail/iterator.hpp>
+# include <iterator>
namespace boost { namespace python { namespace objects {
@@ -42,7 +42,7 @@ struct iterator_range
{
iterator_range(object sequence, Iterator start, Iterator finish);
- typedef boost::detail::iterator_traits<Iterator> traits_t;
+ typedef std::iterator_traits<Iterator> traits_t;
struct next
{
diff --git a/contrib/restricted/boost/python/include/boost/python/object/make_instance.hpp b/contrib/restricted/boost/python/include/boost/python/object/make_instance.hpp
index 31ec08f7c3..5eb3aa9d9c 100644
--- a/contrib/restricted/boost/python/include/boost/python/object/make_instance.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/object/make_instance.hpp
@@ -47,7 +47,7 @@ struct make_instance_impl
// Note the position of the internally-stored Holder,
// for the sake of destruction
- Py_SIZE(instance) = offsetof(instance_t, storage);
+ Py_SET_SIZE(instance, offsetof(instance_t, storage));
// Release ownership of the python object
protect.cancel();
diff --git a/contrib/restricted/boost/python/include/boost/python/other.hpp b/contrib/restricted/boost/python/include/boost/python/other.hpp
index 24a24ad8d1..26ebb426ba 100644
--- a/contrib/restricted/boost/python/include/boost/python/other.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/other.hpp
@@ -1,5 +1,5 @@
-#ifndef OTHER_DWA20020601_HPP
-# define OTHER_DWA20020601_HPP
+#ifndef BOOST_PYTHON_OTHER_HPP
+# define BOOST_PYTHON_OTHER_HPP
# include <boost/python/detail/prefix.hpp>
// Copyright David Abrahams 2002.
@@ -7,8 +7,6 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-# pragma once
-
# include <boost/config.hpp>
namespace boost { namespace python {
@@ -51,4 +49,4 @@ namespace detail
}} // namespace boost::python
-#endif // #ifndef OTHER_DWA20020601_HPP
+#endif
diff --git a/contrib/restricted/boost/python/include/boost/python/override.hpp b/contrib/restricted/boost/python/include/boost/python/override.hpp
index 39714257f9..b631226fd6 100644
--- a/contrib/restricted/boost/python/include/boost/python/override.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/override.hpp
@@ -97,7 +97,7 @@ class override : public object
operator()() const
{
detail::method_result x(
- PyEval_CallFunction(
+ PyObject_CallFunction(
this->ptr()
, const_cast<char*>("()")
));
@@ -132,7 +132,7 @@ detail::method_result
operator()( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) ) const
{
detail::method_result x(
- PyEval_CallFunction(
+ PyObject_CallFunction(
this->ptr()
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_fast_arg_to_python_get, nil)
diff --git a/contrib/restricted/boost/python/include/boost/python/ptr.hpp b/contrib/restricted/boost/python/include/boost/python/ptr.hpp
index 287daba458..8e97aa4064 100644
--- a/contrib/restricted/boost/python/include/boost/python/ptr.hpp
+++ b/contrib/restricted/boost/python/include/boost/python/ptr.hpp
@@ -1,5 +1,5 @@
-#ifndef PTR_DWA20020601_HPP
-# define PTR_DWA20020601_HPP
+#ifndef BOOST_PYTHON_PTR_HPP
+# define BOOST_PYTHON_PTR_HPP
# include <boost/python/detail/prefix.hpp>
// Copyright David Abrahams 2002.
@@ -11,8 +11,6 @@
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001 Peter Dimov
-# pragma once
-
# include <boost/config.hpp>
# include <boost/mpl/bool.hpp>
@@ -64,4 +62,4 @@ class unwrap_pointer<pointer_wrapper<T> >
}} // namespace boost::python
-#endif // #ifndef PTR_DWA20020601_HPP
+#endif
diff --git a/contrib/restricted/boost/python/src/exec.cpp b/contrib/restricted/boost/python/src/exec.cpp
index 5193b04745..8bc8be996b 100644
--- a/contrib/restricted/boost/python/src/exec.cpp
+++ b/contrib/restricted/boost/python/src/exec.cpp
@@ -116,7 +116,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l
#elif PY_VERSION_HEX >= 0x03000000
// Let python open the file to avoid potential binary incompatibilities.
PyObject *fo = Py_BuildValue("s", f);
- FILE *fs = _Py_fopen(fo, "r"); // Private CPython API
+ FILE *fs = fopen(fo, "r");
Py_DECREF(fo);
#else
// Let python open the file to avoid potential binary incompatibilities.
@@ -128,7 +128,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l
PyObject* result = PyRun_File(fs,
f,
Py_file_input,
- global.ptr(), local.ptr());
+ global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
diff --git a/contrib/restricted/boost/python/src/long.cpp b/contrib/restricted/boost/python/src/long.cpp
index 1ec8ebc011..6aa2965e83 100644
--- a/contrib/restricted/boost/python/src/long.cpp
+++ b/contrib/restricted/boost/python/src/long.cpp
@@ -6,16 +6,16 @@
namespace boost { namespace python { namespace detail {
-new_non_null_reference long_base::call(object const& arg_)
+new_reference long_base::call(object const& arg_)
{
- return (detail::new_non_null_reference)PyObject_CallFunction(
+ return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, const_cast<char*>("(O)"),
arg_.ptr());
}
-new_non_null_reference long_base::call(object const& arg_, object const& base)
+new_reference long_base::call(object const& arg_, object const& base)
{
- return (detail::new_non_null_reference)PyObject_CallFunction(
+ return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, const_cast<char*>("(OO)"),
arg_.ptr(), base.ptr());
}
diff --git a/contrib/restricted/boost/python/src/module.cpp b/contrib/restricted/boost/python/src/module.cpp
index 9628481996..57675fa2df 100644
--- a/contrib/restricted/boost/python/src/module.cpp
+++ b/contrib/restricted/boost/python/src/module.cpp
@@ -21,7 +21,7 @@ namespace
object m_obj(((borrowed_reference_t*)m));
scope current_module(m_obj);
- handle_exception(init_function);
+ if (handle_exception(init_function)) return NULL;
}
return m;
diff --git a/contrib/restricted/boost/python/src/object/class.cpp b/contrib/restricted/boost/python/src/object/class.cpp
index 8d0daf63d7..9f8dc61ad1 100644
--- a/contrib/restricted/boost/python/src/object/class.cpp
+++ b/contrib/restricted/boost/python/src/object/class.cpp
@@ -208,7 +208,7 @@ namespace objects
{
if (static_data_object.tp_dict == 0)
{
- Py_TYPE(&static_data_object) = &PyType_Type;
+ Py_SET_TYPE(&static_data_object, &PyType_Type);
static_data_object.tp_base = &PyProperty_Type;
if (PyType_Ready(&static_data_object))
return 0;
@@ -316,7 +316,7 @@ namespace objects
{
if (class_metatype_object.tp_dict == 0)
{
- Py_TYPE(&class_metatype_object) = &PyType_Type;
+ Py_SET_TYPE(&class_metatype_object, &PyType_Type);
class_metatype_object.tp_base = &PyType_Type;
if (PyType_Ready(&class_metatype_object))
return type_handle();
@@ -374,12 +374,7 @@ namespace objects
// like, so we'll store the total size of the object
// there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders.
-#if PY_VERSION_HEX >= 0x02060000
- Py_SIZE(result) =
-#else
- result->ob_size =
-#endif
- -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
+ Py_SET_SIZE(result,-static_cast<int>(offsetof(instance<>,storage) + instance_size));
}
return (PyObject*)result;
}
@@ -470,7 +465,7 @@ namespace objects
{
if (class_type_object.tp_dict == 0)
{
- Py_TYPE(&class_type_object) = incref(class_metatype().get());
+ Py_SET_TYPE(&class_type_object, incref(class_metatype().get()));
class_type_object.tp_base = &PyBaseObject_Type;
if (PyType_Ready(&class_type_object))
return type_handle();
@@ -618,7 +613,7 @@ namespace objects
{
object property(
(python::detail::new_reference)
- PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
+ PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), (char*)NULL, (char*)NULL, docstr));
this->setattr(name, property);
}
@@ -628,7 +623,7 @@ namespace objects
{
object property(
(python::detail::new_reference)
- PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
+ PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), (char*)NULL, docstr));
this->setattr(name, property);
}
@@ -739,7 +734,7 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std:
assert(holder_offset >= offsetof(objects::instance<>,storage));
// Record the fact that the storage is occupied, noting where it starts
- Py_SIZE(self) = holder_offset;
+ Py_SET_SIZE(self, holder_offset);
return (char*)self + holder_offset;
}
else
diff --git a/contrib/restricted/boost/python/src/object/enum.cpp b/contrib/restricted/boost/python/src/object/enum.cpp
index 10122ad1da..293e705899 100644
--- a/contrib/restricted/boost/python/src/object/enum.cpp
+++ b/contrib/restricted/boost/python/src/object/enum.cpp
@@ -153,7 +153,7 @@ namespace
{
if (enum_type_object.tp_dict == 0)
{
- Py_TYPE(&enum_type_object) = incref(&PyType_Type);
+ Py_SET_TYPE(&enum_type_object, incref(&PyType_Type));
#if PY_VERSION_HEX >= 0x03000000
enum_type_object.tp_base = &PyLong_Type;
#else
diff --git a/contrib/restricted/boost/python/src/object/function.cpp b/contrib/restricted/boost/python/src/object/function.cpp
index e15eb3ffc0..787679e138 100644
--- a/contrib/restricted/boost/python/src/object/function.cpp
+++ b/contrib/restricted/boost/python/src/object/function.cpp
@@ -107,7 +107,7 @@ function::function(
PyObject* p = this;
if (Py_TYPE(&function_type) == 0)
{
- Py_TYPE(&function_type) = &PyType_Type;
+ Py_SET_TYPE(&function_type, &PyType_Type);
::PyType_Ready(&function_type);
}
@@ -158,11 +158,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
{
// no argument preprocessing
}
- else if (n_actual > max_arity)
- {
- // too many arguments
- inner_args = handle<>();
- }
else
{
// build a new arg tuple, will adjust its size later
diff --git a/contrib/restricted/boost/python/src/object/life_support.cpp b/contrib/restricted/boost/python/src/object/life_support.cpp
index b7e9aa861e..281c3bffc5 100644
--- a/contrib/restricted/boost/python/src/object/life_support.cpp
+++ b/contrib/restricted/boost/python/src/object/life_support.cpp
@@ -93,7 +93,7 @@ PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)
if (Py_TYPE(&life_support_type) == 0)
{
- Py_TYPE(&life_support_type) = &PyType_Type;
+ Py_SET_TYPE(&life_support_type, &PyType_Type);
PyType_Ready(&life_support_type);
}
diff --git a/contrib/restricted/boost/python/src/wrapper.cpp b/contrib/restricted/boost/python/src/wrapper.cpp
index f8feaef947..8b1b884769 100644
--- a/contrib/restricted/boost/python/src/wrapper.cpp
+++ b/contrib/restricted/boost/python/src/wrapper.cpp
@@ -25,7 +25,7 @@ namespace detail
if (
PyMethod_Check(m.get())
- && ((PyMethodObject*)m.get())->im_self == this->m_self
+ && PyMethod_GET_SELF(m.get()) == this->m_self
&& class_object->tp_dict != 0
)
{
@@ -34,7 +34,7 @@ namespace detail
}
- if (borrowed_f != ((PyMethodObject*)m.get())->im_func)
+ if (borrowed_f != PyMethod_GET_FUNCTION(m.get()))
return override(m);
}
}
diff --git a/contrib/restricted/boost/winapi/include/boost/winapi/directory_management.hpp b/contrib/restricted/boost/winapi/include/boost/winapi/directory_management.hpp
new file mode 100644
index 0000000000..b219010d6d
--- /dev/null
+++ b/contrib/restricted/boost/winapi/include/boost/winapi/directory_management.hpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 Vicente J. Botet Escriba
+ * Copyright 2015 Andrey Semashev
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#ifndef BOOST_WINAPI_DIRECTORY_MANAGEMENT_HPP_INCLUDED_
+#define BOOST_WINAPI_DIRECTORY_MANAGEMENT_HPP_INCLUDED_
+
+#include <boost/winapi/basic_types.hpp>
+#include <boost/winapi/get_system_directory.hpp>
+#include <boost/winapi/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+ CreateDirectoryA(boost::winapi::LPCSTR_, ::_SECURITY_ATTRIBUTES*);
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC
+ GetTempPathA(boost::winapi::DWORD_ length, boost::winapi::LPSTR_ buffer);
+#endif
+BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+ RemoveDirectoryA(boost::winapi::LPCSTR_);
+#endif
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+ CreateDirectoryW(boost::winapi::LPCWSTR_, ::_SECURITY_ATTRIBUTES*);
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC
+ GetTempPathW(boost::winapi::DWORD_ length, boost::winapi::LPWSTR_ buffer);
+#endif
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+ RemoveDirectoryW(boost::winapi::LPCWSTR_);
+} // extern "C"
+#endif
+
+namespace boost {
+namespace winapi {
+
+#if !defined( BOOST_NO_ANSI_APIS )
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+using ::GetTempPathA;
+#endif
+using ::RemoveDirectoryA;
+#endif
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+using ::GetTempPathW;
+#endif
+using ::RemoveDirectoryW;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ CreateDirectoryA(LPCSTR_ pPathName, PSECURITY_ATTRIBUTES_ pSecurityAttributes)
+{
+ return ::CreateDirectoryA(pPathName, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(pSecurityAttributes));
+}
+#endif
+
+BOOST_FORCEINLINE BOOL_ CreateDirectoryW(LPCWSTR_ pPathName, PSECURITY_ATTRIBUTES_ pSecurityAttributes)
+{
+ return ::CreateDirectoryW(pPathName, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(pSecurityAttributes));
+}
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ create_directory(LPCSTR_ pPathName, PSECURITY_ATTRIBUTES_ pSecurityAttributes)
+{
+ return ::CreateDirectoryA(pPathName, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(pSecurityAttributes));
+}
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+BOOST_FORCEINLINE DWORD_ get_temp_path(DWORD_ length, LPSTR_ buffer)
+{
+ return ::GetTempPathA(length, buffer);
+}
+#endif
+BOOST_FORCEINLINE BOOL_ remove_directory(LPCSTR_ pPathName)
+{
+ return ::RemoveDirectoryA(pPathName);
+}
+#endif
+
+BOOST_FORCEINLINE BOOL_ create_directory(LPCWSTR_ pPathName, PSECURITY_ATTRIBUTES_ pSecurityAttributes)
+{
+ return ::CreateDirectoryW(pPathName, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(pSecurityAttributes));
+}
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+BOOST_FORCEINLINE DWORD_ get_temp_path(DWORD_ length, LPWSTR_ buffer)
+{
+ return ::GetTempPathW(length, buffer);
+}
+#endif
+BOOST_FORCEINLINE BOOL_ remove_directory(LPCWSTR_ pPathName)
+{
+ return ::RemoveDirectoryW(pPathName);
+}
+
+} // namespace winapi
+} // namespace boost
+
+#include <boost/winapi/detail/footer.hpp>
+
+#endif // BOOST_WINAPI_DIRECTORY_MANAGEMENT_HPP_INCLUDED_
diff --git a/contrib/restricted/boost/winapi/include/boost/winapi/file_mapping.hpp b/contrib/restricted/boost/winapi/include/boost/winapi/file_mapping.hpp
new file mode 100644
index 0000000000..9a5e23803a
--- /dev/null
+++ b/contrib/restricted/boost/winapi/include/boost/winapi/file_mapping.hpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2010 Vicente J. Botet Escriba
+ * Copyright 2015 Andrey Semashev
+ * Copyright 2016 Jorge Lodos
+ * Copyright 2017 James E. King, III
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#ifndef BOOST_WINAPI_FILE_MAPPING_HPP_INCLUDED_
+#define BOOST_WINAPI_FILE_MAPPING_HPP_INCLUDED_
+
+#include <boost/winapi/basic_types.hpp>
+#include <boost/winapi/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+/*
+ * UWP:
+ * API SDK 8 SDK 10
+ * CreateFileMapping DESKTOP - DESKTOP | SYSTEM
+ * FlushViewOfFile APP - APP | SYSTEM
+ * MapViewOfFile DESKTOP - DESKTOP | SYSTEM
+ * MapViewOfFileEx DESKTOP - DESKTOP | SYSTEM
+ * OpenFileMapping DESKTOP - DESKTOP | SYSTEM
+ * UnmapViewOfFile APP - APP | SYSTEM
+ */
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+#if BOOST_WINAPI_PARTITION_DESKTOP
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateFileMappingA(
+ boost::winapi::HANDLE_ hFile,
+ ::_SECURITY_ATTRIBUTES* lpFileMappingAttributes,
+ boost::winapi::DWORD_ flProtect,
+ boost::winapi::DWORD_ dwMaximumSizeHigh,
+ boost::winapi::DWORD_ dwMaximumSizeLow,
+ boost::winapi::LPCSTR_ lpName);
+
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+OpenFileMappingA(
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::BOOL_ bInheritHandle,
+ boost::winapi::LPCSTR_ lpName);
+#endif // !defined( BOOST_NO_ANSI_APIS )
+#endif // BOOST_WINAPI_PARTITION_DESKTOP
+
+#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateFileMappingW(
+ boost::winapi::HANDLE_ hFile,
+ ::_SECURITY_ATTRIBUTES* lpFileMappingAttributes,
+ boost::winapi::DWORD_ flProtect,
+ boost::winapi::DWORD_ dwMaximumSizeHigh,
+ boost::winapi::DWORD_ dwMaximumSizeLow,
+ boost::winapi::LPCWSTR_ lpName);
+
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::LPVOID_ BOOST_WINAPI_WINAPI_CC
+MapViewOfFile(
+ boost::winapi::HANDLE_ hFileMappingObject,
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::DWORD_ dwFileOffsetHigh,
+ boost::winapi::DWORD_ dwFileOffsetLow,
+ boost::winapi::SIZE_T_ dwNumberOfBytesToMap);
+
+BOOST_WINAPI_IMPORT boost::winapi::LPVOID_ BOOST_WINAPI_WINAPI_CC
+MapViewOfFileEx(
+ boost::winapi::HANDLE_ hFileMappingObject,
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::DWORD_ dwFileOffsetHigh,
+ boost::winapi::DWORD_ dwFileOffsetLow,
+ boost::winapi::SIZE_T_ dwNumberOfBytesToMap,
+ boost::winapi::LPVOID_ lpBaseAddress);
+
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+OpenFileMappingW(
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::BOOL_ bInheritHandle,
+ boost::winapi::LPCWSTR_ lpName);
+#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
+
+#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+FlushViewOfFile(
+ boost::winapi::LPCVOID_ lpBaseAddress,
+ boost::winapi::SIZE_T_ dwNumberOfBytesToFlush);
+
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+UnmapViewOfFile(boost::winapi::LPCVOID_ lpBaseAddress);
+#endif // BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM
+
+} // extern "C"
+#endif // !defined( BOOST_USE_WINDOWS_H )
+
+namespace boost {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_FILE_ = SEC_FILE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_IMAGE_ = SEC_IMAGE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_RESERVE_ = SEC_RESERVE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_COMMIT_ = SEC_COMMIT;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_NOCACHE_ = SEC_NOCACHE;
+
+// These permission flags are undocumented and some of them are equivalent to the FILE_MAP_* flags.
+// SECTION_QUERY enables NtQuerySection.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtQuerySection.html
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_QUERY_ = SECTION_QUERY;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_WRITE_ = SECTION_MAP_WRITE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_READ_ = SECTION_MAP_READ;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_EXECUTE_ = SECTION_MAP_EXECUTE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_EXTEND_SIZE_ = SECTION_EXTEND_SIZE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_ALL_ACCESS_ = SECTION_ALL_ACCESS;
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_COPY_ = FILE_MAP_COPY;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_WRITE_ = FILE_MAP_WRITE;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_READ_ = FILE_MAP_READ;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_ALL_ACCESS_ = FILE_MAP_ALL_ACCESS;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_FILE_ = 0x800000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_IMAGE_ = 0x1000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_RESERVE_ = 0x4000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_COMMIT_ = 0x8000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_NOCACHE_ = 0x10000000;
+
+// These permission flags are undocumented and some of them are equivalent to the FILE_MAP_* flags.
+// SECTION_QUERY enables NtQuerySection.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtQuerySection.html
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_QUERY_ = 0x00000001;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_WRITE_ = 0x00000002;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_READ_ = 0x00000004;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_EXECUTE_ = 0x00000008;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_EXTEND_SIZE_ = 0x00000010;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_ALL_ACCESS_ = 0x000F001F; // STANDARD_RIGHTS_REQUIRED | SECTION_*
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_COPY_ = SECTION_QUERY_;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_WRITE_ = SECTION_MAP_WRITE_;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_READ_ = SECTION_MAP_READ_;
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_ALL_ACCESS_ = SECTION_ALL_ACCESS_;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+// These constants are not defined in Windows SDK up until the one shipped with MSVC 8 and MinGW (as of 2016-02-14)
+BOOST_CONSTEXPR_OR_CONST DWORD_ SECTION_MAP_EXECUTE_EXPLICIT_ = 0x00000020; // not included in SECTION_ALL_ACCESS
+BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_MAP_EXECUTE_ = SECTION_MAP_EXECUTE_EXPLICIT_; // not included in FILE_MAP_ALL_ACCESS
+
+// These constants are not defined in Windows SDK up until 6.0A and MinGW (as of 2016-02-14)
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_PROTECTED_IMAGE_ = 0x2000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_WRITECOMBINE_ = 0x40000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_LARGE_PAGES_ = 0x80000000;
+BOOST_CONSTEXPR_OR_CONST DWORD_ SEC_IMAGE_NO_EXECUTE_ = (SEC_IMAGE_ | SEC_NOCACHE_);
+
+#if BOOST_WINAPI_PARTITION_DESKTOP
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE HANDLE_ CreateFileMappingA(
+ HANDLE_ hFile,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
+ DWORD_ flProtect,
+ DWORD_ dwMaximumSizeHigh,
+ DWORD_ dwMaximumSizeLow,
+ LPCSTR_ lpName)
+{
+ return ::CreateFileMappingA(
+ hFile,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpFileMappingAttributes),
+ flProtect,
+ dwMaximumSizeHigh,
+ dwMaximumSizeLow,
+ lpName);
+}
+
+BOOST_FORCEINLINE HANDLE_ create_file_mapping(
+ HANDLE_ hFile,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
+ DWORD_ flProtect,
+ DWORD_ dwMaximumSizeHigh,
+ DWORD_ dwMaximumSizeLow,
+ LPCSTR_ lpName)
+{
+ return ::CreateFileMappingA(
+ hFile,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpFileMappingAttributes),
+ flProtect,
+ dwMaximumSizeHigh,
+ dwMaximumSizeLow,
+ lpName);
+}
+
+using ::OpenFileMappingA;
+
+BOOST_FORCEINLINE HANDLE_ open_file_mapping(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCSTR_ lpName)
+{
+ return ::OpenFileMappingA(dwDesiredAccess, bInheritHandle, lpName);
+}
+#endif
+#endif // BOOST_WINAPI_PARTITION_DESKTOP
+
+#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
+BOOST_FORCEINLINE HANDLE_ CreateFileMappingW(
+ HANDLE_ hFile,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
+ DWORD_ flProtect,
+ DWORD_ dwMaximumSizeHigh,
+ DWORD_ dwMaximumSizeLow,
+ LPCWSTR_ lpName)
+{
+ return ::CreateFileMappingW(
+ hFile,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpFileMappingAttributes),
+ flProtect,
+ dwMaximumSizeHigh,
+ dwMaximumSizeLow,
+ lpName);
+}
+
+BOOST_FORCEINLINE HANDLE_ create_file_mapping(
+ HANDLE_ hFile,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
+ DWORD_ flProtect,
+ DWORD_ dwMaximumSizeHigh,
+ DWORD_ dwMaximumSizeLow,
+ LPCWSTR_ lpName)
+{
+ return ::CreateFileMappingW(
+ hFile,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpFileMappingAttributes),
+ flProtect,
+ dwMaximumSizeHigh,
+ dwMaximumSizeLow,
+ lpName);
+}
+
+using ::MapViewOfFile;
+using ::MapViewOfFileEx;
+using ::OpenFileMappingW;
+
+BOOST_FORCEINLINE HANDLE_ open_file_mapping(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCWSTR_ lpName)
+{
+ return ::OpenFileMappingW(dwDesiredAccess, bInheritHandle, lpName);
+}
+#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
+
+#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM
+using ::FlushViewOfFile;
+using ::UnmapViewOfFile;
+#endif // BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM
+
+}
+}
+
+#include <boost/winapi/detail/footer.hpp>
+
+#endif // BOOST_WINAPI_FILE_MAPPING_HPP_INCLUDED_
diff --git a/contrib/restricted/boost/winapi/include/boost/winapi/get_system_directory.hpp b/contrib/restricted/boost/winapi/include/boost/winapi/get_system_directory.hpp
new file mode 100644
index 0000000000..636808a915
--- /dev/null
+++ b/contrib/restricted/boost/winapi/include/boost/winapi/get_system_directory.hpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Klemens D. Morgenstern
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#ifndef BOOST_WINAPI_GET_SYSTEM_DIRECTORY_HPP_INCLUDED_
+#define BOOST_WINAPI_GET_SYSTEM_DIRECTORY_HPP_INCLUDED_
+
+#include <boost/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_WINAPI_PARTITION_DESKTOP
+
+#include <boost/winapi/detail/header.hpp>
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_WINAPI_IMPORT boost::winapi::UINT_ BOOST_WINAPI_WINAPI_CC
+GetSystemDirectoryA(
+ boost::winapi::LPSTR_ lpBuffer,
+ boost::winapi::UINT_ uSize);
+#endif
+
+BOOST_WINAPI_IMPORT boost::winapi::UINT_ BOOST_WINAPI_WINAPI_CC
+GetSystemDirectoryW(
+ boost::winapi::LPWSTR_ lpBuffer,
+ boost::winapi::UINT_ uSize);
+} // extern "C"
+#endif
+
+namespace boost {
+namespace winapi {
+
+#if !defined( BOOST_NO_ANSI_APIS )
+using ::GetSystemDirectoryA;
+#endif
+using ::GetSystemDirectoryW;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE UINT_ get_system_directory(LPSTR_ lpBuffer, UINT_ uSize)
+{
+ return ::GetSystemDirectoryA(lpBuffer, uSize);
+}
+#endif
+
+BOOST_FORCEINLINE UINT_ get_system_directory(LPWSTR_ lpBuffer, UINT_ uSize)
+{
+ return ::GetSystemDirectoryW(lpBuffer, uSize);
+}
+
+}
+}
+
+#include <boost/winapi/detail/footer.hpp>
+
+#endif // BOOST_WINAPI_PARTITION_DESKTOP
+
+#endif // BOOST_WINAPI_GET_SYSTEM_DIRECTORY_HPP_INCLUDED_
diff --git a/contrib/restricted/boost/winapi/include/boost/winapi/mutex.hpp b/contrib/restricted/boost/winapi/include/boost/winapi/mutex.hpp
new file mode 100644
index 0000000000..c708c54376
--- /dev/null
+++ b/contrib/restricted/boost/winapi/include/boost/winapi/mutex.hpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2010 Vicente J. Botet Escriba
+ * Copyright 2015, 2017 Andrey Semashev
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#ifndef BOOST_WINAPI_MUTEX_HPP_INCLUDED_
+#define BOOST_WINAPI_MUTEX_HPP_INCLUDED_
+
+#include <boost/winapi/basic_types.hpp>
+#include <boost/winapi/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H ) && BOOST_WINAPI_PARTITION_APP_SYSTEM
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateMutexA(
+ ::_SECURITY_ATTRIBUTES* lpMutexAttributes,
+ boost::winapi::BOOL_ bInitialOwner,
+ boost::winapi::LPCSTR_ lpName);
+#endif
+
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateMutexW(
+ ::_SECURITY_ATTRIBUTES* lpMutexAttributes,
+ boost::winapi::BOOL_ bInitialOwner,
+ boost::winapi::LPCWSTR_ lpName);
+} // extern "C"
+#endif // !defined( BOOST_USE_WINDOWS_H ) && BOOST_WINAPI_PARTITION_APP_SYSTEM
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateMutexExA(
+ ::_SECURITY_ATTRIBUTES* lpMutexAttributes,
+ boost::winapi::LPCSTR_ lpName,
+ boost::winapi::DWORD_ dwFlags,
+ boost::winapi::DWORD_ dwDesiredAccess);
+#endif
+
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+OpenMutexA(
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::BOOL_ bInheritHandle,
+ boost::winapi::LPCSTR_ lpName);
+#endif // !defined( BOOST_NO_ANSI_APIS )
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+CreateMutexExW(
+ ::_SECURITY_ATTRIBUTES* lpMutexAttributes,
+ boost::winapi::LPCWSTR_ lpName,
+ boost::winapi::DWORD_ dwFlags,
+ boost::winapi::DWORD_ dwDesiredAccess);
+#endif
+
+BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC
+OpenMutexW(
+ boost::winapi::DWORD_ dwDesiredAccess,
+ boost::winapi::BOOL_ bInheritHandle,
+ boost::winapi::LPCWSTR_ lpName);
+
+BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+ReleaseMutex(boost::winapi::HANDLE_ hMutex);
+} // extern "C"
+#endif
+
+namespace boost {
+namespace winapi {
+
+#if !defined( BOOST_NO_ANSI_APIS )
+using ::OpenMutexA;
+#endif
+using ::OpenMutexW;
+using ::ReleaseMutex;
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ MUTEX_ALL_ACCESS_ = MUTEX_ALL_ACCESS;
+BOOST_CONSTEXPR_OR_CONST DWORD_ MUTEX_MODIFY_STATE_ = MUTEX_MODIFY_STATE;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_MUTEX_INITIAL_OWNER_ = CREATE_MUTEX_INITIAL_OWNER;
+#endif
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ MUTEX_ALL_ACCESS_ = 0x001F0001;
+BOOST_CONSTEXPR_OR_CONST DWORD_ MUTEX_MODIFY_STATE_ = 0x00000001;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_MUTEX_INITIAL_OWNER_ = 0x00000001;
+#endif
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+BOOST_CONSTEXPR_OR_CONST DWORD_ mutex_all_access = MUTEX_ALL_ACCESS_;
+BOOST_CONSTEXPR_OR_CONST DWORD_ mutex_modify_state = MUTEX_MODIFY_STATE_;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_CONSTEXPR_OR_CONST DWORD_ create_mutex_initial_owner = CREATE_MUTEX_INITIAL_OWNER_;
+#endif
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE HANDLE_ CreateMutexA(SECURITY_ATTRIBUTES_* lpMutexAttributes, BOOL_ bInitialOwner, LPCSTR_ lpName)
+{
+#if !BOOST_WINAPI_PARTITION_APP_SYSTEM && BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+ const DWORD_ flags = bInitialOwner ? create_mutex_initial_owner : 0u;
+ return ::CreateMutexExA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), lpName, flags, mutex_all_access);
+#else
+ return ::CreateMutexA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), bInitialOwner, lpName);
+#endif
+}
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_FORCEINLINE HANDLE_ CreateMutexExA(
+ SECURITY_ATTRIBUTES_* lpMutexAttributes,
+ LPCSTR_ lpName,
+ DWORD_ dwFlags,
+ DWORD_ dwDesiredAccess)
+{
+ return ::CreateMutexExA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), lpName, dwFlags, dwDesiredAccess);
+}
+#endif
+#endif
+
+BOOST_FORCEINLINE HANDLE_ CreateMutexW(SECURITY_ATTRIBUTES_* lpMutexAttributes, BOOL_ bInitialOwner, LPCWSTR_ lpName)
+{
+#if !BOOST_WINAPI_PARTITION_APP_SYSTEM && BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+ const DWORD_ flags = bInitialOwner ? create_mutex_initial_owner : 0u;
+ return ::CreateMutexExW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), lpName, flags, mutex_all_access);
+#else
+ return ::CreateMutexW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), bInitialOwner, lpName);
+#endif
+}
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+BOOST_FORCEINLINE HANDLE_ CreateMutexExW(
+ SECURITY_ATTRIBUTES_* lpMutexAttributes,
+ LPCWSTR_ lpName,
+ DWORD_ dwFlags,
+ DWORD_ dwDesiredAccess)
+{
+ return ::CreateMutexExW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpMutexAttributes), lpName, dwFlags, dwDesiredAccess);
+}
+#endif
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE HANDLE_ create_mutex(SECURITY_ATTRIBUTES_* lpAttributes, BOOL_ bInitialOwner, LPCSTR_ lpName)
+{
+ return winapi::CreateMutexA(lpAttributes, bInitialOwner, lpName);
+}
+
+BOOST_FORCEINLINE HANDLE_ open_mutex(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCSTR_ lpName)
+{
+ return ::OpenMutexA(dwDesiredAccess, bInheritHandle, lpName);
+}
+#endif
+
+BOOST_FORCEINLINE HANDLE_ create_mutex(SECURITY_ATTRIBUTES_* lpAttributes, BOOL_ bInitialOwner, LPCWSTR_ lpName)
+{
+ return winapi::CreateMutexW(lpAttributes, bInitialOwner, lpName);
+}
+
+BOOST_FORCEINLINE HANDLE_ open_mutex(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCWSTR_ lpName)
+{
+ return ::OpenMutexW(dwDesiredAccess, bInheritHandle, lpName);
+}
+
+BOOST_FORCEINLINE HANDLE_ create_anonymous_mutex(SECURITY_ATTRIBUTES_* lpAttributes, BOOL_ bInitialOwner)
+{
+ return winapi::CreateMutexW(lpAttributes, bInitialOwner, 0);
+}
+
+}
+}
+
+#include <boost/winapi/detail/footer.hpp>
+
+#endif // BOOST_WINAPI_MUTEX_HPP_INCLUDED_
diff --git a/contrib/restricted/boost/winapi/include/boost/winapi/security.hpp b/contrib/restricted/boost/winapi/include/boost/winapi/security.hpp
new file mode 100644
index 0000000000..80a2d952e3
--- /dev/null
+++ b/contrib/restricted/boost/winapi/include/boost/winapi/security.hpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 Vicente J. Botet Escriba
+ * Copyright 2015 Andrey Semashev
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#ifndef BOOST_WINAPI_SECURITY_HPP_INCLUDED_
+#define BOOST_WINAPI_SECURITY_HPP_INCLUDED_
+
+#include <boost/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_WINAPI_PARTITION_APP_SYSTEM
+
+#include <boost/winapi/detail/header.hpp>
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+struct _ACL;
+struct _SECURITY_DESCRIPTOR;
+#if defined( BOOST_WINAPI_IS_MINGW )
+typedef _SECURITY_DESCRIPTOR *PSECURITY_DESCRIPTOR;
+#else
+typedef boost::winapi::PVOID_ PSECURITY_DESCRIPTOR;
+#endif
+
+BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+InitializeSecurityDescriptor(
+ PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ boost::winapi::DWORD_ dwRevision);
+BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC
+SetSecurityDescriptorDacl(
+ PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ boost::winapi::BOOL_ bDaclPresent,
+ ::_ACL* pDacl,
+ boost::winapi::BOOL_ bDaclDefaulted);
+}
+#endif
+
+namespace boost {
+namespace winapi {
+
+typedef PVOID_ PSID_;
+typedef WORD_ SECURITY_DESCRIPTOR_CONTROL_, *PSECURITY_DESCRIPTOR_CONTROL_;
+
+typedef struct BOOST_MAY_ALIAS _ACL {
+ BYTE_ AclRevision;
+ BYTE_ Sbz1;
+ WORD_ AclSize;
+ WORD_ AceCount;
+ WORD_ Sbz2;
+} ACL_, *PACL_;
+
+typedef struct BOOST_MAY_ALIAS _SECURITY_DESCRIPTOR {
+ BYTE_ Revision;
+ BYTE_ Sbz1;
+ SECURITY_DESCRIPTOR_CONTROL_ Control;
+ PSID_ Owner;
+ PSID_ Group;
+ PACL_ Sacl;
+ PACL_ Dacl;
+} SECURITY_DESCRIPTOR_, *PISECURITY_DESCRIPTOR_;
+
+// To abstract away the different ::PSECURITY_DESCRIPTOR on MinGW, we use PVOID_ universally here
+// and cast the pointers to ::PSECURITY_DESCRIPTOR in wrapper functions.
+typedef PVOID_ PSECURITY_DESCRIPTOR_;
+
+BOOST_FORCEINLINE BOOL_ InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR_ pSecurityDescriptor, DWORD_ dwRevision)
+{
+ return ::InitializeSecurityDescriptor(reinterpret_cast< ::PSECURITY_DESCRIPTOR >(pSecurityDescriptor), dwRevision);
+}
+
+BOOST_FORCEINLINE BOOL_ SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR_ pSecurityDescriptor, BOOL_ bDaclPresent, PACL_ pDacl, BOOL_ bDaclDefaulted)
+{
+ return ::SetSecurityDescriptorDacl(reinterpret_cast< ::PSECURITY_DESCRIPTOR >(pSecurityDescriptor), bDaclPresent, reinterpret_cast< ::_ACL* >(pDacl), bDaclDefaulted);
+}
+
+}
+}
+
+#include <boost/winapi/detail/footer.hpp>
+
+#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM
+#endif // BOOST_WINAPI_SECURITY_HPP_INCLUDED_