From 62ad26ff8327909580b94afba1b669dbd9d31cd4 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Wed, 9 Jul 2025 10:54:47 -0300 Subject: [PATCH 1/7] Add boost/interprocess. --- .../interprocess/allocators/adaptive_pool.hpp | 470 ++++++ .../interprocess/allocators/allocator.hpp | 294 ++++ .../allocators/cached_adaptive_pool.hpp | 357 +++++ .../allocators/cached_node_allocator.hpp | 328 ++++ .../allocators/detail/adaptive_node_pool.hpp | 115 ++ .../allocators/detail/allocator_common.hpp | 857 +++++++++++ .../allocators/detail/node_pool.hpp | 111 ++ .../allocators/detail/node_tools.hpp | 54 + .../allocators/node_allocator.hpp | 454 ++++++ .../allocators/private_adaptive_pool.hpp | 470 ++++++ .../allocators/private_node_allocator.hpp | 447 ++++++ .../interprocess/anonymous_shared_memory.hpp | 125 ++ .../containers/allocation_type.hpp | 44 + .../containers/containers_fwd.hpp | 44 + .../boost/interprocess/containers/deque.hpp | 37 + .../interprocess/containers/flat_map.hpp | 37 + .../interprocess/containers/flat_set.hpp | 37 + .../boost/interprocess/containers/list.hpp | 37 + .../boost/interprocess/containers/map.hpp | 37 + .../boost/interprocess/containers/pair.hpp | 37 + .../boost/interprocess/containers/set.hpp | 37 + .../boost/interprocess/containers/slist.hpp | 36 + .../interprocess/containers/stable_vector.hpp | 36 + .../boost/interprocess/containers/string.hpp | 37 + .../boost/interprocess/containers/vector.hpp | 37 + .../interprocess/containers/version_type.hpp | 37 + .../boost/interprocess/detail/cast_tags.hpp | 31 + .../detail/file_locking_helpers.hpp | 302 ++++ .../interprocess/detail/file_wrapper.hpp | 233 +++ .../detail/in_place_interface.hpp | 77 + .../detail/intermodule_singleton.hpp | 53 + .../detail/interprocess_tester.hpp | 39 + .../detail/managed_global_memory.hpp | 119 ++ .../detail/managed_memory_impl.hpp | 775 ++++++++++ .../detail/managed_open_or_create_impl.hpp | 574 +++++++ .../interprocess/detail/math_functions.hpp | 118 ++ .../boost/boost/interprocess/detail/move.hpp | 36 + .../boost/interprocess/detail/named_proxy.hpp | 284 ++++ .../boost/interprocess/detail/nothrow.hpp | 42 + .../interprocess/detail/pointer_type.hpp | 78 + .../detail/portable_intermodule_singleton.hpp | 361 +++++ .../interprocess/detail/robust_emulation.hpp | 387 +++++ .../detail/segment_manager_helper.hpp | 503 ++++++ .../detail/transform_iterator.hpp | 44 + .../detail/variadic_templates_tools.hpp | 35 + .../detail/xsi_shared_memory_file_wrapper.hpp | 88 ++ .../boost/boost/interprocess/file_mapping.hpp | 250 +++ .../interprocess/indexes/flat_map_index.hpp | 93 ++ .../boost/interprocess/indexes/iset_index.hpp | 158 ++ .../indexes/iunordered_set_index.hpp | 390 +++++ .../boost/interprocess/indexes/map_index.hpp | 109 ++ .../boost/interprocess/indexes/null_index.hpp | 76 + .../boost/interprocess/ipc/message_queue.hpp | 1131 ++++++++++++++ .../interprocess/managed_external_buffer.hpp | 143 ++ .../interprocess/managed_heap_memory.hpp | 172 +++ .../interprocess/managed_mapped_file.hpp | 370 +++++ .../interprocess/managed_shared_memory.hpp | 388 +++++ .../managed_windows_shared_memory.hpp | 288 ++++ .../managed_xsi_shared_memory.hpp | 251 +++ .../mem_algo/detail/mem_algo_common.hpp | 599 ++++++++ .../mem_algo/detail/simple_seq_fit_impl.hpp | 1107 ++++++++++++++ .../interprocess/mem_algo/rbtree_best_fit.hpp | 1359 +++++++++++++++++ .../interprocess/mem_algo/simple_seq_fit.hpp | 62 + .../boost/boost/interprocess/offset_ptr.hpp | 776 ++++++++++ .../boost/interprocess/segment_manager.hpp | 1357 ++++++++++++++++ .../boost/interprocess/smart_ptr/deleter.hpp | 68 + .../smart_ptr/detail/bad_weak_ptr.hpp | 48 + .../smart_ptr/detail/shared_count.hpp | 347 +++++ .../smart_ptr/detail/sp_counted_base.hpp | 26 + .../detail/sp_counted_base_atomic.hpp | 94 ++ .../smart_ptr/detail/sp_counted_impl.hpp | 164 ++ .../smart_ptr/enable_shared_from_this.hpp | 87 ++ .../interprocess/smart_ptr/intrusive_ptr.hpp | 333 ++++ .../interprocess/smart_ptr/scoped_ptr.hpp | 176 +++ .../interprocess/smart_ptr/shared_ptr.hpp | 430 ++++++ .../interprocess/smart_ptr/unique_ptr.hpp | 63 + .../boost/interprocess/smart_ptr/weak_ptr.hpp | 271 ++++ .../interprocess/streams/vectorstream.hpp | 633 ++++++++ .../boost/interprocess/sync/cv_status.hpp | 29 + .../sync/detail/condition_algorithm_8a.hpp | 389 +++++ .../sync/detail/condition_any_algorithm.hpp | 191 +++ .../boost/interprocess/sync/detail/locks.hpp | 111 ++ .../boost/interprocess/sync/file_lock.hpp | 324 ++++ .../sync/interprocess_condition.hpp | 177 +++ .../sync/interprocess_condition_any.hpp | 154 ++ .../interprocess/sync/interprocess_mutex.hpp | 198 +++ .../sync/interprocess_recursive_mutex.hpp | 184 +++ .../sync/interprocess_semaphore.hpp | 143 ++ .../sync/interprocess_sharable_mutex.hpp | 424 +++++ .../sync/interprocess_upgradable_mutex.hpp | 771 ++++++++++ .../boost/interprocess/sync/mutex_family.hpp | 60 + .../interprocess/sync/named_condition.hpp | 299 ++++ .../interprocess/sync/named_condition_any.hpp | 230 +++ .../boost/interprocess/sync/named_mutex.hpp | 267 ++++ .../sync/named_recursive_mutex.hpp | 245 +++ .../interprocess/sync/named_semaphore.hpp | 239 +++ .../sync/named_sharable_mutex.hpp | 391 +++++ .../sync/named_upgradable_mutex.hpp | 540 +++++++ .../boost/interprocess/sync/null_mutex.hpp | 178 +++ .../interprocess/sync/posix/condition.hpp | 218 +++ .../boost/interprocess/sync/posix/mutex.hpp | 188 +++ .../interprocess/sync/posix/named_mutex.hpp | 126 ++ .../sync/posix/named_semaphore.hpp | 89 ++ .../sync/posix/pthread_helpers.hpp | 176 +++ .../sync/posix/recursive_mutex.hpp | 175 +++ .../interprocess/sync/posix/semaphore.hpp | 67 + .../sync/posix/semaphore_wrapper.hpp | 254 +++ .../sync/posix/timepoint_to_timespec.hpp | 91 ++ .../boost/interprocess/sync/sharable_lock.hpp | 351 +++++ .../interprocess/sync/shm/named_condition.hpp | 348 +++++ .../sync/shm/named_condition_any.hpp | 226 +++ .../sync/shm/named_creation_functor.hpp | 81 + .../interprocess/sync/shm/named_mutex.hpp | 259 ++++ .../sync/shm/named_recursive_mutex.hpp | 249 +++ .../interprocess/sync/shm/named_semaphore.hpp | 198 +++ .../sync/shm/named_upgradable_mutex.hpp | 360 +++++ .../interprocess/sync/spin/condition.hpp | 299 ++++ .../sync/spin/interprocess_barrier.hpp | 53 + .../sync/spin/recursive_mutex.hpp | 185 +++ .../interprocess/sync/spin/semaphore.hpp | 94 ++ .../interprocess/sync/upgradable_lock.hpp | 314 ++++ .../interprocess/sync/windows/condition.hpp | 147 ++ .../boost/interprocess/sync/windows/mutex.hpp | 126 ++ .../sync/windows/named_condition.hpp | 40 + .../sync/windows/named_condition_any.hpp | 337 ++++ .../interprocess/sync/windows/named_mutex.hpp | 232 +++ .../sync/windows/named_recursive_mutex.hpp | 74 + .../sync/windows/named_semaphore.hpp | 230 +++ .../interprocess/sync/windows/named_sync.hpp | 237 +++ .../sync/windows/recursive_mutex.hpp | 47 + .../interprocess/sync/windows/semaphore.hpp | 119 ++ .../interprocess/windows_shared_memory.hpp | 277 ++++ extern/boost/boost/interprocess/xsi_key.hpp | 101 ++ .../boost/interprocess/xsi_shared_memory.hpp | 215 +++ 134 files changed, 32737 insertions(+) create mode 100644 extern/boost/boost/interprocess/allocators/adaptive_pool.hpp create mode 100644 extern/boost/boost/interprocess/allocators/allocator.hpp create mode 100644 extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp create mode 100644 extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp create mode 100644 extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp create mode 100644 extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp create mode 100644 extern/boost/boost/interprocess/allocators/detail/node_pool.hpp create mode 100644 extern/boost/boost/interprocess/allocators/detail/node_tools.hpp create mode 100644 extern/boost/boost/interprocess/allocators/node_allocator.hpp create mode 100644 extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp create mode 100644 extern/boost/boost/interprocess/allocators/private_node_allocator.hpp create mode 100644 extern/boost/boost/interprocess/anonymous_shared_memory.hpp create mode 100644 extern/boost/boost/interprocess/containers/allocation_type.hpp create mode 100644 extern/boost/boost/interprocess/containers/containers_fwd.hpp create mode 100644 extern/boost/boost/interprocess/containers/deque.hpp create mode 100644 extern/boost/boost/interprocess/containers/flat_map.hpp create mode 100644 extern/boost/boost/interprocess/containers/flat_set.hpp create mode 100644 extern/boost/boost/interprocess/containers/list.hpp create mode 100644 extern/boost/boost/interprocess/containers/map.hpp create mode 100644 extern/boost/boost/interprocess/containers/pair.hpp create mode 100644 extern/boost/boost/interprocess/containers/set.hpp create mode 100644 extern/boost/boost/interprocess/containers/slist.hpp create mode 100644 extern/boost/boost/interprocess/containers/stable_vector.hpp create mode 100644 extern/boost/boost/interprocess/containers/string.hpp create mode 100644 extern/boost/boost/interprocess/containers/vector.hpp create mode 100644 extern/boost/boost/interprocess/containers/version_type.hpp create mode 100644 extern/boost/boost/interprocess/detail/cast_tags.hpp create mode 100644 extern/boost/boost/interprocess/detail/file_locking_helpers.hpp create mode 100644 extern/boost/boost/interprocess/detail/file_wrapper.hpp create mode 100644 extern/boost/boost/interprocess/detail/in_place_interface.hpp create mode 100644 extern/boost/boost/interprocess/detail/intermodule_singleton.hpp create mode 100644 extern/boost/boost/interprocess/detail/interprocess_tester.hpp create mode 100644 extern/boost/boost/interprocess/detail/managed_global_memory.hpp create mode 100644 extern/boost/boost/interprocess/detail/managed_memory_impl.hpp create mode 100644 extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp create mode 100644 extern/boost/boost/interprocess/detail/math_functions.hpp create mode 100644 extern/boost/boost/interprocess/detail/move.hpp create mode 100644 extern/boost/boost/interprocess/detail/named_proxy.hpp create mode 100644 extern/boost/boost/interprocess/detail/nothrow.hpp create mode 100644 extern/boost/boost/interprocess/detail/pointer_type.hpp create mode 100644 extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp create mode 100644 extern/boost/boost/interprocess/detail/robust_emulation.hpp create mode 100644 extern/boost/boost/interprocess/detail/segment_manager_helper.hpp create mode 100644 extern/boost/boost/interprocess/detail/transform_iterator.hpp create mode 100644 extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp create mode 100644 extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp create mode 100644 extern/boost/boost/interprocess/file_mapping.hpp create mode 100644 extern/boost/boost/interprocess/indexes/flat_map_index.hpp create mode 100644 extern/boost/boost/interprocess/indexes/iset_index.hpp create mode 100644 extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp create mode 100644 extern/boost/boost/interprocess/indexes/map_index.hpp create mode 100644 extern/boost/boost/interprocess/indexes/null_index.hpp create mode 100644 extern/boost/boost/interprocess/ipc/message_queue.hpp create mode 100644 extern/boost/boost/interprocess/managed_external_buffer.hpp create mode 100644 extern/boost/boost/interprocess/managed_heap_memory.hpp create mode 100644 extern/boost/boost/interprocess/managed_mapped_file.hpp create mode 100644 extern/boost/boost/interprocess/managed_shared_memory.hpp create mode 100644 extern/boost/boost/interprocess/managed_windows_shared_memory.hpp create mode 100644 extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp create mode 100644 extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp create mode 100644 extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp create mode 100644 extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp create mode 100644 extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp create mode 100644 extern/boost/boost/interprocess/offset_ptr.hpp create mode 100644 extern/boost/boost/interprocess/segment_manager.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/deleter.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp create mode 100644 extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp create mode 100644 extern/boost/boost/interprocess/streams/vectorstream.hpp create mode 100644 extern/boost/boost/interprocess/sync/cv_status.hpp create mode 100644 extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp create mode 100644 extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp create mode 100644 extern/boost/boost/interprocess/sync/detail/locks.hpp create mode 100644 extern/boost/boost/interprocess/sync/file_lock.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/mutex_family.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_condition_any.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/null_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/named_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp create mode 100644 extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp create mode 100644 extern/boost/boost/interprocess/sync/sharable_lock.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/spin/condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp create mode 100644 extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/spin/semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/upgradable_lock.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_condition.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/named_sync.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp create mode 100644 extern/boost/boost/interprocess/sync/windows/semaphore.hpp create mode 100644 extern/boost/boost/interprocess/windows_shared_memory.hpp create mode 100644 extern/boost/boost/interprocess/xsi_key.hpp create mode 100644 extern/boost/boost/interprocess/xsi_shared_memory.hpp diff --git a/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp new file mode 100644 index 00000000000..83b9e8d6dce --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp @@ -0,0 +1,470 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes adaptive_pool pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail{ + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class adaptive_pool_base + : public node_pool_allocation_impl + < adaptive_pool_base + < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> + , Version + , T + , SegmentManager + > +{ + public: + typedef typename SegmentManager::void_pointer void_pointer; + typedef SegmentManager segment_manager; + typedef adaptive_pool_base + self_t; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + template + struct node_pool + { + typedef ipcdetail::shared_adaptive_node_pool + < SegmentManager, sizeof_value::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type; + + static type *get(void *p) + { return static_cast(p); } + }; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + BOOST_STATIC_ASSERT((Version <=2)); + + public: + //------- + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + typedef boost::interprocess::version_type version; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + //!Obtains adaptive_pool_base from + //!adaptive_pool_base + template + struct rebind + { + typedef adaptive_pool_base other; + }; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + //!Not assignable from related adaptive_pool_base + template + adaptive_pool_base& operator= + (const adaptive_pool_base&); + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + adaptive_pool_base(segment_manager *segment_mngr) + : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(segment_mngr)) { } + + //!Copy constructor from other adaptive_pool_base. Increments the reference + //!count of the associated node pool. Never throws + adaptive_pool_base(const adaptive_pool_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + } + + //!Assignment from other adaptive_pool_base + adaptive_pool_base& operator=(const adaptive_pool_base &other) + { + adaptive_pool_base c(other); + boost::adl_move_swap(*this, c); + return *this; + } + + //!Copy constructor from related adaptive_pool_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + adaptive_pool_base + (const adaptive_pool_base &other) + : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(other.get_segment_manager())) { } + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~adaptive_pool_base() + { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const + { return ipcdetail::to_raw_pointer(mp_node_pool); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + void_pointer mp_node_pool; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Equality test for same type +//!of adaptive_pool_base +template inline +bool operator==(const adaptive_pool_base &alloc1, + const adaptive_pool_base &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type +//!of adaptive_pool_base +template inline +bool operator!=(const adaptive_pool_base &alloc1, + const adaptive_pool_base &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class adaptive_pool_v1 + : public adaptive_pool_base + < 1 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > +{ + public: + typedef ipcdetail::adaptive_pool_base + < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + + template + struct rebind + { + typedef adaptive_pool_v1 other; + }; + + adaptive_pool_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + adaptive_pool_v1 + (const adaptive_pool_v1 &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail{ + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//! +//!This node allocator shares a segregated storage between all instances +//!of adaptive_pool with equal sizeof(T) placed in the same segment +//!group. NodesPerBlock is the number of nodes allocated at once when the allocator +//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class adaptive_pool + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::adaptive_pool_base + < 2 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef ipcdetail::adaptive_pool_base + < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + public: + typedef boost::interprocess::version_type version; + + template + struct rebind + { + typedef adaptive_pool other; + }; + + adaptive_pool(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + adaptive_pool + (const adaptive_pool &other) + : base_t(other) + {} + + #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + //!Obtains adaptive_pool from + //!adaptive_pool + template + struct rebind + { + typedef adaptive_pool other; + }; + + private: + //!Not assignable from + //!related adaptive_pool + template + adaptive_pool& operator= + (const adaptive_pool&); + + //!Not assignable from + //!other adaptive_pool + //adaptive_pool& operator=(const adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + adaptive_pool(const adaptive_pool &other); + + //!Copy constructor from related adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + adaptive_pool + (const adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; +/* + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); +*/ + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of adaptive_pool +template inline +bool operator==(const adaptive_pool &alloc1, + const adaptive_pool &alloc2); + +//!Inequality test for same type +//!of adaptive_pool +template inline +bool operator!=(const adaptive_pool &alloc1, + const adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP + diff --git a/extern/boost/boost/interprocess/allocators/allocator.hpp b/extern/boost/boost/interprocess/allocators/allocator.hpp new file mode 100644 index 00000000000..127df774f54 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/allocator.hpp @@ -0,0 +1,294 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (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_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_ALLOCATOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//!\file +//!Describes an allocator that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace interprocess { + + +//!An STL compatible allocator that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +template +class allocator +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + //Self type + typedef allocator self_t; + + //Pointer to void + typedef typename segment_manager::void_pointer aux_pointer_t; + + //Typedef to const void pointer + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type cvoid_ptr; + + //Pointer to the allocator + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type alloc_ptr_t; + + //Not assignable from related allocator + template + allocator& operator=(const allocator&); + + //Not assignable from other allocator + allocator& operator=(const allocator&); + + //Pointer to the allocator + alloc_ptr_t mp_mngr; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef T value_type; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + typedef boost::interprocess::version_type version; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Experimental. Don't use. + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Obtains an allocator that allocates + //!objects of type T2 + template + struct rebind + { + typedef allocator other; + }; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return ipcdetail::to_raw_pointer(mp_mngr); } + + //!Constructor from the segment manager. + //!Never throws + allocator(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other allocator. + //!Never throws + allocator(const allocator &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related allocator. + //!Never throws + template + allocator(const allocator &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { + (void)hint; + if(size_overflows(count)){ + throw bad_alloc(); + } + return pointer(static_cast(mp_mngr->allocate(count*sizeof(T)))); + } + + //!Deallocates memory previously allocated. + //!Never throws + void deallocate(const pointer &ptr, size_type) + { mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); } + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const + { return mp_mngr->get_size()/sizeof(T); } + + //!Swap segment manager. Does not throw. If each allocator is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { boost::adl_move_swap(alloc1.mp_mngr, alloc2.mp_mngr); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const + { + return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T); + } + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) + { + value_type *reuse_raw = ipcdetail::to_raw_pointer(reuse); + pointer const p = mp_mngr->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse_raw); + reuse = reuse_raw; + return p; + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) + { + if(size_overflows(elem_size)){ + throw bad_alloc(); + } + mp_mngr->allocate_many(elem_size*sizeof(T), num_elements, chain); + } + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) + { + mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T), chain); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain) + { mp_mngr->deallocate_many(chain); } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return this->allocate(1); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain) + { this->allocate_many(1, num_elements, chain); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { return this->deallocate(p, 1); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain) + { this->deallocate_many(chain); } + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const + { return pointer(boost::addressof(value)); } + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const + { return const_pointer(boost::addressof(value)); } +}; + +//!Equality test for same type +//!of allocator +template inline +bool operator==(const allocator &alloc1, + const allocator &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type +//!of allocator +template inline +bool operator!=(const allocator &alloc1, + const allocator &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +struct has_trivial_destructor; + +template +struct has_trivial_destructor + > +{ + static const bool value = true; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP + diff --git a/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp new file mode 100644 index 00000000000..0ccf1f3638e --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -0,0 +1,357 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CACHED_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail { + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class cached_adaptive_pool_v1 + : public ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 1> +{ + public: + typedef ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 1> base_t; + + template + struct rebind + { + typedef cached_adaptive_pool_v1 + other; + }; + + typedef typename base_t::size_type size_type; + + cached_adaptive_pool_v1(SegmentManager *segment_mngr, + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_adaptive_pool_v1 + (const cached_adaptive_pool_v1 + &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail{ + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//! +//!This node allocator shares a segregated storage between all instances of +//!cached_adaptive_pool with equal sizeof(T) placed in the same +//!memory segment. But also caches some nodes privately to +//!avoid some synchronization overhead. +//! +//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when +//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class cached_adaptive_pool + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 2> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 2> base_t; + + public: + typedef boost::interprocess::version_type version; + + template + struct rebind + { + typedef cached_adaptive_pool + other; + }; + + cached_adaptive_pool(SegmentManager *segment_mngr, + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_adaptive_pool + (const cached_adaptive_pool &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + //!Obtains cached_adaptive_pool from + //!cached_adaptive_pool + template + struct rebind + { + typedef cached_adaptive_pool other; + }; + + private: + //!Not assignable from + //!related cached_adaptive_pool + template + cached_adaptive_pool& operator= + (const cached_adaptive_pool&); + + //!Not assignable from + //!other cached_adaptive_pool + cached_adaptive_pool& operator=(const cached_adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + cached_adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other cached_adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + cached_adaptive_pool(const cached_adaptive_pool &other); + + //!Copy constructor from related cached_adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_adaptive_pool + (const cached_adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~cached_adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_chain allocate_individual(size_type num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain); + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(size_type newmax); + + //!Returns the max cached nodes parameter. + //!Never throws + size_type get_max_cached_nodes() const; + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of cached_adaptive_pool +template inline +bool operator==(const cached_adaptive_pool &alloc1, + const cached_adaptive_pool &alloc2); + +//!Inequality test for same type +//!of cached_adaptive_pool +template inline +bool operator!=(const cached_adaptive_pool &alloc1, + const cached_adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP + diff --git a/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp b/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp new file mode 100644 index 00000000000..4eff061b0a3 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp @@ -0,0 +1,328 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CACHED_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail { + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class cached_node_allocator_v1 + : public ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 1> +{ + public: + typedef ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 1> base_t; + + template + struct rebind + { + typedef cached_node_allocator_v1 + other; + }; + + typedef typename base_t::size_type size_type; + + cached_node_allocator_v1(SegmentManager *segment_mngr, + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_node_allocator_v1 + (const cached_node_allocator_v1 + &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail{ + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class cached_node_allocator + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 2> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef ipcdetail::cached_allocator_impl + < T + , ipcdetail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 2> base_t; + + public: + typedef boost::interprocess::version_type version; + typedef typename base_t::size_type size_type; + + template + struct rebind + { + typedef cached_node_allocator other; + }; + + cached_node_allocator(SegmentManager *segment_mngr, + size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_node_allocator + (const cached_node_allocator &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename SegmentManager::size_type size_type; + typedef typename SegmentManager::difference_type difference_type; + + //!Obtains cached_node_allocator from + //!cached_node_allocator + template + struct rebind + { + typedef cached_node_allocator other; + }; + + private: + //!Not assignable from + //!related cached_node_allocator + template + cached_node_allocator& operator= + (const cached_node_allocator&); + + //!Not assignable from + //!other cached_node_allocator + cached_node_allocator& operator=(const cached_node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + cached_node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other cached_node_allocator. Increments the reference + //!count of the associated node pool. Never throws + cached_node_allocator(const cached_node_allocator &other); + + //!Copy constructor from related cached_node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_node_allocator + (const cached_node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~cached_node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Default construct an object. + //!Throws if T's default constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_chain allocate_individual(size_type num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain it); + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(size_type newmax); + + //!Returns the max cached nodes parameter. + //!Never throws + size_type get_max_cached_nodes() const; + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of cached_node_allocator +template inline +bool operator==(const cached_node_allocator &alloc1, + const cached_node_allocator &alloc2); + +//!Inequality test for same type +//!of cached_node_allocator +template inline +bool operator!=(const cached_node_allocator &alloc1, + const cached_node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP + diff --git a/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp new file mode 100644 index 00000000000..e9a8e2655cf --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp @@ -0,0 +1,115 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ADAPTIVE_NODE_POOL_HPP +#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the real adaptive pool shared by many Interprocess pool allocators + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_node_pool + : public boost::container::dtl::private_adaptive_node_pool_impl_rt + < typename SegmentManager::segment_manager_base_type + , ::boost::container::adaptive_pool_flag::size_ordered | + ::boost::container::adaptive_pool_flag::address_ordered + > +{ + typedef boost::container::dtl::private_adaptive_node_pool_impl_rt + < typename SegmentManager::segment_manager_base_type + , ::boost::container::adaptive_pool_flag::size_ordered | + ::boost::container::adaptive_pool_flag::address_ordered + > base_t; + //Non-copyable + private_adaptive_node_pool(); + private_adaptive_node_pool(const private_adaptive_node_pool &); + private_adaptive_node_pool &operator=(const private_adaptive_node_pool &); + + public: + typedef SegmentManager segment_manager; + typedef typename base_t::size_type size_type; + + static const size_type nodes_per_block = NodesPerBlock; + + //!Constructor from a segment manager. Never throws + private_adaptive_node_pool(segment_manager *segment_mngr) + : base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent) + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager() const + { return static_cast(base_t::get_segment_manager_base()); } +}; + +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class shared_adaptive_node_pool + : public ipcdetail::shared_pool_impl + < private_adaptive_node_pool + + > +{ + typedef ipcdetail::shared_pool_impl + < private_adaptive_node_pool + + > base_t; + public: + shared_adaptive_node_pool(SegmentManager *segment_mgnr) + : base_t(segment_mgnr) + {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp b/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp new file mode 100644 index 00000000000..bb301ebfbb8 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp @@ -0,0 +1,857 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP +#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include //to_raw_pointer +#include //boost::addressof +#include //BOOST_ASSERT +#include //bad_alloc +#include //scoped_lock +#include //boost::interprocess::allocation_type +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +template +struct sizeof_value +{ + static const std::size_t value = sizeof(T); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +namespace ipcdetail { + +//!Object function that creates the node allocator if it is not created and +//!increments reference count if it is already created +template +struct get_or_create_node_pool_func +{ + + //!This connects or constructs the unique instance of node_pool_t + //!Can throw boost::interprocess::bad_alloc + void operator()() + { + //Find or create the node_pool_t + mp_node_pool = mp_segment_manager->template find_or_construct + (boost::interprocess::unique_instance)(mp_segment_manager); + //If valid, increment link count + if(mp_node_pool != 0) + mp_node_pool->inc_ref_count(); + } + + //!Constructor. Initializes function + //!object parameters + get_or_create_node_pool_func(typename NodePool::segment_manager *mngr) + : mp_segment_manager(mngr){} + + NodePool *mp_node_pool; + typename NodePool::segment_manager *mp_segment_manager; +}; + +template +inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr) +{ + ipcdetail::get_or_create_node_pool_func func(mgnr); + mgnr->atomic_func(func); + return func.mp_node_pool; +} + +//!Object function that decrements the reference count. If the count +//!reaches to zero destroys the node allocator from memory. +//!Never throws +template +struct destroy_if_last_link_func +{ + //!Decrements reference count and destroys the object if there is no + //!more attached allocators. Never throws + void operator()() + { + //If not the last link return + if(mp_node_pool->dec_ref_count() != 0) return; + + //Last link, let's destroy the segment_manager + mp_node_pool->get_segment_manager()->template destroy(boost::interprocess::unique_instance); + } + + //!Constructor. Initializes function + //!object parameters + destroy_if_last_link_func(NodePool *pool) + : mp_node_pool(pool) + {} + + NodePool *mp_node_pool; +}; + +//!Destruction function, initializes and executes destruction function +//!object. Never throws +template +inline void destroy_node_pool_if_last_link(NodePool *pool) +{ + //Get segment manager + typename NodePool::segment_manager *mngr = pool->get_segment_manager(); + //Execute destruction functor atomically + destroy_if_last_link_funcfunc(pool); + mngr->atomic_func(func); +} + +template +class cache_impl +{ + typedef typename NodePool::segment_manager:: + void_pointer void_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type node_pool_ptr; + typedef typename NodePool::multiallocation_chain multiallocation_chain; + typedef typename NodePool::segment_manager::size_type size_type; + node_pool_ptr mp_node_pool; + multiallocation_chain m_cached_nodes; + size_type m_max_cached_nodes; + + public: + typedef typename NodePool::segment_manager segment_manager; + + cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes) + : mp_node_pool(get_or_create_node_pool(segment_mngr)) + , m_max_cached_nodes(max_cached_nodes) + {} + + cache_impl(const cache_impl &other) + : mp_node_pool(other.get_node_pool()) + , m_max_cached_nodes(other.get_max_cached_nodes()) + { + mp_node_pool->inc_ref_count(); + } + + ~cache_impl() + { + this->deallocate_all_cached_nodes(); + ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); + } + + NodePool *get_node_pool() const + { return ipcdetail::to_raw_pointer(mp_node_pool); } + + segment_manager *get_segment_manager() const + { return mp_node_pool->get_segment_manager(); } + + size_type get_max_cached_nodes() const + { return m_max_cached_nodes; } + + void *cached_allocation() + { + //If don't have any cached node, we have to get a new list of free nodes from the pool + if(m_cached_nodes.empty()){ + mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes); + } + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); + return ret; + } + + void cached_allocation(size_type n, multiallocation_chain &chain) + { + size_type count = n, allocated(0); + BOOST_TRY{ + //If don't have any cached node, we have to get a new list of free nodes from the pool + while(!m_cached_nodes.empty() && count--){ + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); + chain.push_back(ret); + ++allocated; + } + + if(allocated != n){ + mp_node_pool->allocate_nodes(n - allocated, chain); + } + } + BOOST_CATCH(...){ + this->cached_deallocation(chain); + BOOST_RETHROW + } BOOST_CATCH_END + } + + void cached_deallocation(void *ptr) + { + //Check if cache is full + if(m_cached_nodes.size() >= m_max_cached_nodes){ + //This only occurs if this allocator deallocate memory allocated + //with other equal allocator. Since the cache is full, and more + //deallocations are probably coming, we'll make some room in cache + //in a single, efficient multi node deallocation. + this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); + } + m_cached_nodes.push_front(ptr); + } + + void cached_deallocation(multiallocation_chain &chain) + { + m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain); + + //Check if cache is full + if(m_cached_nodes.size() >= m_max_cached_nodes){ + //This only occurs if this allocator deallocate memory allocated + //with other equal allocator. Since the cache is full, and more + //deallocations are probably coming, we'll make some room in cache + //in a single, efficient multi node deallocation. + this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); + } + } + + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(size_type newmax) + { + m_max_cached_nodes = newmax; + this->priv_deallocate_remaining_nodes(); + } + + //!Frees all cached nodes. + //!Never throws + void deallocate_all_cached_nodes() + { + if(m_cached_nodes.empty()) return; + mp_node_pool->deallocate_nodes(m_cached_nodes); + } + + private: + //!Frees all cached nodes at once. + //!Never throws + void priv_deallocate_remaining_nodes() + { + if(m_cached_nodes.size() > m_max_cached_nodes){ + priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes); + } + } + + //!Frees n cached nodes at once. Never throws + void priv_deallocate_n_nodes(size_type n) + { + //This only occurs if this allocator deallocate memory allocated + //with other equal allocator. Since the cache is full, and more + //deallocations are probably coming, we'll make some room in cache + //in a single, efficient multi node deallocation. + size_type count(n); + typename multiallocation_chain::iterator it(m_cached_nodes.before_begin()); + while(count--){ + ++it; + } + multiallocation_chain chain; + chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n); + //Deallocate all new linked list at once + mp_node_pool->deallocate_nodes(chain); + } + + public: + void swap(cache_impl &other) + { + ::boost::adl_move_swap(mp_node_pool, other.mp_node_pool); + ::boost::adl_move_swap(m_cached_nodes, other.m_cached_nodes); + ::boost::adl_move_swap(m_max_cached_nodes, other.m_max_cached_nodes); + } +}; + +template +class array_allocation_impl +{ + const Derived *derived() const + { return static_cast(this); } + Derived *derived() + { return static_cast(this); } + + typedef typename SegmentManager::void_pointer void_pointer; + + public: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename SegmentManager::size_type size_type; + typedef typename SegmentManager::difference_type difference_type; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + + public: + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const + { + return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T); + } + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) + { + value_type *reuse_raw = ipcdetail::to_raw_pointer(reuse); + pointer const p = this->derived()->get_segment_manager()->allocation_command + (command, limit_size, prefer_in_recvd_out_size, reuse_raw); + reuse = reuse_raw; + return p; + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) + { + if(size_overflows(elem_size)){ + throw bad_alloc(); + } + this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain); + } + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) + { + this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain) + { this->derived()->get_segment_manager()->deallocate_many(chain); } + + //!Returns the number of elements that could be + //!allocated. Never throws + size_type max_size() const + { return this->derived()->get_segment_manager()->get_size()/sizeof(T); } + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const + { return pointer(boost::addressof(value)); } + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const + { return const_pointer(boost::addressof(value)); } + + //!Constructs an object + //!Throws if T's constructor throws + //!For backwards compatibility with libraries using C++03 allocators + template + void construct(const pointer &ptr, BOOST_FWD_REF(P) p) + { ::new((void*)ipcdetail::to_raw_pointer(ptr), boost_container_new_t()) value_type(::boost::forward

(p)); } + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr) + { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } +}; + + +template +class node_pool_allocation_impl + : public array_allocation_impl + < Derived + , T + , SegmentManager> +{ + const Derived *derived() const + { return static_cast(this); } + Derived *derived() + { return static_cast(this); } + + typedef typename SegmentManager::void_pointer void_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type cvoid_pointer; + + public: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename SegmentManager::size_type size_type; + typedef typename SegmentManager::difference_type difference_type; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + + template + struct node_pool + { + typedef typename Derived::template node_pool<0>::type type; + static type *get(void *p) + { return static_cast(p); } + }; + + public: + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0) + { + (void)hint; + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + if(size_overflows(count)){ + throw bad_alloc(); + } + else if(Version == 1 && count == 1){ + return pointer(static_cast + (pool->allocate_node())); + } + else{ + return pointer(static_cast + (pool->get_segment_manager()->allocate(count*sizeof(T)))); + } + } + + //!Deallocate allocated memory. Never throws + void deallocate(const pointer &ptr, size_type count) + { + (void)count; + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + if(Version == 1 && count == 1) + pool->deallocate_node(ipcdetail::to_raw_pointer(ptr)); + else + pool->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); + } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + return pointer(static_cast(pool->allocate_node())); + } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain) + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + pool->allocate_nodes(num_elements, chain); + } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + pool->deallocate_node(ipcdetail::to_raw_pointer(p)); + } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain) + { + node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes + (chain); + } + + //!Deallocates all free blocks of the pool + void deallocate_free_blocks() + { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } + + //!Deprecated, use deallocate_free_blocks. + //!Deallocates all free chunks of the pool. + void deallocate_free_chunks() + { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } +}; + +template +class cached_allocator_impl + : public array_allocation_impl + , T, typename NodePool::segment_manager> +{ + cached_allocator_impl & operator=(const cached_allocator_impl& other); + typedef array_allocation_impl + < cached_allocator_impl + + , T + , typename NodePool::segment_manager> base_t; + + public: + typedef NodePool node_pool_t; + typedef typename NodePool::segment_manager segment_manager; + typedef typename segment_manager::void_pointer void_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type cvoid_pointer; + typedef typename base_t::pointer pointer; + typedef typename base_t::size_type size_type; + typedef typename base_t::multiallocation_chain multiallocation_chain; + typedef typename base_t::value_type value_type; + + public: + static const std::size_t DEFAULT_MAX_CACHED_NODES = 64; + + cached_allocator_impl(segment_manager *segment_mngr, size_type max_cached_nodes) + : m_cache(segment_mngr, max_cached_nodes) + {} + + cached_allocator_impl(const cached_allocator_impl &other) + : m_cache(other.m_cache) + {} + + //!Copy constructor from related cached_adaptive_pool_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_allocator_impl + (const cached_allocator_impl + &other) + : m_cache(other.get_segment_manager(), other.get_max_cached_nodes()) + {} + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const + { return m_cache.get_node_pool(); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return m_cache.get_segment_manager(); } + + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(size_type newmax) + { m_cache.set_max_cached_nodes(newmax); } + + //!Returns the max cached nodes parameter. + //!Never throws + size_type get_max_cached_nodes() const + { return m_cache.get_max_cached_nodes(); } + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0) + { + (void)hint; + void * ret; + if(size_overflows(count)){ + throw bad_alloc(); + } + else if(Version == 1 && count == 1){ + ret = m_cache.cached_allocation(); + } + else{ + ret = this->get_segment_manager()->allocate(count*sizeof(T)); + } + return pointer(static_cast(ret)); + } + + //!Deallocate allocated memory. Never throws + void deallocate(const pointer &ptr, size_type count) + { + (void)count; + if(Version == 1 && count == 1){ + m_cache.cached_deallocation(ipcdetail::to_raw_pointer(ptr)); + } + else{ + this->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); + } + } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return pointer(static_cast(this->m_cache.cached_allocation())); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain) + { this->m_cache.cached_allocation(num_elements, chain); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain) + { m_cache.cached_deallocation(chain); } + + //!Deallocates all free blocks of the pool + void deallocate_free_blocks() + { m_cache.get_node_pool()->deallocate_free_blocks(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2) + { ::boost::adl_move_swap(alloc1.m_cache, alloc2.m_cache); } + + void deallocate_cache() + { m_cache.deallocate_all_cached_nodes(); } + + //!Deprecated use deallocate_free_blocks. + void deallocate_free_chunks() + { m_cache.get_node_pool()->deallocate_free_blocks(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + cache_impl m_cache; + #endif //!defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +}; + +//!Equality test for same type of +//!cached_allocator_impl +template inline +bool operator==(const cached_allocator_impl &alloc1, + const cached_allocator_impl &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type of +//!cached_allocator_impl +template inline +bool operator!=(const cached_allocator_impl &alloc1, + const cached_allocator_impl &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + + +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template +class shared_pool_impl + : public private_node_allocator_t +{ + public: + //!Segment manager typedef + typedef typename private_node_allocator_t:: + segment_manager segment_manager; + typedef typename private_node_allocator_t:: + multiallocation_chain multiallocation_chain; + typedef typename private_node_allocator_t:: + size_type size_type; + + private: + typedef typename segment_manager::mutex_family::mutex_type mutex_type; + + public: + //!Constructor from a segment manager. Never throws + shared_pool_impl(segment_manager *segment_mngr) + : private_node_allocator_t(segment_mngr) + {} + + //!Destructor. Deallocates all allocated blocks. Never throws + ~shared_pool_impl() + {} + + //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc + void *allocate_node() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return private_node_allocator_t::allocate_node(); + } + + //!Deallocates an array pointed by ptr. Never throws + void deallocate_node(void *ptr) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_node(ptr); + } + + //!Allocates n nodes. + //!Can throw boost::interprocess::bad_alloc + void allocate_nodes(const size_type n, multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::allocate_nodes(n, chain); + } + + //!Deallocates a linked list of nodes ending in null pointer. Never throws + void deallocate_nodes(multiallocation_chain &nodes, size_type num) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_nodes(nodes, num); + } + + //!Deallocates the nodes pointed by the multiallocation iterator. Never throws + void deallocate_nodes(multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_nodes(chain); + } + + //!Deallocates all the free blocks of memory. Never throws + void deallocate_free_blocks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_free_blocks(); + } + + //!Deallocates all used memory from the common pool. + //!Precondition: all nodes allocated from this pool should + //!already be deallocated. Otherwise, undefined behavior. Never throws + void purge_blocks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::purge_blocks(); + } + + //!Increments internal reference count and returns new count. Never throws + size_type inc_ref_count() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return ++m_header.m_usecount; + } + + //!Decrements internal reference count and returns new count. Never throws + size_type dec_ref_count() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + BOOST_ASSERT(m_header.m_usecount > 0); + return --m_header.m_usecount; + } + + //!Deprecated, use deallocate_free_blocks. + void deallocate_free_chunks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_free_blocks(); + } + + //!Deprecated, use purge_blocks. + void purge_chunks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::purge_blocks(); + } + + private: + //!This struct includes needed data and derives from + //!the mutex type to allow EBO when using null_mutex + struct header_t : mutex_type + { + size_type m_usecount; //Number of attached allocators + + header_t() + : m_usecount(0) {} + } m_header; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp b/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp new file mode 100644 index 00000000000..552410ad597 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp @@ -0,0 +1,111 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NODE_POOL_HPP +#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include + + +//!\file +//!Describes the real adaptive pool shared by many Interprocess adaptive pool allocators + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +//!Pooled shared memory allocator using single segregated storage. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > +class private_node_pool + //Inherit from the implementation to avoid template bloat + : public boost::container::dtl:: + private_node_pool_impl +{ + typedef boost::container::dtl::private_node_pool_impl + base_t; + //Non-copyable + private_node_pool(); + private_node_pool(const private_node_pool &); + private_node_pool &operator=(const private_node_pool &); + + public: + typedef SegmentManager segment_manager; + typedef typename base_t::size_type size_type; + + static const size_type nodes_per_block = NodesPerBlock; + //Deprecated, use nodes_per_block + static const size_type nodes_per_chunk = NodesPerBlock; + + //!Constructor from a segment manager. Never throws + private_node_pool(segment_manager *segment_mngr) + : base_t(segment_mngr, NodeSize, NodesPerBlock) + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager() const + { return static_cast(base_t::get_segment_manager_base()); } +}; + + +//!Pooled shared memory allocator using single segregated storage. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + > +class shared_node_pool + : public ipcdetail::shared_pool_impl + < private_node_pool + + > +{ + typedef ipcdetail::shared_pool_impl + < private_node_pool + + > base_t; + public: + shared_node_pool(SegmentManager *segment_mgnr) + : base_t(segment_mgnr) + {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp b/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp new file mode 100644 index 00000000000..7f5a4f515c5 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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_NODE_TOOLS_HPP +#define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + +template +struct node_slist +{ + //This hook will be used to chain the individual nodes + typedef typename bi::make_slist_base_hook + , bi::link_mode >::type slist_hook_t; + + //A node object will hold node_t when it's not allocated + struct node_t + : public slist_hook_t + {}; + + typedef typename bi::make_slist + , bi::base_hook >::type node_slist_t; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP diff --git a/extern/boost/boost/interprocess/allocators/node_allocator.hpp b/extern/boost/boost/interprocess/allocators/node_allocator.hpp new file mode 100644 index 00000000000..34af80c711e --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/node_allocator.hpp @@ -0,0 +1,454 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes node_allocator pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail{ + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class node_allocator_base + : public node_pool_allocation_impl + < node_allocator_base + < Version, T, SegmentManager, NodesPerBlock> + , Version + , T + , SegmentManager + > +{ + public: + typedef typename SegmentManager::void_pointer void_pointer; + typedef SegmentManager segment_manager; + typedef node_allocator_base + self_t; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + template + struct node_pool + { + typedef ipcdetail::shared_node_pool + < SegmentManager, sizeof_value::value, NodesPerBlock> type; + + static type *get(void *p) + { return static_cast(p); } + }; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + BOOST_STATIC_ASSERT((Version <=2)); + + public: + //------- + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + typedef boost::interprocess::version_type version; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + //!Obtains node_allocator_base from + //!node_allocator_base + template + struct rebind + { + typedef node_allocator_base other; + }; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + //!Not assignable from related node_allocator_base + template + node_allocator_base& operator= + (const node_allocator_base&); + + //!Not assignable from other node_allocator_base + //node_allocator_base& operator=(const node_allocator_base&); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + node_allocator_base(segment_manager *segment_mngr) + : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(segment_mngr)) { } + + //!Copy constructor from other node_allocator_base. Increments the reference + //!count of the associated node pool. Never throws + node_allocator_base(const node_allocator_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + } + + //!Copy constructor from related node_allocator_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + node_allocator_base + (const node_allocator_base &other) + : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(other.get_segment_manager())) { } + + //!Assignment from other node_allocator_base + node_allocator_base& operator=(const node_allocator_base &other) + { + node_allocator_base c(other); + boost::adl_move_swap(*this, c); + return *this; + } + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~node_allocator_base() + { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const + { return ipcdetail::to_raw_pointer(mp_node_pool); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + void_pointer mp_node_pool; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Equality test for same type +//!of node_allocator_base +template inline +bool operator==(const node_allocator_base &alloc1, + const node_allocator_base &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type +//!of node_allocator_base +template inline +bool operator!=(const node_allocator_base &alloc1, + const node_allocator_base &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class node_allocator_v1 + : public node_allocator_base + < 1 + , T + , SegmentManager + , NodesPerBlock + > +{ + public: + typedef ipcdetail::node_allocator_base + < 1, T, SegmentManager, NodesPerBlock> base_t; + + template + struct rebind + { + typedef node_allocator_v1 other; + }; + + node_allocator_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + node_allocator_v1 + (const node_allocator_v1 &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail{ + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This node allocator shares a segregated storage between all instances +//!of node_allocator with equal sizeof(T) placed in the same segment +//!group. NodesPerBlock is the number of nodes allocated at once when the allocator +//!runs out of nodes +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class node_allocator + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::node_allocator_base + < 2 + , T + , SegmentManager + , NodesPerBlock + > + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef ipcdetail::node_allocator_base + < 2, T, SegmentManager, NodesPerBlock> base_t; + public: + typedef boost::interprocess::version_type version; + + template + struct rebind + { + typedef node_allocator other; + }; + + node_allocator(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + node_allocator + (const node_allocator &other) + : base_t(other) + {} + + #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + //!Obtains node_allocator from + //!node_allocator + template + struct rebind + { + typedef node_allocator other; + }; + + private: + //!Not assignable from + //!related node_allocator + template + node_allocator& operator= + (const node_allocator&); + + //!Not assignable from + //!other node_allocator + //node_allocator& operator=(const node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other node_allocator. Increments the reference + //!count of the associated node pool. Never throws + node_allocator(const node_allocator &other); + + //!Copy constructor from related node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + node_allocator + (const node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of node_allocator +template inline +bool operator==(const node_allocator &alloc1, + const node_allocator &alloc2); + +//!Inequality test for same type +//!of node_allocator +template inline +bool operator!=(const node_allocator &alloc1, + const node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP diff --git a/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp new file mode 100644 index 00000000000..a6da71e58ab --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -0,0 +1,470 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_PRIVATE_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail { + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_pool_base + : public node_pool_allocation_impl + < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock + , MaxFreeBlocks, OverheadPercent> + , Version + , T + , SegmentManager + > +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef private_adaptive_pool_base + < Version, T, SegmentManager, NodesPerBlock + , MaxFreeBlocks, OverheadPercent> self_t; + typedef ipcdetail::private_adaptive_node_pool + ::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > node_pool_t; + + BOOST_STATIC_ASSERT((Version <=2)); + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + typedef boost::interprocess::version_type + version; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + //!Obtains node_allocator from other node_allocator + template + struct rebind + { + typedef private_adaptive_pool_base + other; + }; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + template + struct node_pool + { + typedef ipcdetail::private_adaptive_node_pool + ::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > type; + + static type *get(void *p) + { return static_cast(p); } + }; + + private: + //!Not assignable from related private_adaptive_pool_base + template + private_adaptive_pool_base& operator= + (const private_adaptive_pool_base&); + + //!Not assignable from other private_adaptive_pool_base + private_adaptive_pool_base& operator=(const private_adaptive_pool_base&); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor from a segment manager + private_adaptive_pool_base(segment_manager *segment_mngr) + : m_node_pool(segment_mngr) + {} + + //!Copy constructor from other private_adaptive_pool_base. Never throws + private_adaptive_pool_base(const private_adaptive_pool_base &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Copy constructor from related private_adaptive_pool_base. Never throws. + template + private_adaptive_pool_base + (const private_adaptive_pool_base + &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Destructor, frees all used memory. Never throws + ~private_adaptive_pool_base() + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return m_node_pool.get_segment_manager(); } + + //!Returns the internal node pool. Never throws + node_pool_t* get_node_pool() const + { return const_cast(&m_node_pool); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(self_t &alloc1,self_t &alloc2) + { boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + node_pool_t m_node_pool; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Equality test for same type of private_adaptive_pool_base +template inline +bool operator==(const private_adaptive_pool_base &alloc1, + const private_adaptive_pool_base &alloc2) +{ return &alloc1 == &alloc2; } + +//!Inequality test for same type of private_adaptive_pool_base +template inline +bool operator!=(const private_adaptive_pool_base &alloc1, + const private_adaptive_pool_base &alloc2) +{ return &alloc1 != &alloc2; } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class private_adaptive_pool_v1 + : public private_adaptive_pool_base + < 1 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > +{ + public: + typedef ipcdetail::private_adaptive_pool_base + < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + + template + struct rebind + { + typedef private_adaptive_pool_v1 other; + }; + + private_adaptive_pool_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_adaptive_pool_v1 + (const private_adaptive_pool_v1 &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail { + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This allocator has its own node pool. +//! +//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when +//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_pool + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::private_adaptive_pool_base + < 2 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef ipcdetail::private_adaptive_pool_base + < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + public: + typedef boost::interprocess::version_type version; + + template + struct rebind + { + typedef private_adaptive_pool + other; + }; + + private_adaptive_pool(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_adaptive_pool + (const private_adaptive_pool &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + //!Obtains private_adaptive_pool from + //!private_adaptive_pool + template + struct rebind + { + typedef private_adaptive_pool + other; + }; + + private: + //!Not assignable from + //!related private_adaptive_pool + template + private_adaptive_pool& operator= + (const private_adaptive_pool&); + + //!Not assignable from + //!other private_adaptive_pool + private_adaptive_pool& operator=(const private_adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + private_adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other private_adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + private_adaptive_pool(const private_adaptive_pool &other); + + //!Copy constructor from related private_adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + private_adaptive_pool + (const private_adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~private_adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of private_adaptive_pool +template inline +bool operator==(const private_adaptive_pool &alloc1, + const private_adaptive_pool &alloc2); + +//!Inequality test for same type +//!of private_adaptive_pool +template inline +bool operator!=(const private_adaptive_pool &alloc1, + const private_adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP + diff --git a/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp b/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp new file mode 100644 index 00000000000..703e0d74e52 --- /dev/null +++ b/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp @@ -0,0 +1,447 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_PRIVATE_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes private_node_allocator_base pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail { + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class private_node_allocator_base + : public node_pool_allocation_impl + < private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock> + , Version + , T + , SegmentManager + > +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef private_node_allocator_base + < Version, T, SegmentManager, NodesPerBlock> self_t; + typedef ipcdetail::private_node_pool + ::value + , NodesPerBlock + > node_pool_t; + + BOOST_STATIC_ASSERT((Version <=2)); + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + typedef boost::interprocess::version_type + version; + typedef boost::container::dtl::transform_multiallocation_chain + multiallocation_chain; + + //!Obtains node_allocator from other node_allocator + template + struct rebind + { + typedef private_node_allocator_base + other; + }; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + template + struct node_pool + { + typedef ipcdetail::private_node_pool + ::value + , NodesPerBlock + > type; + + static type *get(void *p) + { return static_cast(p); } + }; + + private: + //!Not assignable from related private_node_allocator_base + template + private_node_allocator_base& operator= + (const private_node_allocator_base&); + + //!Not assignable from other private_node_allocator_base + private_node_allocator_base& operator=(const private_node_allocator_base&); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor from a segment manager + private_node_allocator_base(segment_manager *segment_mngr) + : m_node_pool(segment_mngr) + {} + + //!Copy constructor from other private_node_allocator_base. Never throws + private_node_allocator_base(const private_node_allocator_base &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Copy constructor from related private_node_allocator_base. Never throws. + template + private_node_allocator_base + (const private_node_allocator_base + &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Destructor, frees all used memory. Never throws + ~private_node_allocator_base() + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return m_node_pool.get_segment_manager(); } + + //!Returns the internal node pool. Never throws + node_pool_t* get_node_pool() const + { return const_cast(&m_node_pool); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(self_t &alloc1,self_t &alloc2) + { boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + node_pool_t m_node_pool; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Equality test for same type of private_node_allocator_base +template inline +bool operator==(const private_node_allocator_base &alloc1, + const private_node_allocator_base &alloc2) +{ return &alloc1 == &alloc2; } + +//!Inequality test for same type of private_node_allocator_base +template inline +bool operator!=(const private_node_allocator_base &alloc1, + const private_node_allocator_base &alloc2) +{ return &alloc1 != &alloc2; } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class private_node_allocator_v1 + : public private_node_allocator_base + < 1 + , T + , SegmentManager + , NodesPerBlock + > +{ + public: + typedef ipcdetail::private_node_allocator_base + < 1, T, SegmentManager, NodesPerBlock> base_t; + + template + struct rebind + { + typedef private_node_allocator_v1 other; + }; + + private_node_allocator_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_node_allocator_v1 + (const private_node_allocator_v1 &other) + : base_t(other) + {} +}; + +} //namespace ipcdetail { + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated +//!at once when the allocator needs runs out of nodes +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class private_node_allocator + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::private_node_allocator_base + < 2 + , T + , SegmentManager + , NodesPerBlock + > + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef ipcdetail::private_node_allocator_base + < 2, T, SegmentManager, NodesPerBlock> base_t; + public: + typedef boost::interprocess::version_type version; + + template + struct rebind + { + typedef private_node_allocator + other; + }; + + private_node_allocator(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_node_allocator + (const private_node_allocator &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manage::difference_type difference_type; + + //!Obtains private_node_allocator from + //!private_node_allocator + template + struct rebind + { + typedef private_node_allocator + other; + }; + + private: + //!Not assignable from + //!related private_node_allocator + template + private_node_allocator& operator= + (const private_node_allocator&); + + //!Not assignable from + //!other private_node_allocator + private_node_allocator& operator=(const private_node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + private_node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other private_node_allocator. Increments the reference + //!count of the associated node pool. Never throws + private_node_allocator(const private_node_allocator &other); + + //!Copy constructor from related private_node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + private_node_allocator + (const private_node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~private_node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_chain &chain); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void allocate_individual(size_type num_elements, multiallocation_chain &chain); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_chain &chain); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of private_node_allocator +template inline +bool operator==(const private_node_allocator &alloc1, + const private_node_allocator &alloc2); + +//!Inequality test for same type +//!of private_node_allocator +template inline +bool operator!=(const private_node_allocator &alloc1, + const private_node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP + diff --git a/extern/boost/boost/interprocess/anonymous_shared_memory.hpp b/extern/boost/boost/interprocess/anonymous_shared_memory.hpp new file mode 100644 index 00000000000..4e0ec61b19a --- /dev/null +++ b/extern/boost/boost/interprocess/anonymous_shared_memory.hpp @@ -0,0 +1,125 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ANONYMOUS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if (!defined(BOOST_INTERPROCESS_WINDOWS)) +# include //open, O_CREAT, O_*... +# include //mmap +# include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, +#else +#include +#endif + + +//!\file +//!Describes a function that creates anonymous shared memory that can be +//!shared between forked processes + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail{ + + class raw_mapped_region_creator + { + public: + static mapped_region + create_posix_mapped_region(void *address, std::size_t size) + { + mapped_region region; + region.m_base = address; + region.m_size = size; + return region; + } + }; +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!A function that creates an anonymous shared memory segment of size "size". +//!If "address" is passed the function will try to map the segment in that address. +//!Otherwise the operating system will choose the mapping address. +//!The function returns a mapped_region holding that segment or throws +//!interprocess_exception if the function fails. +//static mapped_region +inline mapped_region +anonymous_shared_memory(std::size_t size, void *address = 0) +#if (!defined(BOOST_INTERPROCESS_WINDOWS)) +{ + int flags; + int fd = -1; + + #if defined(MAP_ANONYMOUS) //Use MAP_ANONYMOUS + flags = MAP_ANONYMOUS | MAP_SHARED; + #elif !defined(MAP_ANONYMOUS) && defined(MAP_ANON) //use MAP_ANON + flags = MAP_ANON | MAP_SHARED; + #else // Use "/dev/zero" + fd = open("/dev/zero", O_RDWR); + flags = MAP_SHARED; + if(fd == -1){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + #endif + + + address = mmap( address + , size + , PROT_READ|PROT_WRITE + , flags + , fd + , 0); + + if(address == MAP_FAILED){ + if(fd != -1) + close(fd); + error_info err = system_error_code(); + throw interprocess_exception(err); + } + + if(fd != -1) + close(fd); + + return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size); +} +#else +{ + windows_shared_memory anonymous_mapping(create_only, (char*)0, read_write, size); + return mapped_region(anonymous_mapping, read_write, 0, size, address); +} + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/containers/allocation_type.hpp b/extern/boost/boost/interprocess/containers/allocation_type.hpp new file mode 100644 index 00000000000..d99b7ab51de --- /dev/null +++ b/extern/boost/boost/interprocess/containers/allocation_type.hpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_ALLOCATION_TYPE_HPP +#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +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; +static const allocation_type expand_bwd = boost::container::expand_bwd; +static const allocation_type shrink_in_place = boost::container::shrink_in_place; +static const allocation_type try_shrink_in_place= boost::container::try_shrink_in_place; +static const allocation_type nothrow_allocation = boost::container::nothrow_allocation; +static const allocation_type zero_memory = boost::container::zero_memory; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP diff --git a/extern/boost/boost/interprocess/containers/containers_fwd.hpp b/extern/boost/boost/interprocess/containers/containers_fwd.hpp new file mode 100644 index 00000000000..9620a92ee92 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/containers_fwd.hpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_CONTAINERS_CONTAINERS_FWD_HPP +#define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +////////////////////////////////////////////////////////////////////////////// +// Standard predeclarations +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::ordered_range; +using boost::container::ordered_unique_range; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP diff --git a/extern/boost/boost/interprocess/containers/deque.hpp b/extern/boost/boost/interprocess/containers/deque.hpp new file mode 100644 index 00000000000..50073060050 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/deque.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_DEQUE_HPP +#define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::deque; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP + diff --git a/extern/boost/boost/interprocess/containers/flat_map.hpp b/extern/boost/boost/interprocess/containers/flat_map.hpp new file mode 100644 index 00000000000..6b9262b8dfc --- /dev/null +++ b/extern/boost/boost/interprocess/containers/flat_map.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_FLAT_MAP_HPP +#define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::flat_map; +using boost::container::flat_multimap; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP diff --git a/extern/boost/boost/interprocess/containers/flat_set.hpp b/extern/boost/boost/interprocess/containers/flat_set.hpp new file mode 100644 index 00000000000..9c729a67e03 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/flat_set.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_FLAT_SET_HPP +#define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::flat_set; +using boost::container::flat_multiset; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP diff --git a/extern/boost/boost/interprocess/containers/list.hpp b/extern/boost/boost/interprocess/containers/list.hpp new file mode 100644 index 00000000000..465e8828645 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/list.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_LIST_HPP +#define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::list; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP + diff --git a/extern/boost/boost/interprocess/containers/map.hpp b/extern/boost/boost/interprocess/containers/map.hpp new file mode 100644 index 00000000000..966abdf3962 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/map.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_MAP_HPP +#define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::map; +using boost::container::multimap; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP diff --git a/extern/boost/boost/interprocess/containers/pair.hpp b/extern/boost/boost/interprocess/containers/pair.hpp new file mode 100644 index 00000000000..ccd3c235f04 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/pair.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_PAIR_HPP +#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::dtl::pair; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP + diff --git a/extern/boost/boost/interprocess/containers/set.hpp b/extern/boost/boost/interprocess/containers/set.hpp new file mode 100644 index 00000000000..433607ba284 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/set.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_SET_HPP +#define BOOST_INTERPROCESS_CONTAINERS_SET_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::set; +using boost::container::multiset; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP diff --git a/extern/boost/boost/interprocess/containers/slist.hpp b/extern/boost/boost/interprocess/containers/slist.hpp new file mode 100644 index 00000000000..1f1aee63ded --- /dev/null +++ b/extern/boost/boost/interprocess/containers/slist.hpp @@ -0,0 +1,36 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_SLIST_HPP +#define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::slist; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP diff --git a/extern/boost/boost/interprocess/containers/stable_vector.hpp b/extern/boost/boost/interprocess/containers/stable_vector.hpp new file mode 100644 index 00000000000..f6d1ee1b04f --- /dev/null +++ b/extern/boost/boost/interprocess/containers/stable_vector.hpp @@ -0,0 +1,36 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_STABLE_VECTOR_HPP +#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { + namespace interprocess { + + using boost::container::stable_vector; + + } //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP diff --git a/extern/boost/boost/interprocess/containers/string.hpp b/extern/boost/boost/interprocess/containers/string.hpp new file mode 100644 index 00000000000..bd1286411a8 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/string.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_STRING_HPP +#define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::basic_string; +using boost::container::string; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP diff --git a/extern/boost/boost/interprocess/containers/vector.hpp b/extern/boost/boost/interprocess/containers/vector.hpp new file mode 100644 index 00000000000..89b3e471499 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/vector.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_VECTOR_HPP +#define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::vector; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP + diff --git a/extern/boost/boost/interprocess/containers/version_type.hpp b/extern/boost/boost/interprocess/containers/version_type.hpp new file mode 100644 index 00000000000..68850729923 --- /dev/null +++ b/extern/boost/boost/interprocess/containers/version_type.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_VERSION_TYPE_HPP +#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { + +using boost::container::dtl::version_type; +using boost::container::dtl::version; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP + diff --git a/extern/boost/boost/interprocess/detail/cast_tags.hpp b/extern/boost/boost/interprocess/detail/cast_tags.hpp new file mode 100644 index 00000000000..e47b86344cc --- /dev/null +++ b/extern/boost/boost/interprocess/detail/cast_tags.hpp @@ -0,0 +1,31 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CAST_TAGS_HPP +#define BOOST_INTERPROCESS_DETAIL_CAST_TAGS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost { namespace interprocess { namespace ipcdetail { + +struct static_cast_tag {}; +struct const_cast_tag {}; +struct dynamic_cast_tag {}; +struct reinterpret_cast_tag {}; + +}}} //namespace boost { namespace interprocess { namespace ipcdetail { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_CAST_TAGS_HPP diff --git a/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp b/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp new file mode 100644 index 00000000000..c6688e619c1 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp @@ -0,0 +1,302 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_FILE_LOCKING_HELPERS_HPP +#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +#include +#include +#include + +#else //defined(BOOST_INTERPROCESS_WINDOWS) + +#include +#include +#include + +#endif //defined(BOOST_INTERPROCESS_WINDOWS) + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +struct locking_file_serial_id +{ + int fd; + unsigned long dwVolumeSerialNumber; + unsigned long nFileIndexHigh; + unsigned long nFileIndexLow; + //This reference count counts the number of modules attached + //to the shared memory and lock file. This serves to unlink + //the locking file and shared memory when all modules are + //done with the global memory (shared memory) + volatile boost::uint32_t modules_attached_to_gmem_count; +}; + +inline bool lock_locking_file(int fd) +{ + int ret = 0; + while(ret != 0 && errno == EDEADLK){ + ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/); + } + return 0 == ret; +} + +inline bool try_lock_locking_file(int fd) +{ + return 0 == _locking(fd, _LK_NBLCK , 1); +} + +inline int open_or_create_and_lock_file(const char *name) +{ + permissions p; + p.set_unrestricted(); + while(1){ + file_handle_t handle = create_or_open_file(name, read_write, p); + int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); + if(fd < 0){ + close_file(handle); + return fd; + } + if(!try_lock_locking_file(fd)){ + _close(fd); + return -1; + } + struct _stat s; + if(0 == _stat(name, &s)){ + return fd; + } + else{ + _close(fd); + } + } +} + +inline int try_open_and_lock_file(const char *name) +{ + file_handle_t handle = open_existing_file(name, read_write); + int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); + if(fd < 0){ + close_file(handle); + return fd; + } + if(!try_lock_locking_file(fd)){ + _close(fd); + return -1; + } + return fd; +} + +inline void close_lock_file(int fd) +{ _close(fd); } + +inline bool is_valid_fd(int fd) +{ + struct _stat s; + return EBADF != _fstat(fd, &s); +} + +inline bool is_normal_file(int fd) +{ + if(_isatty(fd)) + return false; + struct _stat s; + if(0 != _fstat(fd, &s)) + return false; + return 0 != (s.st_mode & _S_IFREG); +} + +inline std::size_t get_size(int fd) +{ + struct _stat s; + if(0 != _fstat(fd, &s)) + return 0u; + return (std::size_t)s.st_size; +} + +inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) +{ + winapi::interprocess_by_handle_file_information info; + if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) + return false; + id.fd = fd; + id.dwVolumeSerialNumber = info.dwVolumeSerialNumber; + id.nFileIndexHigh = info.nFileIndexHigh; + id.nFileIndexLow = info.nFileIndexLow; + id.modules_attached_to_gmem_count = 1; //Initialize attached count + return true; +} + +inline bool compare_file_serial(int fd, const locking_file_serial_id &id) +{ + winapi::interprocess_by_handle_file_information info; + if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) + return false; + + return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber && + id.nFileIndexHigh == info.nFileIndexHigh && + id.nFileIndexLow == info.nFileIndexLow; +} + +#else //UNIX + +struct locking_file_serial_id +{ + int fd; + dev_t st_dev; + ino_t st_ino; + //This reference count counts the number of modules attached + //to the shared memory and lock file. This serves to unlink + //the locking file and shared memory when all modules are + //done with the global memory (shared memory) + volatile boost::uint32_t modules_attached_to_gmem_count; +}; + +inline bool lock_locking_file(int fd) +{ + int ret = 0; + while(ret != 0 && errno != EINTR){ + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + ret = fcntl (fd, F_SETLKW, &lock); + } + return 0 == ret; +} + +inline bool try_lock_locking_file(int fd) +{ + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + return 0 == fcntl (fd, F_SETLK, &lock); +} + +inline int open_or_create_and_lock_file(const char *name) +{ + permissions p; + p.set_unrestricted(); + while(1){ + int fd = create_or_open_file(name, read_write, p); + if(fd < 0){ + return fd; + } + if(!try_lock_locking_file(fd)){ + close(fd); + return -1; + } + struct stat s; + if(0 == stat(name, &s)){ + return fd; + } + else{ + close(fd); + } + } +} + +inline int try_open_and_lock_file(const char *name) +{ + int fd = open_existing_file(name, read_write); + if(fd < 0){ + return fd; + } + if(!try_lock_locking_file(fd)){ + close(fd); + return -1; + } + return fd; +} + +inline void close_lock_file(int fd) +{ close(fd); } + +inline bool is_valid_fd(int fd) +{ + struct stat s; + return EBADF != fstat(fd, &s); +} + +inline bool is_normal_file(int fd) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return false; + return 0 != (s.st_mode & S_IFREG); +} + +inline std::size_t get_size(int fd) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return 0u; + return (std::size_t)s.st_size; +} + +inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) +{ + struct stat s; + if(0 != fstat(fd, &s)) + return false; + id.fd = fd; + id.st_dev = s.st_dev; + id.st_ino = s.st_ino; + id.modules_attached_to_gmem_count = 1; //Initialize attached count + return true; +} + +inline bool compare_file_serial(int fd, const locking_file_serial_id &id) +{ + struct stat info; + if(0 != fstat(fd, &info)) + return false; + + return id.st_dev == info.st_dev && + id.st_ino == info.st_ino; +} + +#endif + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP diff --git a/extern/boost/boost/interprocess/detail/file_wrapper.hpp b/extern/boost/boost/interprocess/detail/file_wrapper.hpp new file mode 100644 index 00000000000..84b495362a9 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/file_wrapper.hpp @@ -0,0 +1,233 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-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_FILE_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +class file_wrapper +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Default constructor. + //!Represents an empty file_wrapper. + file_wrapper(); + + //!Creates a file object with name "name" and mode "mode", with the access mode "mode" + //!If the file previously exists, throws an error. + file_wrapper(create_only_t, const char *name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); } + + //!Tries to create a file 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. + file_wrapper(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } + + //!Tries to open a file with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + file_wrapper(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 file 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). + file_wrapper(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 file 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). + file_wrapper(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 file 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). + file_wrapper(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 file to *this. + //!After the call, "moved" does not represent any file. + //!Does not throw + file_wrapper(BOOST_RV_REF(file_wrapper) moved) + : m_handle(file_handle_t(ipcdetail::invalid_file())) + { this->swap(moved); } + + //!Moves the ownership of "moved"'s file to *this. + //!After the call, "moved" does not represent any file. + //!Does not throw + file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved) + { + file_wrapper tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps to file_wrappers. + //!Does not throw + void swap(file_wrapper &other); + + //!Erases a file from the system. + //!Returns false on error. Never throws + static bool remove(const char *name); + + //!Sets the size of the file + void truncate(offset_t length); + + //!Closes the + //!file + ~file_wrapper(); + + //!Returns the name of the file + //!used in the constructor + const char *get_name() const; + + //!Returns the name of the file + //!used in the constructor + bool get_size(offset_t &size) const; + + //!Returns access mode + //!used in the constructor + mode_t get_mode() const; + + //!Get mapping handle + //!to use with mapped_region + mapping_handle_t get_mapping_handle() const; + + private: + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + //!Closes a previously opened file mapping. Never throws. + template + 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; +}; + +inline file_wrapper::file_wrapper() + : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) +{} + +inline file_wrapper::~file_wrapper() +{ this->priv_close(); } + +inline bool file_wrapper::get_size(offset_t &size) const +{ return get_file_size((file_handle_t)m_handle, size); } + +inline void file_wrapper::swap(file_wrapper &other) +{ + (simple_swap)(m_handle, other.m_handle); + (simple_swap)(m_mode, other.m_mode); +} + +inline mapping_handle_t file_wrapper::get_mapping_handle() const +{ return mapping_handle_from_file_handle(m_handle); } + +inline mode_t file_wrapper::get_mode() const +{ return m_mode; } + +template +inline bool file_wrapper::priv_open_or_create + ( ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm) +{ + if(mode != read_only && mode != read_write){ + error_info err(mode_error); + throw interprocess_exception(err); + } + + //Open file existing native API to obtain the handle + switch(type){ + case ipcdetail::DoOpen: + m_handle = open_existing_file(filename, mode); + break; + case ipcdetail::DoCreate: + m_handle = create_new_file(filename, mode, perm); + break; + case ipcdetail::DoOpenOrCreate: + m_handle = create_or_open_file(filename, mode, perm); + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + //Check for error + if(m_handle == invalid_file()){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + + m_mode = mode; + return true; +} + +inline bool file_wrapper::remove(const char *filename) +{ return delete_file(filename); } + +inline void file_wrapper::truncate(offset_t length) +{ + if(!truncate_file(m_handle, (std::size_t)length)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline void file_wrapper::priv_close() +{ + if(m_handle != invalid_file()){ + close_file(m_handle); + m_handle = invalid_file(); + } +} + +} //namespace ipcdetail{ +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/detail/in_place_interface.hpp b/extern/boost/boost/interprocess/detail/in_place_interface.hpp new file mode 100644 index 00000000000..89ad74eac76 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/in_place_interface.hpp @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_IN_PLACE_INTERFACE_HPP +#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include //alignment_of, aligned_storage +#include //typeid + +//!\file +//!Describes an abstract interface for placement construction and destruction. + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +struct in_place_interface +{ + in_place_interface(std::size_t alignm, std::size_t sz, const char *tname) + : alignment(alignm), size(sz), type_name(tname) + {} + + std::size_t alignment; + std::size_t size; + const char *type_name; + + virtual void construct_n(void *mem, std::size_t num) = 0; + virtual void destroy_n(void *mem, std::size_t num) = 0; + virtual ~in_place_interface(){} +}; + +template +struct placement_destroy : public in_place_interface +{ + placement_destroy() + : in_place_interface(::boost::container::dtl::alignment_of::value, sizeof(T), typeid(T).name()) + {} + + virtual void destroy_n(void *mem, std::size_t num) BOOST_OVERRIDE + { + T* memory = static_cast(mem); + for(std::size_t destroyed = 0; destroyed < num; ++destroyed) + (memory++)->~T(); + } + + virtual void construct_n(void *, std::size_t) BOOST_OVERRIDE {} + + private: + void destroy(void *mem) + { static_cast(mem)->~T(); } +}; + +} +} +} //namespace boost { namespace interprocess { namespace ipcdetail { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP diff --git a/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp b/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp new file mode 100644 index 00000000000..24148d47590 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp @@ -0,0 +1,53 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_INTERMODULE_SINGLETON_HPP +#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#ifdef BOOST_INTERPROCESS_WINDOWS + #include +#else + #include +#endif + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +//Now this class is a singleton, initializing the singleton in +//the first get() function call if LazyInit is true. If false +//then the singleton will be initialized when loading the module. +template +class intermodule_singleton + #ifdef BOOST_INTERPROCESS_WINDOWS + : public windows_intermodule_singleton + #else + : public portable_intermodule_singleton + #endif +{}; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif diff --git a/extern/boost/boost/interprocess/detail/interprocess_tester.hpp b/extern/boost/boost/interprocess/detail/interprocess_tester.hpp new file mode 100644 index 00000000000..368820f82a3 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/interprocess_tester.hpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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_INTERPROCESS_TESTER_HPP +#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +class interprocess_tester +{ + public: + template + static void dont_close_on_destruction(T &t) + { t.dont_close_on_destruction(); } +}; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP + diff --git a/extern/boost/boost/interprocess/detail/managed_global_memory.hpp b/extern/boost/boost/interprocess/detail/managed_global_memory.hpp new file mode 100644 index 00000000000..fdf9e1f0481 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/managed_global_memory.hpp @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_BASIC_GLOBAL_MEMORY_HPP +#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +struct intermodule_singleton_mutex_family +{ + typedef boost::interprocess::ipcdetail::spin_mutex mutex_type; + typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type; +}; + +struct intermodule_types +{ + //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory + //at a different address than other DLLs or the main executable + typedef rbtree_best_fit > mem_algo; + template + struct open_or_create + { + typedef managed_open_or_create_impl + type; + }; +}; + +//we must implement our own managed shared memory to avoid circular dependencies +template +class basic_managed_global_memory + : public basic_managed_memory_impl + < char + , intermodule_types::mem_algo + , iset_index + , intermodule_types::open_or_create::type::ManagedOpenOrCreateUserOffset + > + , private intermodule_types::open_or_create::type +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef typename intermodule_types::template open_or_create::type base2_t; + + typedef basic_managed_memory_impl + < char + , intermodule_types::mem_algo + , iset_index + , base2_t::ManagedOpenOrCreateUserOffset + > base_t; + + typedef create_open_func create_open_func_t; + + basic_managed_global_memory *get_this_pointer() + { return this; } + + public: + typedef typename base_t::size_type size_type; + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + + basic_managed_global_memory (open_or_create_t, + const char *name, size_type size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create_t(), name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + DoOpenOrCreate), perm) + {} + + basic_managed_global_memory (open_only_t , const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only_t(), name, read_write, addr, + create_open_func_t(get_this_pointer(), + DoOpen)) + {} +}; + + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp b/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp new file mode 100644 index 00000000000..72e242d50ac --- /dev/null +++ b/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp @@ -0,0 +1,775 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_MEMORY_IMPL_HPP +#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +#include +// +#include +#include + +//!\file +//!Describes a named shared memory allocation user class. +//! + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +class create_open_func; + +template< + class CharType, + class MemoryAlgorithm, + template class IndexType + > +struct segment_manager_type +{ + typedef segment_manager type; +}; + +//!This class is designed to be a base class to classes that manage +//!creation of objects in a fixed size memory buffer. Apart +//!from allocating raw memory, the user can construct named objects. To +//!achieve this, this class uses the reserved space provided by the allocation +//!algorithm to place a named_allocator_algo, who takes care of name mappings. +//!The class can be customized with the char type used for object names +//!and the memory allocation algorithm to be used.*/ +template < class CharType + , class MemoryAlgorithm + , template class IndexType + , std::size_t Offset = 0 + > +class basic_managed_memory_impl +{ + //Non-copyable + basic_managed_memory_impl(const basic_managed_memory_impl &); + basic_managed_memory_impl &operator=(const basic_managed_memory_impl &); + + template + friend class create_open_func; + + public: + typedef typename segment_manager_type + ::type segment_manager; + typedef CharType char_type; + typedef MemoryAlgorithm memory_algorithm; + typedef typename MemoryAlgorithm::mutex_family mutex_family; + typedef CharType char_t; + typedef typename MemoryAlgorithm::size_type size_type; + typedef typename MemoryAlgorithm::difference_type difference_type; + typedef difference_type handle_t; + typedef typename segment_manager:: + const_named_iterator const_named_iterator; + typedef typename segment_manager:: + const_unique_iterator const_unique_iterator; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + typedef typename + segment_manager::char_ptr_holder_t char_ptr_holder_t; + //Experimental. Don't use. + + typedef typename segment_manager::multiallocation_chain multiallocation_chain; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation; + + private: + typedef basic_managed_memory_impl + self_t; + protected: + template + static bool grow(const CharT *filename, size_type extra_bytes) + { + typedef typename ManagedMemory::device_type device_type; + //Increase file size + BOOST_TRY{ + offset_t old_size; + { + device_type f(open_or_create, filename, read_write); + if(!f.get_size(old_size)) + return false; + f.truncate(old_size + static_cast(extra_bytes)); + } + ManagedMemory managed_memory(open_only, filename); + //Grow always works + managed_memory.self_t::grow(extra_bytes); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END + return true; + } + + template + static bool shrink_to_fit(const CharT *filename) + { + typedef typename ManagedMemory::device_type device_type; + size_type new_size; + BOOST_TRY{ + ManagedMemory managed_memory(open_only, filename); + managed_memory.get_size(); + managed_memory.self_t::shrink_to_fit(); + new_size = managed_memory.get_size(); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END + + //Decrease file size + { + device_type f(open_or_create, filename, read_write); + f.truncate(static_cast(new_size)); + } + return true; + } + + //!Constructor. Allocates basic resources. Never throws. + basic_managed_memory_impl() + : mp_header(0){} + + //!Destructor. Calls close. Never throws. + ~basic_managed_memory_impl() + { this->close_impl(); } + + //!Places segment manager in the reserved space. This can throw. + bool create_impl (void *addr, size_type size) + { + if(mp_header) return false; + + //Check if there is enough space + if(size < segment_manager::get_min_size()) + return false; + + //This function should not throw. The index construction can + //throw if constructor allocates memory. So we must catch it. + BOOST_TRY{ + //Let's construct the allocator in memory + BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of::value)); + mp_header = ::new(addr, boost_container_new_t()) segment_manager(size); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END + return true; + } + + //!Connects to a segment manager in the reserved buffer. Never throws. + bool open_impl (void *addr, size_type) + { + if(mp_header) return false; + mp_header = static_cast(addr); + return true; + } + + //!Frees resources. Never throws. + bool close_impl() + { + bool ret = mp_header != 0; + mp_header = 0; + return ret; + } + + //!Frees resources and destroys common resources. Never throws. + bool destroy_impl() + { + if(mp_header == 0) + return false; + mp_header->~segment_manager(); + this->close_impl(); + return true; + } + + //! + void grow(size_type extra_bytes) + { mp_header->grow(extra_bytes); } + + void shrink_to_fit() + { mp_header->shrink_to_fit(); } + + public: + + //!Returns segment manager. Never throws. + segment_manager *get_segment_manager() const + { return mp_header; } + + //!Returns the base address of the memory in this process. Never throws. + void * get_address () const + { return reinterpret_cast(mp_header) - Offset; } + + //!Returns the size of memory segment. Never throws. + size_type get_size () const + { return mp_header->get_size() + Offset; } + + //!Returns the number of free bytes of the memory + //!segment + size_type get_free_memory() const + { return mp_header->get_free_memory(); } + + //!Returns the result of "all_memory_deallocated()" function + //!of the used memory algorithm + bool all_memory_deallocated() + { return mp_header->all_memory_deallocated(); } + + //!Returns the result of "check_sanity()" function + //!of the used memory algorithm + bool check_sanity() + { return mp_header->check_sanity(); } + + //!Writes to zero free memory (memory not yet allocated) of + //!the memory algorithm + void zero_free_memory() + { mp_header->zero_free_memory(); } + + //!Transforms an absolute address into an offset from base address. + //!The address must belong to the memory segment. Never throws. + handle_t get_handle_from_address (const void *ptr) const + { + return (handle_t)(reinterpret_cast(ptr) - + reinterpret_cast(this->get_address())); + } + + //!Returns true if the address belongs to the managed memory segment + bool belongs_to_segment (const void *ptr) const + { + return ptr >= this->get_address() && + ptr < (reinterpret_cast(this->get_address()) + this->get_size()); + } + + //!Transforms previously obtained offset into an absolute address in the + //!process space of the current process. Never throws.*/ + void * get_address_from_handle (handle_t offset) const + { return reinterpret_cast(this->get_address()) + offset; } + + //!Searches for nbytes of free memory in the segment, marks the + //!memory as used and return the pointer to the memory. If no + //!memory is available throws a boost::interprocess::bad_alloc exception + void* allocate (size_type nbytes) + { return mp_header->allocate(nbytes); } + + //!Searches for nbytes of free memory in the segment, marks the + //!memory as used and return the pointer to the memory. If no memory + //!is available returns 0. Never throws. + void* allocate (size_type nbytes, const std::nothrow_t &tag) + { return mp_header->allocate(nbytes, tag); } + + //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" + //!must be power of two. If no memory + //!is available returns 0. Never throws. + void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag) + { return mp_header->allocate_aligned(nbytes, alignment, tag); } + + template + T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse) + { return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } + + //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" + //!must be power of two. If no + //!memory is available throws a boost::interprocess::bad_alloc exception + void * allocate_aligned(size_type nbytes, size_type alignment) + { return mp_header->allocate_aligned(nbytes, alignment); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Experimental. Don't use. + + //!Allocates n_elements of elem_bytes bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(elem_bytes, n_elements, chain); } + + //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); } + + //!Allocates n_elements of elem_bytes bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(tag, elem_bytes, n_elements, chain); } + + //!Allocates n_elements, each one of + //!element_lengths[i]*sizeof_element bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); } + + //!Deallocates all elements contained in chain. + //!Never throws. + void deallocate_many(multiallocation_chain &chain) + { mp_header->deallocate_many(chain); } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Marks previously allocated memory as free. Never throws. + void deallocate (void *addr) + { if (mp_header) mp_header->deallocate(addr); } + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { return mp_header->template find(name); } + + //!Creates a named object or array in memory + //! + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + construct(char_ptr_holder_t name) + { return mp_header->template construct(name); } + + //!Finds or creates a named object or array in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + find_or_construct(char_ptr_holder_t name) + { return mp_header->template find_or_construct(name); } + + //!Creates a named object or array in memory + //! + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Returns 0 if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + construct(char_ptr_holder_t name, const std::nothrow_t &tag) + { return mp_header->template construct(name, tag); } + + //!Finds or creates a named object or array in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> Returns 0 if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag) + { return mp_header->template find_or_construct(name, tag); } + + //!Creates a named array from iterators in memory + //! + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory. + template + typename segment_manager::template construct_iter_proxy::type + construct_it(char_ptr_holder_t name) + { return mp_header->template construct_it(name); } + + //!Finds or creates a named array from iterators in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory. + template + typename segment_manager::template construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name) + { return mp_header->template find_or_construct_it(name); } + + //!Creates a named array from iterators in memory + //! + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> If there is no available memory, returns 0. + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory.*/ + template + typename segment_manager::template construct_iter_proxy::type + construct_it(char_ptr_holder_t name, const std::nothrow_t &tag) + { return mp_header->template construct_it(name, tag); } + + //!Finds or creates a named array from iterators in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> If there is no available memory, returns 0. + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory.*/ + template + typename segment_manager::template construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag) + { return mp_header->template find_or_construct_it(name, tag); } + + //!Calls a functor and guarantees that no new construction, search or + //!destruction will be executed by any process while executing the object + //!function call. If the functor throws, this function throws. + template + void atomic_func(Func &f) + { mp_header->atomic_func(f); } + + //!Tries to call a functor guaranteeing that no new construction, search or + //!destruction will be executed by any process while executing the object + //!function call. If the atomic function can't be immediatelly executed + //!because the internal mutex is already locked, returns false. + //!If the functor throws, this function throws. + template + bool try_atomic_func(Func &f) + { return mp_header->try_atomic_func(f); } + + //!Destroys a named memory object or array. + //! + //!Finds the object with the given name, calls its destructors, + //!frees used memory and returns true. + //! + //!-> If the object is not found, it returns false. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object or array, the Standard + //!does not guarantee that dynamically allocated memory, will be released. + //!Also, when deleting arrays, the Standard doesn't require calling + //!destructors for the rest of the objects if for one of them the destructor + //!terminated with an exception. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!Destroying an array: + //! + //!When destroying an array, if a destructor throws, the rest of + //!destructors are called. If any of these throws, the exceptions are + //!ignored. The name association will be erased, memory will be freed and + //!the first exception will be thrown. This guarantees the unlocking of + //!mutexes and other resources. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended. + template + bool destroy(const CharType *name) + { return mp_header->template destroy(name); } + + //!Destroys the unique instance of type T + //! + //!Calls the destructor, frees used memory and returns true. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object, the Standard does not + //!guarantee that dynamically allocated memory will be released. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended for memory. + template + bool destroy(const unique_instance_t *const ) + { return mp_header->template destroy(unique_instance); } + + //!Destroys the object (named, unique, or anonymous) + //! + //!Calls the destructor, frees used memory and returns true. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object, the Standard does not + //!guarantee that dynamically allocated memory will be released. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended for memory. + template + void destroy_ptr(const T *ptr) + { mp_header->template destroy_ptr(ptr); } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. If ptr points to an unique instance typeid(T).name() is returned. + template + static const char_type *get_instance_name(const T *ptr) + { return segment_manager::get_instance_name(ptr); } + + //!Returns is the type an object created with construct/find_or_construct + //!functions. Does not throw. + template + static instance_type get_instance_type(const T *ptr) + { return segment_manager::get_instance_type(ptr); } + + //!Returns the length of an object created with construct/find_or_construct + //!functions (1 if is a single element, >=1 if it's an array). Does not throw. + template + static size_type get_instance_length(const T *ptr) + { return segment_manager::get_instance_length(ptr); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" named objects in the memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_named_objects(size_type num) + { mp_header->reserve_named_objects(num); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" unique objects in the memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_unique_objects(size_type num) + { mp_header->reserve_unique_objects(num); } + + //!Calls shrink_to_fit in both named and unique object indexes + //to try to free unused memory from those indexes. + void shrink_to_fit_indexes() + { mp_header->shrink_to_fit_indexes(); } + + //!Returns the number of named objects stored + //!in the managed segment. + size_type get_num_named_objects() + { return mp_header->get_num_named_objects(); } + + //!Returns the number of unique objects stored + //!in the managed segment. + size_type get_num_unique_objects() + { return mp_header->get_num_unique_objects(); } + + //!Returns a constant iterator to the index storing the + //!named allocations. NOT thread-safe. Never throws. + const_named_iterator named_begin() const + { return mp_header->named_begin(); } + + //!Returns a constant iterator to the end of the index + //!storing the named allocations. NOT thread-safe. Never throws. + const_named_iterator named_end() const + { return mp_header->named_end(); } + + //!Returns a constant iterator to the index storing the + //!unique allocations. NOT thread-safe. Never throws. + const_unique_iterator unique_begin() const + { return mp_header->unique_begin(); } + + //!Returns a constant iterator to the end of the index + //!storing the unique allocations. NOT thread-safe. Never throws. + const_unique_iterator unique_end() const + { return mp_header->unique_end(); } + + //!This is the default allocator to allocate types T + //!from this managed segment + template + struct allocator + { + typedef typename segment_manager::template allocator::type type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename allocator::type + get_allocator() + { return mp_header->template get_allocator(); } + + //!This is the default deleter to delete types T + //!from this managed segment. + template + struct deleter + { + typedef typename segment_manager::template deleter::type type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename deleter::type + get_deleter() + { return mp_header->template get_deleter(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find_no_lock (char_ptr_holder_t name) + { return mp_header->template find_no_lock(name); } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + protected: + //!Swaps the segment manager's managed by this managed memory segment. + //!NOT thread-safe. Never throws. + void swap(basic_managed_memory_impl &other) + { (simple_swap)(mp_header, other.mp_header); } + + private: + segment_manager *mp_header; +}; + +template +class create_open_func +{ + typedef typename BasicManagedMemoryImpl::size_type size_type; + + public: + + create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type) + : m_frontend(frontend), m_type(type){} + + bool operator()(void *addr, std::size_t size, bool created) const + { + if( ((m_type == DoOpen) && created) || + ((m_type == DoCreate) && !created) || + //Check for overflow + size_type(-1) < size ){ + return false; + } + else if(created){ + return m_frontend->create_impl(addr, static_cast(size)); + } + else{ + return m_frontend->open_impl (addr, static_cast(size)); + } + } + + static std::size_t get_min_size() + { + const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size(); + if(sz > std::size_t(-1)){ + //The minimum size is not representable by std::size_t + BOOST_ASSERT(false); + return std::size_t(-1); + } + else{ + return static_cast(sz); + } + } + + private: + BasicManagedMemoryImpl *m_frontend; + create_enum_t m_type; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP + diff --git a/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp b/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp new file mode 100644 index 00000000000..f7acdb89da4 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -0,0 +1,574 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-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_MANAGED_OPEN_OR_CREATE_IMPL +#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //alignment_of, aligned_storage +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +class managed_open_or_create_impl_device_holder +{ + public: + DeviceAbstraction &get_device() + { static DeviceAbstraction dev; return dev; } + + const DeviceAbstraction &get_device() const + { static DeviceAbstraction dev; return dev; } +}; + +template +class managed_open_or_create_impl_device_holder +{ + public: + DeviceAbstraction &get_device() + { return dev; } + + const DeviceAbstraction &get_device() const + { return dev; } + + private: + DeviceAbstraction dev; +}; + +template +class managed_open_or_create_impl + : public managed_open_or_create_impl_device_holder +{ + //Non-copyable + BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl) + typedef bool_ file_like_t; + + static const unsigned MaxCreateOrOpenTries = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES; + static const unsigned MaxInitializeTimeSec = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC; + + typedef managed_open_or_create_impl_device_holder DevHolder; + enum + { + UninitializedSegment, + InitializingSegment, + InitializedSegment, + CorruptedSegment + }; + + static const std::size_t RequiredAlignment = + MemAlignment ? MemAlignment + : boost::container::dtl::alignment_of< boost::container::dtl::max_align_t >::value + ; + + public: + static const std::size_t ManagedOpenOrCreateUserOffset = + ct_rounded_size::value; + + managed_open_or_create_impl() + {} + + template + managed_open_or_create_impl(create_only_t, + const DeviceId & id, + std::size_t size, + mode_t mode, + const void *addr, + const permissions &perm) + { + priv_open_or_create + ( DoCreate + , id + , size + , mode + , addr + , perm + , null_mapped_region_function()); + } + + template + managed_open_or_create_impl(open_only_t, + const DeviceId & id, + mode_t mode, + const void *addr) + { + priv_open_or_create + ( DoOpen + , id + , 0 + , mode + , addr + , permissions() + , null_mapped_region_function()); + } + + template + managed_open_or_create_impl(open_or_create_t, + const DeviceId & id, + std::size_t size, + mode_t mode, + const void *addr, + const permissions &perm) + { + priv_open_or_create + ( DoOpenOrCreate + , id + , size + , mode + , addr + , perm + , null_mapped_region_function()); + } + + template + managed_open_or_create_impl(create_only_t, + const DeviceId & id, + std::size_t size, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func, + const permissions &perm) + { + priv_open_or_create + (DoCreate + , id + , size + , mode + , addr + , perm + , construct_func); + } + + template + managed_open_or_create_impl(open_only_t, + const DeviceId & id, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func) + { + priv_open_or_create + ( DoOpen + , id + , 0 + , mode + , addr + , permissions() + , construct_func); + } + + template + managed_open_or_create_impl(open_or_create_t, + const DeviceId & id, + std::size_t size, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func, + const permissions &perm) + { + priv_open_or_create + ( DoOpenOrCreate + , id + , size + , mode + , addr + , perm + , construct_func); + } + + template + managed_open_or_create_impl(std::size_t size, void *addr, const ConstructFunc &construct_func) + { + priv_map_anonymous + ( size + , addr + , construct_func); + } + + managed_open_or_create_impl(BOOST_RV_REF(managed_open_or_create_impl) moved) + { this->swap(moved); } + + managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved) + { + managed_open_or_create_impl tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + ~managed_open_or_create_impl() + {} + + std::size_t get_user_size() const + { return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; } + + void *get_user_address() const + { return static_cast(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset; } + + std::size_t get_real_size() const + { return m_mapped_region.get_size(); } + + void *get_real_address() const + { return m_mapped_region.get_address(); } + + void swap(managed_open_or_create_impl &other) + { + this->m_mapped_region.swap(other.m_mapped_region); + } + + bool flush() + { return m_mapped_region.flush(); } + + const mapped_region &get_mapped_region() const + { return m_mapped_region; } + + DeviceAbstraction &get_device() + { return this->DevHolder::get_device(); } + + const DeviceAbstraction &get_device() const + { return this->DevHolder::get_device(); } + + private: + + //These are templatized to allow explicit instantiations + template + static void truncate_device(DeviceAbstraction &, offset_t, false_) + {} //Empty + + template + static void truncate_device(DeviceAbstraction &dev, offset_t size, true_) + { dev.truncate(size); } + + + template + static bool check_offset_t_size(std::size_t , false_) + { return true; } //Empty + + template + static bool check_offset_t_size(std::size_t size, true_) + { return size == std::size_t(offset_t(size)); } + + //These are templatized to allow explicit instantiations + template + static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm, false_ /*file_like*/) + { + DeviceAbstraction tmp(create_only, id, read_write, size, perm); + tmp.swap(dev); + } + + template + static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t, const permissions &perm, true_ /*file_like*/) + { + DeviceAbstraction tmp(create_only, id, read_write, perm); + tmp.swap(dev); + } + + template + static bool do_create_else_open(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm) + { + //This loop is very ugly, but brute force is sometimes better + //than diplomacy. In POSIX file-based resources we can' know if we + //effectively created the file or not (there is no ERROR_ALREADY_EXISTS equivalent), + //so we try to create exclusively and fallback to open if already exists, with + //some retries if opening also fails because the file does not exist + //(there is a race, the creator just removed the file after creating it). + // + //We'll put a maximum retry limit just to avoid possible deadlocks, we don't + //want to support pathological use cases. + spin_wait swait; + unsigned tries = 0; + while(1){ + BOOST_TRY{ + create_device(dev, id, size, perm, file_like_t()); + return true; + } + BOOST_CATCH(interprocess_exception &ex){ + #ifndef BOOST_NO_EXCEPTIONS + if(ex.get_error_code() != already_exists_error){ + BOOST_RETHROW + } + else if (++tries == MaxCreateOrOpenTries) { + //File existing when trying to create, but non-existing when + //trying to open, and tried MaxCreateOrOpenTries times. Something fishy + //is happening here and we can't solve it + throw interprocess_exception(error_info(corrupted_error)); + } + else{ + BOOST_TRY{ + DeviceAbstraction tmp(open_only, id, read_write); + dev.swap(tmp); + return false; + } + BOOST_CATCH(interprocess_exception &e){ + if(e.get_error_code() != not_found_error){ + BOOST_RETHROW + } + } + BOOST_CATCH(...){ + BOOST_RETHROW + } BOOST_CATCH_END + } + #endif //#ifndef BOOST_NO_EXCEPTIONS + } + BOOST_CATCH(...){ + BOOST_RETHROW + } BOOST_CATCH_END + swait.yield(); + } + return false; + } + + template + static void do_map_after_create + (DeviceAbstraction &dev, mapped_region &final_region, + std::size_t size, const void *addr, ConstructFunc construct_func) + { + BOOST_TRY{ + //If this throws, we are lost + truncate_device(dev, static_cast(size), file_like_t()); + + //If the following throws, we will truncate the file to 1 + mapped_region region(dev, read_write, 0, 0, addr); + boost::uint32_t *patomic_word = 0; //avoid gcc warning + patomic_word = static_cast(region.get_address()); + boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment); + + if(previous == UninitializedSegment){ + BOOST_TRY{ + construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset + , size - ManagedOpenOrCreateUserOffset, true); + //All ok, just move resources to the external mapped region + final_region.swap(region); + } + BOOST_CATCH(...){ + atomic_write32(patomic_word, CorruptedSegment); + BOOST_RETHROW + } BOOST_CATCH_END + atomic_write32(patomic_word, InitializedSegment); + } + else{ + atomic_write32(patomic_word, CorruptedSegment); + throw interprocess_exception(error_info(corrupted_error)); + } + } + BOOST_CATCH(...){ + BOOST_TRY{ + truncate_device(dev, 1u, file_like_t()); + } + BOOST_CATCH(...){ + } + BOOST_CATCH_END + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + static void do_map_after_open + ( DeviceAbstraction &dev, mapped_region &final_region + , const void *addr, ConstructFunc construct_func + , bool ronly, bool cow) + { + const usduration TimeoutSec(usduration_from_seconds(MaxInitializeTimeSec)); + + if(FileBased){ + offset_t filesize = 0; + spin_wait swait; + + //If a file device was used, the creator might be truncating the device, so wait + //until the file size is enough to map the initial word + ustime ustime_start = microsec_clock::universal_time(); + + while(1){ + if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + if (filesize != 0) + break; + else { + //More than MaxZeroTruncateTimeSec seconds waiting to the creator + //to minimally increase the size of the file: something bad has happened + const usduration elapsed(microsec_clock::universal_time() - ustime_start); + if (elapsed > TimeoutSec){ + throw interprocess_exception(error_info(corrupted_error)); + } + swait.yield(); + } + } + //The creator detected an error creating the file and signalled it with size 1 + if(filesize == 1){ + throw interprocess_exception(error_info(corrupted_error)); + } + } + + mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr); + + boost::uint32_t *patomic_word = static_cast(region.get_address()); + boost::uint32_t value = atomic_read32(patomic_word); + + if (value != InitializedSegment){ + ustime ustime_start = microsec_clock::universal_time(); + spin_wait swait; + while ((value = atomic_read32(patomic_word)) != InitializedSegment){ + if(value == CorruptedSegment){ + throw interprocess_exception(error_info(corrupted_error)); + } + //More than MaxZeroTruncateTimeSec seconds waiting to the creator + //to minimally increase the size of the file: something bad has happened + const usduration elapsed(microsec_clock::universal_time() - ustime_start); + if (elapsed > TimeoutSec){ + throw interprocess_exception(error_info(corrupted_error)); + } + swait.yield(); + } + //The size of the file might have grown while Uninitialized -> Initializing, so remap + { + mapped_region null_map; + region.swap(null_map); + } + mapped_region final_size_map(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr); + final_size_map.swap(region); + } + construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset + , region.get_size() - ManagedOpenOrCreateUserOffset + , false); + //All ok, just move resources to the external mapped region + final_region.swap(region); + } + + template inline + void priv_open_or_create + (create_enum_t type, + const DeviceId & id, + std::size_t size, + mode_t mode, const void *addr, + const permissions &perm, + ConstructFunc construct_func) + { + if(type != DoOpen){ + //Check if the requested size is enough to build the managed metadata + const std::size_t func_min_size = construct_func.get_min_size(); + if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size || + size < (func_min_size + ManagedOpenOrCreateUserOffset) ){ + throw interprocess_exception(error_info(size_error)); + } + //Check size can be represented by offset_t (used by truncate) + if (!check_offset_t_size(size, file_like_t())){ + throw interprocess_exception(error_info(size_error)); + } + } + + //Now create the device (file, shm file, etc.) + DeviceAbstraction dev; + (void)mode; + bool created = false; + bool ronly = false; + bool cow = false; + if(type == DoOpen){ + DeviceAbstraction tmp(open_only, id, mode == read_write ? read_write : read_only); + tmp.swap(dev); + ronly = mode == read_only; + cow = mode == copy_on_write; + } + else if(type == DoCreate){ + create_device(dev, id, size, perm, file_like_t()); + created = true; + } + else { //DoOpenOrCreate + created = this->do_create_else_open(dev, id, size, perm); + } + + if(created){ + this->do_map_after_create(dev, m_mapped_region, size, addr, construct_func); + } + else{ + this->do_map_after_open(dev, m_mapped_region, addr, construct_func, ronly, cow); + } + + if(StoreDevice){ + this->DevHolder::get_device() = boost::move(dev); + } + } + + template inline + void priv_map_anonymous + (std::size_t size, + void *addr, + ConstructFunc construct_func) + { + mapped_region region = anonymous_shared_memory(size, addr); + + boost::uint32_t *patomic_word = 0; //avoid gcc warning + patomic_word = static_cast(region.get_address()); + boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment); + + if(previous == UninitializedSegment){ + BOOST_TRY{ + construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset + , size - ManagedOpenOrCreateUserOffset, true); + //All ok, just move resources to the external mapped region + m_mapped_region.swap(region); + } + BOOST_CATCH(...){ + atomic_write32(patomic_word, CorruptedSegment); + BOOST_RETHROW + } BOOST_CATCH_END + atomic_write32(patomic_word, InitializedSegment); + } + else{ + atomic_write32(patomic_word, CorruptedSegment); + throw interprocess_exception(error_info(corrupted_error)); + } + } + + friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right) + { + left.swap(right); + } + + private: + friend class interprocess_tester; + void dont_close_on_destruction() + { interprocess_tester::dont_close_on_destruction(m_mapped_region); } + + mapped_region m_mapped_region; +}; + +} //namespace ipcdetail { + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL diff --git a/extern/boost/boost/interprocess/detail/math_functions.hpp b/extern/boost/boost/interprocess/detail/math_functions.hpp new file mode 100644 index 00000000000..a19efac1a42 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/math_functions.hpp @@ -0,0 +1,118 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Stephen Cleary 2000. +// (C) Copyright Ion Gaztanaga 2007-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. +// +// This file is a slightly modified file from Boost.Pool +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP +#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +// Greatest common divisor and least common multiple + +// +// gcd is an algorithm that calculates the greatest common divisor of two +// integers, using Euclid's algorithm. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer gcd(Integer A, Integer B) +{ + do + { + const Integer tmp(B); + B = A % B; + A = tmp; + } while (B != 0); + + return A; +} + +// +// lcm is an algorithm that calculates the least common multiple of two +// integers. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer lcm(const Integer & A, const Integer & B) +{ + Integer ret = A; + ret /= gcd(A, B); + ret *= B; + return ret; +} + +template +inline Integer log2_ceil(const Integer & A) +{ + Integer i = 0; + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + ++i; + } + return i; +} + +template +inline Integer upper_power_of_2(const Integer & A) +{ + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + } + return power_of_2; +} + +//This function uses binary search to discover the +//highest set bit of the integer +inline std::size_t floor_log2 (std::size_t x) +{ + const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; + const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); + BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true)); + + std::size_t n = x; + std::size_t log2 = 0; + + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ + std::size_t tmp = n >> shift; + if (tmp) + log2 += shift, n = tmp; + } + + return log2; +} + +} // namespace ipcdetail +} // namespace interprocess +} // namespace boost + +#endif diff --git a/extern/boost/boost/interprocess/detail/move.hpp b/extern/boost/boost/interprocess/detail/move.hpp new file mode 100644 index 00000000000..3a2c29b051c --- /dev/null +++ b/extern/boost/boost/interprocess/detail/move.hpp @@ -0,0 +1,36 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-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/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +//! \file + +#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP +#define BOOST_INTERPROCESS_DETAIL_MOVE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include + +namespace boost { +namespace interprocess { + +using ::boost::move; +using ::boost::forward; + +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP diff --git a/extern/boost/boost/interprocess/detail/named_proxy.hpp b/extern/boost/boost/interprocess/detail/named_proxy.hpp new file mode 100644 index 00000000000..f8a46d09874 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/named_proxy.hpp @@ -0,0 +1,284 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_PROXY_HPP +#define BOOST_INTERPROCESS_NAMED_PROXY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess/detail +#include +#include +#include +#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING +#include +#else +#include +#include +#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING +#include + +#include + +//!\file +//!Describes a proxy class that implements named allocation syntax. + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING + +template +struct CtorArgN : public placement_destroy +{ + typedef bool_ IsIterator; + typedef CtorArgN self_t; + typedef typename build_number_seq::type index_tuple_t; + + self_t& operator++() + { + this->do_increment(IsIterator(), index_tuple_t()); + return *this; + } + + self_t operator++(int) { return ++*this; *this; } + + CtorArgN(Args && ...args) + : args_(args...) + {} + + virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE + { + std::size_t constructed = 0; + BOOST_TRY{ + T* memory = static_cast(mem); + for(constructed = 0; constructed < num; ++constructed){ + this->construct(memory++, IsIterator(), index_tuple_t()); + this->do_increment(IsIterator(), index_tuple_t()); + } + } + BOOST_CATCH(...) { + this->placement_destroy::destroy_n(mem, constructed); + BOOST_RETHROW + } BOOST_CATCH_END + } + + private: + template + void construct(void *mem, true_, const index_tuple&) + { ::new((void*)mem, boost_container_new_t())T(*boost::forward((get)(args_))...); } + + template + void construct(void *mem, false_, const index_tuple&) + { ::new((void*)mem, boost_container_new_t())T(boost::forward((get)(args_))...); } + + template + void do_increment(true_, const index_tuple&) + { + this->expansion_helper(++(get)(args_)...); + } + + template + void expansion_helper(ExpansionArgs &&...) + {} + + template + void do_increment(false_, const index_tuple&) + {} + + tuple args_; +}; + +//!Describes a proxy class that implements named +//!allocation syntax. +template + < class SegmentManager //segment manager to construct the object + , class T //type of object to build + , bool is_iterator //passing parameters are normal object or iterators? + > +class named_proxy +{ + typedef typename SegmentManager::char_type char_type; + const char_type * mp_name; + SegmentManager * mp_mngr; + mutable std::size_t m_num; + const bool m_find; + const bool m_dothrow; + + public: + named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) + : mp_name(name), mp_mngr(mngr), m_num(1) + , m_find(find), m_dothrow(dothrow) + {} + + template + T *operator()(Args &&...args) const + { + CtorArgN &&ctor_obj = CtorArgN + (boost::forward(args)...); + return mp_mngr->template + generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); + } + + //This operator allows --> named_new("Name")[3]; <-- syntax + const named_proxy &operator[](std::size_t num) const + { m_num *= num; return *this; } +}; + +#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING + +#define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\ +\ +template \ +struct CtorArg##N : placement_destroy\ +{\ + typedef CtorArg##N self_t;\ + \ + CtorArg##N ( BOOST_MOVE_UREF##N )\ + BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\ + \ + virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\ + {\ + std::size_t constructed = 0;\ + BOOST_TRY{\ + T* memory = static_cast(mem);\ + for (constructed = 0; constructed < num; ++constructed) {\ + ::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\ + }\ + }\ + BOOST_CATCH(...) {\ + this->placement_destroy::destroy_n(mem, constructed);\ + BOOST_RETHROW\ + } BOOST_CATCH_END\ + }\ + \ + private:\ + BOOST_MOVE_MREF##N\ +};\ +//! +BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN) +#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN + +#define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\ +\ +template \ +struct CtorIt##N : public placement_destroy\ +{\ + typedef CtorIt##N self_t;\ + \ + self_t& operator++()\ + { BOOST_MOVE_MINC##N; return *this; }\ + \ + self_t operator++(int) { return ++*this; *this; }\ + \ + CtorIt##N ( BOOST_MOVE_VAL##N )\ + BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\ + \ + virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\ + {\ + std::size_t constructed = 0;\ + BOOST_TRY{\ + T* memory = static_cast(mem);\ + for(constructed = 0; constructed < num; ++constructed){\ + ::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\ + ++(*this);\ + }\ + }\ + BOOST_CATCH(...) {\ + this->placement_destroy::destroy_n(mem, constructed);\ + BOOST_RETHROW\ + } BOOST_CATCH_END\ + }\ + \ + private:\ + BOOST_MOVE_MEMB##N\ +};\ +//! +BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN) +#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN + +//!Describes a proxy class that implements named +//!allocation syntax. +template + < class SegmentManager //segment manager to construct the object + , class T //type of object to build + , bool is_iterator //passing parameters are normal object or iterators? + > +class named_proxy +{ + typedef typename SegmentManager::char_type char_type; + const char_type * mp_name; + SegmentManager * mp_mngr; + mutable std::size_t m_num; + const bool m_find; + const bool m_dothrow; + + public: + named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) + : mp_name(name), mp_mngr(mngr), m_num(1) + , m_find(find), m_dothrow(dothrow) + {} + + #define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + T *operator()( BOOST_MOVE_UREF##N ) const\ + {\ + typedef typename if_c \ + , CtorArg##N \ + >::type ctor_obj_t;\ + ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\ + return mp_mngr->template generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR) + #undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR + + //////////////////////////////////////////////////////////////////////// + // What the macro should generate (n == 2) + //////////////////////////////////////////////////////////////////////// + // + // template + // T *operator()(P1 &p1, P2 &p2) const + // { + // typedef CtorArg2 + // + // ctor_obj_t; + // ctor_obj_t ctor_obj(p1, p2); + // + // return mp_mngr->template generic_construct + // (mp_name, m_num, m_find, m_dothrow, ctor_obj); + // } + // + ////////////////////////////////////////////////////////////////////////// + + //This operator allows --> named_new("Name")[3]; <-- syntax + const named_proxy &operator[](std::size_t num) const + { m_num *= num; return *this; } +}; + +#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING + +}}} //namespace boost { namespace interprocess { namespace ipcdetail { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP diff --git a/extern/boost/boost/interprocess/detail/nothrow.hpp b/extern/boost/boost/interprocess/detail/nothrow.hpp new file mode 100644 index 00000000000..d79ba7647ec --- /dev/null +++ b/extern/boost/boost/interprocess/detail/nothrow.hpp @@ -0,0 +1,42 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-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/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP +#define BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace std { //no namespace versioning in clang+libc++ + +struct nothrow_t; + +} //namespace std { + +namespace boost{ namespace interprocess { + +template +struct nothrow +{ + static const std::nothrow_t &get() { return *pnothrow; } + static std::nothrow_t *pnothrow; +}; + +template +std::nothrow_t *nothrow::pnothrow = + reinterpret_cast(0x1234); //Avoid sanitizer warnings on references to null + +}} //namespace boost{ namespace interprocess { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP diff --git a/extern/boost/boost/interprocess/detail/pointer_type.hpp b/extern/boost/boost/interprocess/detail/pointer_type.hpp new file mode 100644 index 00000000000..125858653e4 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/pointer_type.hpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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_POINTER_TYPE_HPP +#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +struct two {char _[2];}; + +namespace pointer_type_imp { + +template static two test(...); +template static char test(typename U::pointer* = 0); + +} //namespace pointer_type_imp { + +template +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test(0)) == 1; +}; + +namespace pointer_type_imp { + +template ::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template +struct pointer_type +{ + typedef T* type; +}; + +} //namespace pointer_type_imp { + +template +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type::type>::type type; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP + diff --git a/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp b/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp new file mode 100644 index 00000000000..32e196a6f65 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp @@ -0,0 +1,361 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_PORTABLE_INTERMODULE_SINGLETON_HPP +#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +typedef basic_managed_global_memory managed_global_memory; + +namespace intermodule_singleton_helpers { + +static void create_tmp_subdir_and_get_pid_based_filepath + (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false) +{ + //Let's create a lock file for each process gmem that will mark if + //the process is alive or not + create_shared_dir_and_clean_old(s); + s += "/"; + s += subdir_name; + if(!open_or_create_shared_directory(s.c_str())){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + s += "/"; + s += file_prefix; + if(creation_time){ + std::string sstamp; + get_pid_creation_time_str(sstamp); + s += sstamp; + } + else{ + pid_str_t pid_str; + get_pid_str(pid_str, pid); + s += pid_str; + } +} + +static bool check_if_filename_complies_with_pid + (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false) +{ + //Check if filename complies with lock file name pattern + std::string fname(filename); + std::string fprefix(prefix); + if(fname.size() <= fprefix.size()){ + return false; + } + fname.resize(fprefix.size()); + if(fname != fprefix){ + return false; + } + + //If not our lock file, delete it if we can lock it + fname = filename; + fname.erase(0, fprefix.size()); + pid_str_t pid_str; + get_pid_str(pid_str, pid); + file_suffix = pid_str; + if(creation_time){ + std::size_t p = fname.find('_'); + if (p == std::string::npos){ + return false; + } + std::string save_suffix(fname); + fname.erase(p); + fname.swap(file_suffix); + bool ret = (file_suffix == fname); + file_suffix.swap(save_suffix); + return ret; + } + else{ + fname.swap(file_suffix); + return (file_suffix == fname); + } +} + +template<> +struct thread_safe_global_map_dependant +{ + private: + static const int GMemMarkToBeRemoved = -1; + static const int GMemNotPresent = -2; + + static const char *get_lock_file_subdir_name() + { return "gmem"; } + + static const char *get_lock_file_base_name() + { return "lck"; } + + static void create_and_get_singleton_lock_file_path(std::string &s) + { + create_tmp_subdir_and_get_pid_based_filepath + (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true); + } + + struct gmem_erase_func + { + gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm) + :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm) + {} + + void operator()() + { + locking_file_serial_id *pserial_id = shm_.find("lock_file_fd").first; + if(pserial_id){ + pserial_id->fd = GMemMarkToBeRemoved; + } + delete_file(singleton_lock_file_path_); + shared_memory_object::remove(shm_name_); + } + + const char * const shm_name_; + const char * const singleton_lock_file_path_; + managed_global_memory & shm_; + }; + + //This function applies shared memory erasure logic based on the passed lock file. + static void apply_gmem_erase_logic(const char *filepath, const char *filename) + { + int fd = GMemMarkToBeRemoved; + BOOST_TRY{ + std::string str; + //If the filename is current process lock file, then avoid it + if(check_if_filename_complies_with_pid + (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){ + return; + } + //Open and lock the other process' lock file + fd = try_open_and_lock_file(filepath); + if(fd < 0){ + return; + } + //If done, then the process is dead so take global shared memory name + //(the name is based on the lock file name) and try to apply erasure logic + str.insert(0, get_map_base_name()); + BOOST_TRY{ + managed_global_memory shm(open_only, str.c_str()); + gmem_erase_func func(str.c_str(), filepath, shm); + shm.try_atomic_func(func); + } + BOOST_CATCH(interprocess_exception &e){ + //If shared memory is not found erase the lock file + if(e.get_error_code() == not_found_error){ + delete_file(filepath); + } + } BOOST_CATCH_END + } + BOOST_CATCH(...){ + + } BOOST_CATCH_END + if(fd >= 0){ + close_lock_file(fd); + } + } + + public: + + static bool remove_old_gmem() + { + std::string refcstrRootDirectory; + get_shared_dir(refcstrRootDirectory); + refcstrRootDirectory += "/"; + refcstrRootDirectory += get_lock_file_subdir_name(); + return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); + } + + struct lock_file_logic + { + lock_file_logic(managed_global_memory &shm) + : mshm(shm) + { shm.atomic_func(*this); } + + void operator()(void) + { + retry_with_new_map = false; + + //First find the file locking descriptor id + locking_file_serial_id *pserial_id = + mshm.find("lock_file_fd").first; + + int fd; + //If not found schedule a creation + if(!pserial_id){ + fd = GMemNotPresent; + } + //Else get it + else{ + fd = pserial_id->fd; + } + //If we need to create a new one, do it + if(fd == GMemNotPresent){ + std::string lck_str; + //Create a unique current pid based lock file path + create_and_get_singleton_lock_file_path(lck_str); + //Open or create and lock file + int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str()); + //If failed, write a bad file descriptor to notify other modules that + //something was wrong and unlink shared memory. Mark the function object + //to tell caller to retry with another shared memory + if(fd_lockfile < 0){ + this->register_lock_file(GMemMarkToBeRemoved); + std::string s; + get_map_name(s); + shared_memory_object::remove(s.c_str()); + retry_with_new_map = true; + } + //If successful, register the file descriptor + else{ + this->register_lock_file(fd_lockfile); + } + } + //If the fd was invalid (maybe a previous try failed) notify caller that + //should retry creation logic, since this shm might have been already + //unlinked since the shm was removed + else if (fd == GMemMarkToBeRemoved){ + retry_with_new_map = true; + } + //If the stored fd is not valid (a open fd, a normal file with the + //expected size, or does not have the same file id number, + //then it's an old shm from an old process with the same pid. + //If that's the case, mark it as invalid + else if(!is_valid_fd(fd) || + !is_normal_file(fd) || + 0 != get_size(fd) || + !compare_file_serial(fd, *pserial_id)){ + pserial_id->fd = GMemMarkToBeRemoved; + std::string s; + get_map_name(s); + shared_memory_object::remove(s.c_str()); + retry_with_new_map = true; + } + else{ + //If the lock file is ok, increment reference count of + //attached modules to shared memory + atomic_inc32(&pserial_id->modules_attached_to_gmem_count); + } + } + + bool retry() const { return retry_with_new_map; } + + private: + locking_file_serial_id * register_lock_file(int fd) + { + locking_file_serial_id *pinfo = mshm.construct("lock_file_fd")(); + fill_file_serial_id(fd, *pinfo); + return pinfo; + } + + managed_global_memory &mshm; + bool retry_with_new_map; + }; + + static void construct_map(void *addr) + { + std::string s; + intermodule_singleton_helpers::get_map_name(s); + const char *MapName = s.c_str(); + const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();; + ::new (addr)managed_global_memory(open_or_create, MapName, MapSize); + } + + struct unlink_map_logic + { + unlink_map_logic(managed_global_memory &mshm) + : mshm_(mshm) + { mshm.atomic_func(*this); } + + void operator()() + { + locking_file_serial_id *pserial_id = + mshm_.find + ("lock_file_fd").first; + BOOST_ASSERT(0 != pserial_id); + if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){ + int fd = pserial_id->fd; + if(fd > 0){ + pserial_id->fd = GMemMarkToBeRemoved; + std::string s; + create_and_get_singleton_lock_file_path(s); + delete_file(s.c_str()); + close_lock_file(fd); + intermodule_singleton_helpers::get_map_name(s); + shared_memory_object::remove(s.c_str()); + } + } + } + + private: + managed_global_memory &mshm_; + }; + + static ref_count_ptr *find(managed_global_memory &map, const char *name) + { + return map.find(name).first; + } + + static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref) + { + return map.construct(name)(ref); + } + + static bool erase(managed_global_memory &map, const char *name) + { + return map.destroy(name); + } + + template + static void atomic_func(managed_global_memory &map, F &f) + { + map.atomic_func(f); + } +}; + +} //namespace intermodule_singleton_helpers { + +template +class portable_intermodule_singleton + : public intermodule_singleton_impl +{}; + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP diff --git a/extern/boost/boost/interprocess/detail/robust_emulation.hpp b/extern/boost/boost/interprocess/detail/robust_emulation.hpp new file mode 100644 index 00000000000..707782df5fb --- /dev/null +++ b/extern/boost/boost/interprocess/detail/robust_emulation.hpp @@ -0,0 +1,387 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-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_ROBUST_EMULATION_HPP +#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace interprocess{ +namespace ipcdetail{ + +namespace robust_emulation_helpers { + +template +class mutex_traits +{ + public: + static void take_ownership(T &t) + { t.take_ownership(); } +}; + +inline void remove_if_can_lock_file(const char *file_path) +{ + file_handle_t fhnd = open_existing_file(file_path, read_write); + + if(fhnd != invalid_file()){ + bool acquired; + if(try_acquire_file_lock(fhnd, acquired) && acquired){ + delete_file(file_path); + } + close_file(fhnd); + } +} + +inline const char *robust_lock_subdir_path() +{ return "robust"; } + +inline const char *robust_lock_prefix() +{ return "lck"; } + +inline void robust_lock_path(std::string &s) +{ + get_shared_dir(s); + s += "/"; + s += robust_lock_subdir_path(); +} + +inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid) +{ + intermodule_singleton_helpers::create_tmp_subdir_and_get_pid_based_filepath + (robust_lock_subdir_path(), robust_lock_prefix(), pid, s); +} + +//This class will be a intermodule_singleton. The constructor will create +//a lock file, the destructor will erase it. +// +//We should take in care that another process might be erasing unlocked +//files while creating this one, so there are some race conditions we must +//take in care to guarantee some robustness. +class robust_mutex_lock_file +{ + file_handle_t fd; + std::string fname; + public: + robust_mutex_lock_file() + { + permissions p; + p.set_unrestricted(); + //Remove old lock files of other processes + remove_old_robust_lock_files(); + //Create path and obtain lock file path for this process + create_and_get_robust_lock_file_path(fname, get_current_process_id()); + + //Now try to open or create the lock file + fd = create_or_open_file(fname.c_str(), read_write, p); + //If we can't open or create it, then something unrecoverable has happened + if(fd == invalid_file()){ + throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file"); + } + + //Now we must take in care a race condition with another process + //calling "remove_old_robust_lock_files()". No other threads from this + //process will be creating the lock file because intermodule_singleton + //guarantees this. So let's loop acquiring the lock and checking if we + //can't exclusively create the file (if the file is erased by another process + //then this exclusive open would fail). If the file can't be exclusively created + //then we have correctly open/create and lock the file. If the file can + //be exclusively created, then close previous locked file and try again. + while(1){ + bool acquired; + if(!try_acquire_file_lock(fd, acquired) || !acquired ){ + throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock"); + } + //Creating exclusively must fail with already_exists_error + //to make sure we've locked the file and no one has + //deleted it between creation and locking + file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p); + if(fd2 != invalid_file()){ + close_file(fd); + fd = fd2; + continue; + } + //If exclusive creation fails with expected error go ahead + else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist + //Leak descriptor to mantain the file locked until the process dies + break; + } + //If exclusive creation fails with unexpected error throw an unrecoverable error + else{ + close_file(fd); + throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error"); + } + } + } + + ~robust_mutex_lock_file() + { + //The destructor is guaranteed by intermodule_singleton to be + //executed serialized between all threads from current process, + //so we just need to close and unlink the file. + close_file(fd); + //If some other process deletes the file before us after + //closing it there should not be any problem. + delete_file(fname.c_str()); + } + + private: + //This functor is execute for all files in the lock file directory + class other_process_lock_remover + { + public: + void operator()(const char *filepath, const char *filename) + { + std::string pid_str; + //If the lock file is not our own lock file, then try to do the cleanup + if(!intermodule_singleton_helpers::check_if_filename_complies_with_pid + (filename, robust_lock_prefix(), get_current_process_id(), pid_str)){ + remove_if_can_lock_file(filepath); + } + } + }; + + bool remove_old_robust_lock_files() + { + std::string refcstrRootDirectory; + robust_lock_path(refcstrRootDirectory); + return for_each_file_in_dir(refcstrRootDirectory.c_str(), other_process_lock_remover()); + } +}; + +} //namespace robust_emulation_helpers { + +//This is the mutex class. Mutex should follow mutex concept +//with an additonal "take_ownership()" function to take ownership of the +//mutex when robust_spin_mutex determines the previous owner was dead. +template +class robust_spin_mutex +{ + public: + static const boost::uint32_t correct_state = 0; + static const boost::uint32_t fixing_state = 1; + static const boost::uint32_t broken_state = 2; + + typedef robust_emulation_helpers::mutex_traits mutex_traits_t; + + robust_spin_mutex(); + void lock(); + bool try_lock(); + template + bool timed_lock(const TimePoint &abs_time); + void unlock(); + void consistent(); + bool previous_owner_dead(); + + private: + static const unsigned int spin_threshold = 100u; + bool lock_own_unique_file(); + bool robust_check(); + bool check_if_owner_dead_and_take_ownership_atomically(); + bool is_owner_dead(boost::uint32_t own); + void owner_to_filename(boost::uint32_t own, std::string &s); + //The real mutex + Mutex mtx; + //The pid of the owner + volatile boost::uint32_t owner; + //The state of the mutex (correct, fixing, broken) + volatile boost::uint32_t state; +}; + +template +inline robust_spin_mutex::robust_spin_mutex() + : mtx(), owner((boost::uint32_t)get_invalid_process_id()), state(correct_state) +{} + +template +inline void robust_spin_mutex::lock() +{ try_based_lock(*this); } + +template +inline bool robust_spin_mutex::try_lock() +{ + //Same as lock() but without spinning + if(atomic_read32(&this->state) == broken_state){ + throw interprocess_exception(lock_error, "Broken id"); + } + + if(!this->lock_own_unique_file()){ + throw interprocess_exception(lock_error, "Broken id"); + } + + if (mtx.try_lock()){ + atomic_write32(&this->owner, static_cast(get_current_process_id())); + return true; + } + else{ + if(!this->robust_check()){ + return false; + } + else{ + return true; + } + } +} + +template +template +inline bool robust_spin_mutex::timed_lock + (const TimePoint &abs_time) +{ return try_based_timed_lock(*this, abs_time); } + +template +inline void robust_spin_mutex::owner_to_filename(boost::uint32_t own, std::string &s) +{ + robust_emulation_helpers::create_and_get_robust_lock_file_path(s, (OS_process_id_t)own); +} + +template +inline bool robust_spin_mutex::robust_check() +{ + //If the old owner was dead, and we've acquired ownership, mark + //the mutex as 'fixing'. This means that a "consistent()" is needed + //to avoid marking the mutex as "broken" when the mutex is unlocked. + if(!this->check_if_owner_dead_and_take_ownership_atomically()){ + return false; + } + atomic_write32(&this->state, fixing_state); + return true; +} + +template +inline bool robust_spin_mutex::check_if_owner_dead_and_take_ownership_atomically() +{ + boost::uint32_t cur_owner = static_cast(get_current_process_id()); + boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2; + //The cas loop guarantees that only one thread from this or another process + //will succeed taking ownership + do{ + //Check if owner is dead + if(!this->is_owner_dead(old_owner)){ + return false; + } + //If it's dead, try to mark this process as the owner in the owner field + old_owner2 = old_owner; + old_owner = atomic_cas32(&this->owner, cur_owner, old_owner); + }while(old_owner2 != old_owner); + //If success, we fix mutex internals to assure our ownership + mutex_traits_t::take_ownership(mtx); + return true; +} + +template +inline bool robust_spin_mutex::is_owner_dead(boost::uint32_t own) +{ + //If owner is an invalid id, then it's clear it's dead + if(own == static_cast(get_invalid_process_id())){ + return true; + } + + //Obtain the lock filename of the owner field + std::string file; + this->owner_to_filename(own, file); + + //Now the logic is to open and lock it + file_handle_t fhnd = open_existing_file(file.c_str(), read_write); + + if(fhnd != invalid_file()){ + //If we can open the file, lock it. + bool acquired; + if(try_acquire_file_lock(fhnd, acquired) && acquired){ + //If locked, just delete the file + delete_file(file.c_str()); + close_file(fhnd); + return true; + } + //If not locked, the owner is suppossed to be still alive + close_file(fhnd); + } + else{ + //If the lock file does not exist then the owner is dead (a previous cleanup) + //function has deleted the file. If there is another reason, then this is + //an unrecoverable error + if(error_info(system_error_code()).get_error_code() == not_found_error){ + return true; + } + } + return false; +} + +template +inline void robust_spin_mutex::consistent() +{ + //This function supposes the previous state was "fixing" + //and the current process holds the mutex + if(atomic_read32(&this->state) != fixing_state && + atomic_read32(&this->owner) != (boost::uint32_t)get_current_process_id()){ + throw interprocess_exception(lock_error, "Broken id"); + } + //If that's the case, just update mutex state + atomic_write32(&this->state, correct_state); +} + +template +inline bool robust_spin_mutex::previous_owner_dead() +{ + //Notifies if a owner recovery has been performed in the last lock() + return atomic_read32(&this->state) == fixing_state; +} + +template +inline void robust_spin_mutex::unlock() +{ + //If in "fixing" state, unlock and mark the mutex as unrecoverable + //so next locks will fail and all threads will be notified that the + //data protected by the mutex was not recoverable. + if(atomic_read32(&this->state) == fixing_state){ + atomic_write32(&this->state, broken_state); + } + //Write an invalid owner to minimize pid reuse possibility + atomic_write32(&this->owner, static_cast(get_invalid_process_id())); + mtx.unlock(); +} + +template +inline bool robust_spin_mutex::lock_own_unique_file() +{ + //This function forces instantiation of the singleton + robust_emulation_helpers::robust_mutex_lock_file* dummy = + &ipcdetail::intermodule_singleton + ::get(); + return dummy != 0; +} + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif diff --git a/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp b/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp new file mode 100644 index 00000000000..f943cf7363f --- /dev/null +++ b/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp @@ -0,0 +1,503 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SEGMENT_MANAGER_BASE_HPP +#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess +#include +// interprocess/detail +#include +#include +#include +// container/detail +#include //alignment_of +#include +// intrusive +#include +// move/detail +#include //make_unsigned +#include +// other boost +#include //BOOST_ASSERT +#include +// std +#include //std::size_t + +//!\file +//!Describes the object placed in a memory segment that provides +//!named object allocation capabilities. + +namespace boost{ +namespace interprocess{ + +template +class segment_manager_base; + +//!An integer that describes the type of the +//!instance constructed in memory +enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type }; + +namespace ipcdetail{ + +template +class mem_algo_deallocator +{ + void * m_ptr; + MemoryAlgorithm & m_algo; + + public: + mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo) + : m_ptr(ptr), m_algo(algo) + {} + + void release() + { m_ptr = 0; } + + ~mem_algo_deallocator() + { if(m_ptr) m_algo.deallocate(m_ptr); } +}; + +template +struct block_header +{ + size_type m_value_bytes; + unsigned short m_num_char; + unsigned char m_value_alignment; + unsigned char m_alloc_type_sizeof_char; + + block_header(size_type val_bytes + ,size_type val_alignment + ,unsigned char al_type + ,std::size_t szof_char + ,std::size_t num_char + ) + : m_value_bytes(val_bytes) + , m_num_char((unsigned short)num_char) + , m_value_alignment((unsigned char)val_alignment) + , m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) ) + {}; + + template + block_header &operator= (const T& ) + { return *this; } + + size_type total_size() const + { + if(alloc_type() != anonymous_type){ + return name_offset() + (m_num_char+1u)*sizeof_char(); + } + else{ + return this->value_offset() + m_value_bytes; + } + } + + size_type value_bytes() const + { return m_value_bytes; } + + template + size_type total_size_with_header() const + { + return get_rounded_size + ( size_type(sizeof(Header)) + , size_type(::boost::container::dtl::alignment_of >::value)) + + total_size(); + } + + unsigned char alloc_type() const + { return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; } + + unsigned char sizeof_char() const + { return m_alloc_type_sizeof_char & (unsigned char)0x1F; } + + template + CharType *name() const + { + return const_cast(move_detail::force_ptr + (reinterpret_cast(this) + name_offset())); + } + + unsigned short name_length() const + { return m_num_char; } + + size_type name_offset() const + { + return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char())); + } + + void *value() const + { + return const_cast((reinterpret_cast(this) + this->value_offset())); + } + + size_type value_offset() const + { + return get_rounded_size(size_type(sizeof(block_header)), size_type(m_value_alignment)); + } + + template + bool less_comp(const block_header &b) const + { + return m_num_char < b.m_num_char || + (m_num_char < b.m_num_char && + std::char_traits::compare(name(), b.name(), m_num_char) < 0); + } + + template + bool equal_comp(const block_header &b) const + { + return m_num_char == b.m_num_char && + std::char_traits::compare(name(), b.name(), m_num_char) == 0; + } + + template + static block_header *block_header_from_value(T *value) + { return block_header_from_value(value, sizeof(T), ::boost::container::dtl::alignment_of::value); } + + static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) + { + block_header * hdr = + const_cast + (move_detail::force_ptr(reinterpret_cast(value) - + get_rounded_size(sizeof(block_header), algn))); + (void)sz; + //Some sanity checks + BOOST_ASSERT(hdr->m_value_alignment == algn); + BOOST_ASSERT(hdr->m_value_bytes % sz == 0); + return hdr; + } + + template + static block_header *from_first_header(Header *header) + { + block_header * hdr = + move_detail::force_ptr*>(reinterpret_cast(header) + + get_rounded_size( size_type(sizeof(Header)) + , size_type(::boost::container::dtl::alignment_of >::value))); + //Some sanity checks + return hdr; + } + + template + static Header *to_first_header(block_header *bheader) + { + Header * hdr = + move_detail::force_ptr(reinterpret_cast(bheader) - + get_rounded_size( size_type(sizeof(Header)) + , size_type(::boost::container::dtl::alignment_of >::value))); + //Some sanity checks + return hdr; + } +}; + +template +struct intrusive_compare_key +{ + typedef CharT char_type; + + intrusive_compare_key(const CharT *str, std::size_t len) + : mp_str(str), m_len(len) + {} + + const CharT * mp_str; + std::size_t m_len; +}; + +//!This struct indicates an anonymous object creation +//!allocation +template +class instance_t +{ + instance_t(){} +}; + +template +struct char_if_void +{ + typedef T type; +}; + +template<> +struct char_if_void +{ + typedef char type; +}; + +typedef instance_t anonymous_instance_t; +typedef instance_t unique_instance_t; + + +template +struct intrusive_value_type_impl + : public Hook +{ + private: + //Non-copyable + intrusive_value_type_impl(const intrusive_value_type_impl &); + intrusive_value_type_impl& operator=(const intrusive_value_type_impl &); + + public: + typedef CharType char_type; + typedef SizeType size_type; + + intrusive_value_type_impl(){} + + enum { BlockHdrAlignment = ::boost::container::dtl::alignment_of >::value }; + + block_header *get_block_header() const + { + return const_cast*> + (move_detail::force_ptr *>(reinterpret_cast(this) + + get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment)))); + } + + bool operator <(const intrusive_value_type_impl & other) const + { return (this->get_block_header())->template less_comp(*other.get_block_header()); } + + bool operator ==(const intrusive_value_type_impl & other) const + { return (this->get_block_header())->template equal_comp(*other.get_block_header()); } + + static intrusive_value_type_impl *get_intrusive_value_type(block_header *hdr) + { + return move_detail::force_ptr(reinterpret_cast(hdr) - + get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment))); + } + + CharType *name() const + { return get_block_header()->template name(); } + + unsigned short name_length() const + { return get_block_header()->name_length(); } + + void *value() const + { return get_block_header()->value(); } +}; + +template +class char_ptr_holder +{ + public: + char_ptr_holder(const CharType *name) + : m_name(name) + {} + + char_ptr_holder(const anonymous_instance_t *) + : m_name(static_cast(0)) + {} + + char_ptr_holder(const unique_instance_t *) + : m_name(reinterpret_cast(-1)) + {} + + operator const CharType *() + { return m_name; } + + const CharType *get() const + { return m_name; } + + bool is_unique() const + { return m_name == reinterpret_cast(-1); } + + bool is_anonymous() const + { return m_name == static_cast(0); } + + private: + const CharType *m_name; +}; + +//!The key of the the named allocation information index. Stores an offset pointer +//!to a null terminated string and the length of the string to speed up sorting +template +struct index_key +{ + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_char_ptr_t; + typedef CharT char_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::move_detail::make_unsigned::type size_type; + + private: + //Offset pointer to the object's name + const_char_ptr_t mp_str; + //Length of the name buffer (null NOT included) + size_type m_len; + public: + + //!Constructor of the key + index_key (const char_type *nm, size_type length) + : mp_str(nm), m_len(length) + {} + + //!Less than function for index ordering + bool operator < (const index_key & right) const + { + return (m_len < right.m_len) || + (m_len == right.m_len && + std::char_traits::compare + (to_raw_pointer(mp_str),to_raw_pointer(right.mp_str), m_len) < 0); + } + + //!Equal to function for index ordering + bool operator == (const index_key & right) const + { + return m_len == right.m_len && + std::char_traits::compare + (to_raw_pointer(mp_str), to_raw_pointer(right.mp_str), m_len) == 0; + } + + void name(const CharT *nm) + { mp_str = nm; } + + void name_length(size_type len) + { m_len = len; } + + const CharT *name() const + { return to_raw_pointer(mp_str); } + + size_type name_length() const + { return m_len; } +}; + +//!The index_data stores a pointer to a buffer and the element count needed +//!to know how many destructors must be called when calling destroy +template +struct index_data +{ + typedef VoidPointer void_pointer; + void_pointer m_ptr; + explicit index_data(void *ptr) : m_ptr(ptr){} + + void *value() const + { return static_cast(to_raw_pointer(m_ptr)); } +}; + +template +struct segment_manager_base_type +{ typedef segment_manager_base type; }; + +template +struct index_config +{ + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef CharT char_type; + typedef index_key key_type; + typedef index_data mapped_type; + typedef typename segment_manager_base_type + ::type segment_manager_base; + + template + struct intrusive_value_type + { typedef intrusive_value_type_impl type; }; + + typedef intrusive_compare_key intrusive_compare_key_type; +}; + +template +class segment_manager_iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::char_type char_type; + + public: + segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->name(); } + + unsigned short name_length() const + { return m_val->name_length(); } + + const void *value() const + { return m_val->value(); } + + const typename Iterator::value_type *m_val; +}; + + +template +class segment_manager_iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::first_type first_type; + typedef typename iterator_val_t::second_type second_type; + typedef typename first_type::char_type char_type; + typedef typename first_type::size_type size_type; + + public: + segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->first.name(); } + + size_type name_length() const + { return m_val->first.name_length(); } + + const void *value() const + { + return move_detail::force_ptr*> + (to_raw_pointer(m_val->second.m_ptr))->value(); + } + + const typename Iterator::value_type *m_val; +}; + +template +struct segment_manager_iterator_transform +{ + typedef segment_manager_iterator_value_adaptor result_type; + + template result_type operator()(const T &arg) const + { return result_type(arg); } +}; + +} //namespace ipcdetail { + +//These pointers are the ones the user will use to +//indicate previous allocation types +static const ipcdetail::anonymous_instance_t * anonymous_instance = 0; +static const ipcdetail::unique_instance_t * unique_instance = 0; + +namespace ipcdetail_really_deep_namespace { + +//Otherwise, gcc issues a warning of previously defined +//anonymous_instance and unique_instance +struct dummy +{ + dummy() + { + (void)anonymous_instance; + (void)unique_instance; + } +}; + +} //detail_really_deep_namespace + +}} //namespace boost { namespace interprocess + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP + diff --git a/extern/boost/boost/interprocess/detail/transform_iterator.hpp b/extern/boost/boost/interprocess/detail/transform_iterator.hpp new file mode 100644 index 00000000000..d409b523622 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/transform_iterator.hpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2015. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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_TRANSFORM_ITERATORS_HPP +#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess +#include +// container/detail +#include + +namespace boost { +namespace interprocess { + +using boost::container::make_transform_iterator; +using boost::container::transform_iterator; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP diff --git a/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp b/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp new file mode 100644 index 00000000000..936f702bc26 --- /dev/null +++ b/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp @@ -0,0 +1,35 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_VARIADIC_TEMPLATES_TOOLS_HPP +#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +using boost::container::dtl::tuple; +using boost::container::dtl::build_number_seq; +using boost::container::dtl::index_tuple; +using boost::container::dtl::get; + +}}} //namespace boost { namespace interprocess { namespace ipcdetail { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP diff --git a/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp new file mode 100644 index 00000000000..b1fe449281e --- /dev/null +++ b/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp @@ -0,0 +1,88 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP +#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +//!\file +//!Describes a class representing a pseudo-file implemented on top of xsi shared memory. + +namespace boost { +namespace interprocess { + +class xsi_shared_memory_file_wrapper + : public xsi_shared_memory +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} + + xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) + : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions()) + {} + + xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) + : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions()) + {} + + xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t, const permissions& = permissions()) + : xsi_shared_memory(open_only_t(), key) + {} + + xsi_shared_memory_file_wrapper(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) + { this->swap(moved); } + + xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) + { + xsi_shared_memory_file_wrapper tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps two xsi_shared_memory_file_wrapper. Does not throw + void swap(xsi_shared_memory_file_wrapper &other) + { this->xsi_shared_memory::swap(other); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/file_mapping.hpp b/extern/boost/boost/interprocess/file_mapping.hpp new file mode 100644 index 00000000000..88268fa0ef0 --- /dev/null +++ b/extern/boost/boost/interprocess/file_mapping.hpp @@ -0,0 +1,250 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_FILE_MAPPING_HPP +#define BOOST_INTERPROCESS_FILE_MAPPING_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#if !defined(BOOST_INTERPROCESS_MAPPED_FILES) +#error "Boost.Interprocess: This platform does not support memory mapped files!" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes file_mapping and mapped region classes + +namespace boost { +namespace interprocess { + +//!A class that wraps a file-mapping that can be used to +//!create mapped regions from the mapped files +class file_mapping +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructs an empty file mapping. + //!Does not throw + file_mapping() BOOST_NOEXCEPT; + + //!Opens a file mapping of file "filename", starting in offset + //!"file_offset", and the mapping's size will be "size". The mapping + //!can be opened for read-only "read_only" or read-write "read_write" + //!modes. Throws interprocess_exception on error. + file_mapping(const char *filename, mode_t mode); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Opens a file mapping of file "filename", starting in offset + //!"file_offset", and the mapping's size will be "size". The mapping + //!can be opened for read-only "read_only" or read-write "read_write" + //!modes. Throws interprocess_exception on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_mapping(const wchar_t *filename, mode_t mode); + #endif + + //!Moves the ownership of "moved"'s file mapping object to *this. + //!After the call, "moved" does not represent any file mapping object. + //!Does not throw + file_mapping(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT + : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) + { this->swap(moved); } + + //!Moves the ownership of "moved"'s file mapping to *this. + //!After the call, "moved" does not represent any file mapping. + //!Does not throw + file_mapping &operator=(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT + { + file_mapping tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps to file_mappings. + //!Does not throw. + void swap(file_mapping &other) BOOST_NOEXCEPT; + + //!Returns access mode + //!used in the constructor + mode_t get_mode() const BOOST_NOEXCEPT; + + //!Obtains the mapping handle + //!to be used with mapped_region + mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; + + //!Destroys the file mapping. All mapped regions created from this are still + //!valid. Does not throw + ~file_mapping(); + + //!Returns the name of the file + //!used in the constructor. + const char *get_name() const BOOST_NOEXCEPT; + + //!Removes the file named "filename" even if it's been memory mapped. + //!Returns true on success. + //!The function might fail in some operating systems if the file is + //!being used other processes and no deletion permission was shared. + static bool remove(const char *filename); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Removes the file named "filename" even if it's been memory mapped. + //!Returns true on success. + //!The function might fail in some operating systems if the file is + //!being used other processes and no deletion permission was shared. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *filename); + #endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + file_handle_t m_handle; + mode_t m_mode; + char_wchar_holder m_filename; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline file_mapping::file_mapping() BOOST_NOEXCEPT + : m_handle(file_handle_t(ipcdetail::invalid_file())) + , m_mode(read_only) +{} + +inline file_mapping::~file_mapping() +{ this->priv_close(); } + +inline const char *file_mapping::get_name() const BOOST_NOEXCEPT +{ return m_filename.getn(); } + +inline void file_mapping::swap(file_mapping &other) BOOST_NOEXCEPT +{ + (simple_swap)(m_handle, other.m_handle); + (simple_swap)(m_mode, other.m_mode); + m_filename.swap(other.m_filename); +} + +inline mapping_handle_t file_mapping::get_mapping_handle() const BOOST_NOEXCEPT +{ return ipcdetail::mapping_handle_from_file_handle(m_handle); } + +inline mode_t file_mapping::get_mode() const BOOST_NOEXCEPT +{ return m_mode; } + +inline file_mapping::file_mapping + (const char *filename, mode_t mode) + : m_filename(filename) +{ + //Check accesses + if (mode != read_write && mode != read_only){ + error_info err = other_error; + throw interprocess_exception(err); + } + + //Open file + m_handle = ipcdetail::open_existing_file(filename, mode); + + //Check for error + if(m_handle == ipcdetail::invalid_file()){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + m_mode = mode; +} + +inline bool file_mapping::remove(const char *filename) +{ return ipcdetail::delete_file(filename); } + +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES +inline file_mapping::file_mapping + (const wchar_t *filename, mode_t mode) + : m_filename(filename) +{ + //Check accesses + if (mode != read_write && mode != read_only){ + error_info err = other_error; + throw interprocess_exception(err); + } + + //Open file + m_handle = ipcdetail::open_existing_file(filename, mode); + + //Check for error + if(m_handle == ipcdetail::invalid_file()){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + m_mode = mode; +} + +inline bool file_mapping::remove(const wchar_t *filename) +{ return ipcdetail::delete_file(filename); } + +#endif + + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void file_mapping::priv_close() +{ + if(m_handle != ipcdetail::invalid_file()){ + ipcdetail::close_file(m_handle); + m_handle = ipcdetail::invalid_file(); + } +} + +//!A class that stores the name of a file +//!and tries to remove it in its destructor +//!Useful to remove temporary files in the presence +//!of exceptions +class remove_file_on_destroy +{ + const char * m_name; + public: + remove_file_on_destroy(const char *name) + : m_name(name) + {} + + ~remove_file_on_destroy() + { ipcdetail::delete_file(m_name); } +}; + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_FILE_MAPPING_HPP diff --git a/extern/boost/boost/interprocess/indexes/flat_map_index.hpp b/extern/boost/boost/interprocess/indexes/flat_map_index.hpp new file mode 100644 index 00000000000..027b75be47c --- /dev/null +++ b/extern/boost/boost/interprocess/indexes/flat_map_index.hpp @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_FLAT_MAP_INDEX_HPP +#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess +#include +#include +// intrusive/detail +#include //std::pair +#include //std::less + + +//!\file +//!Describes index adaptor of boost::map container, to use it +//!as name/shared memory index + +//[flat_map_index +namespace boost { namespace interprocess { + +#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Helper class to define typedefs from IndexTraits +template +struct flat_map_index_aux +{ + typedef typename MapConfig::key_type key_type; + typedef typename MapConfig::mapped_type mapped_type; + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + typedef std::less key_less; + typedef std::pair value_type; + typedef allocator allocator_type; + typedef flat_map index_t; +}; + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Index type based in flat_map. Just derives from flat_map and +//!defines the interface needed by managed memory segments. +template +class flat_map_index + //Derive class from flat_map specialization + : public flat_map_index_aux::index_t +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef flat_map_index_aux index_aux; + typedef typename index_aux::index_t base_type; + typedef typename index_aux:: + segment_manager_base segment_manager_base; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Takes a pointer to the segment manager. Can throw + flat_map_index(segment_manager_base *segment_mngr) + : base_type(typename index_aux::key_less(), + typename index_aux::allocator_type(segment_mngr)) + {} + + //!This reserves memory to optimize the insertion of n elements in the index + void reserve(typename segment_manager_base::size_type n) + { base_type::reserve(n); } + + //!This frees all unnecessary memory + void shrink_to_fit() + { base_type::shrink_to_fit(); } +}; + +}} //namespace boost { namespace interprocess +//] +#include + +#endif //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/iset_index.hpp b/extern/boost/boost/interprocess/indexes/iset_index.hpp new file mode 100644 index 00000000000..ffaa24fa775 --- /dev/null +++ b/extern/boost/boost/interprocess/indexes/iset_index.hpp @@ -0,0 +1,158 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ISET_INDEX_HPP +#define BOOST_INTERPROCESS_ISET_INDEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include //std::pair +#include //std::less +#include //std::char_traits +#include + +//!\file +//!Describes index adaptor of boost::intrusive::set container, to use it +//!as name/shared memory index + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//!Helper class to define typedefs from IndexTraits +template +struct iset_index_aux +{ + typedef typename + MapConfig::segment_manager_base segment_manager_base; + + typedef typename + segment_manager_base::void_pointer void_pointer; + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + >::type derivation_hook; + + typedef typename MapConfig::template + intrusive_value_type::type value_type; + typedef std::less value_compare; + typedef typename bi::make_set + < value_type + , bi::base_hook + >::type index_t; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Index type based in boost::intrusive::set. +//!Just derives from boost::intrusive::set +//!and defines the interface needed by managed memory segments*/ +template +class iset_index + //Derive class from map specialization + : public iset_index_aux::index_t +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef iset_index_aux index_aux; + typedef typename index_aux::index_t index_type; + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + typedef typename MapConfig::char_type char_type; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef typename index_type::iterator iterator; + typedef typename index_type::const_iterator const_iterator; + typedef typename index_type::insert_commit_data insert_commit_data; + typedef typename index_type::value_type value_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + struct intrusive_key_value_less + { + bool operator()(const intrusive_compare_key_type &i, const value_type &b) const + { + std::size_t blen = b.name_length(); + return (i.m_len < blen) || + (i.m_len == blen && + std::char_traits::compare + (i.mp_str, b.name(), i.m_len) < 0); + } + + bool operator()(const value_type &b, const intrusive_compare_key_type &i) const + { + std::size_t blen = b.name_length(); + return (blen < i.m_len) || + (blen == i.m_len && + std::char_traits::compare + (b.name(), i.mp_str, i.m_len) < 0); + } + }; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + iset_index(typename MapConfig::segment_manager_base *) + : index_type(/*typename index_aux::value_compare()*/) + {} + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(typename MapConfig::segment_manager_base::size_type) + { /*Does nothing, map has not reserve or rehash*/ } + + //!This frees all unnecessary memory + void shrink_to_fit() + { /*Does nothing, this intrusive index does not allocate memory;*/ } + + iterator find(const intrusive_compare_key_type &key) + { return index_type::find(key, intrusive_key_value_less()); } + + const_iterator find(const intrusive_compare_key_type &key) const + { return index_type::find(key, intrusive_key_value_less()); } + + std::pairinsert_check + (const intrusive_compare_key_type &key, insert_commit_data &commit_data) + { return index_type::insert_check(key, intrusive_key_value_less(), commit_data); } +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//!Trait class to detect if an index is an intrusive +//!index. +template +struct is_intrusive_index + > +{ + static const bool value = true; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost + +#include + +#endif //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp b/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp new file mode 100644 index 00000000000..9599e8a422e --- /dev/null +++ b/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp @@ -0,0 +1,390 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_IUNORDERED_SET_INDEX_HPP +#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include //std::less +#include //std::char_traits +#include +#include + +//!\file +//!Describes index adaptor of boost::intrusive::unordered_set container, to use it +//!as name/shared memory index + +namespace boost { namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//!Helper class to define typedefs +//!from IndexTraits +template +struct iunordered_set_index_aux +{ + typedef typename + MapConfig::segment_manager_base segment_manager_base; + + typedef typename + segment_manager_base::void_pointer void_pointer; + + typedef typename bi::make_unordered_set_base_hook + < bi::void_pointer + >::type derivation_hook; + + typedef typename MapConfig::template + intrusive_value_type::type value_type; + + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + + typedef std::equal_to value_equal; + + typedef typename MapConfig::char_type char_type; + + struct equal_function + { + bool operator()(const intrusive_compare_key_type &i, const value_type &b) const + { + return (i.m_len == b.name_length()) && + (std::char_traits::compare + (i.mp_str, b.name(), i.m_len) == 0); + } + + bool operator()(const value_type &b, const intrusive_compare_key_type &i) const + { + return (i.m_len == b.name_length()) && + (std::char_traits::compare + (i.mp_str, b.name(), i.m_len) == 0); + } + + bool operator()(const value_type &b1, const value_type &b2) const + { + return (b1.name_length() == b2.name_length()) && + (std::char_traits::compare + (b1.name(), b2.name(), b1.name_length()) == 0); + } + }; + + struct hash_function + { + typedef value_type argument_type; + typedef std::size_t result_type; + + std::size_t hash_char_range(const char_type* beg, const char_type* end) const + { + std::size_t seed = 0; + while (beg != end) { + boost::intrusive::detail::hash_combine_size_t(seed, boost::intrusive::detail::internal_hash_functor()(*beg)); + ++beg; + } + return seed; + } + + std::size_t operator()(const value_type &val) const + { + const char_type* beg = ipcdetail::to_raw_pointer(val.name()), + * end = beg + val.name_length(); + return hash_char_range(beg, end); + } + + std::size_t operator()(const intrusive_compare_key_type &i) const + { + const char_type *beg = i.mp_str, + *end = beg + i.m_len; + return hash_char_range(beg, end); + } + }; + + typedef typename bi::make_unordered_set + < value_type + , bi::hash + , bi::equal + , bi::size_type + >::type index_t; + typedef typename index_t::bucket_type bucket_type; + typedef allocator + allocator_type; + + struct allocator_holder + { + allocator_holder(segment_manager_base *mngr) + : alloc(mngr) + {} + allocator_type alloc; + bucket_type init_bucket; + }; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Index type based in boost::intrusive::set. +//!Just derives from boost::intrusive::set +//!and defines the interface needed by managed memory segments +template +class iunordered_set_index + //Derive class from map specialization + : private iunordered_set_index_aux::allocator_holder + , public iunordered_set_index_aux::index_t +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef iunordered_set_index_aux index_aux; + typedef typename index_aux::index_t index_type; + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + typedef typename index_aux::equal_function equal_function; + typedef typename index_aux::hash_function hash_function; + typedef typename MapConfig::char_type char_type; + typedef typename + iunordered_set_index_aux::allocator_type allocator_type; + typedef typename + iunordered_set_index_aux::allocator_holder allocator_holder; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef typename index_type::iterator iterator; + typedef typename index_type::const_iterator const_iterator; + typedef typename index_type::insert_commit_data insert_commit_data; + typedef typename index_type::value_type value_type; + typedef typename index_type::bucket_ptr bucket_ptr; + typedef typename index_type::bucket_type bucket_type; + typedef typename index_type::bucket_traits bucket_traits; + typedef typename index_type::size_type size_type; + typedef typename index_type::difference_type difference_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef typename index_aux:: + segment_manager_base segment_manager_base; + + static const std::size_t InitBufferSize = 64; + + static bucket_ptr create_buckets(allocator_type &alloc, size_type num) + { + num = index_type::suggested_upper_bucket_count(num); + bucket_ptr buckets = alloc.allocate(num); + bucket_ptr buckets_init = buckets; + for(size_type i = 0; i < num; ++i){ + ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); + } + return buckets; + } + + static size_type shrink_buckets + ( bucket_ptr buckets, size_type old_size + , allocator_type &alloc, size_type new_size) + { + if(old_size <= new_size ) + return old_size; + size_type received_size = new_size; + if(!alloc.allocation_command + (boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, received_size, buckets)){ + return old_size; + } + + for( bucket_type *p = ipcdetail::to_raw_pointer(buckets) + received_size + , *pend = ipcdetail::to_raw_pointer(buckets) + old_size + ; p != pend + ; ++p){ + p->~bucket_type(); + } + + bucket_ptr shunk_p = alloc.allocation_command + (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, buckets); + BOOST_ASSERT(buckets == shunk_p); (void)shunk_p; + + bucket_ptr buckets_init = buckets + difference_type(received_size); + for(size_type i = 0; i < (old_size - received_size); ++i){ + to_raw_pointer(buckets_init++)->~bucket_type(); + } + return received_size; + } + + static bucket_ptr expand_or_create_buckets + ( bucket_ptr old_buckets, const size_type old_num + , allocator_type &alloc, const size_type new_num) + { + size_type received_size = new_num; + bucket_ptr reuse(old_buckets); + bucket_ptr ret = alloc.allocation_command + (boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, received_size, reuse); + if(ret == old_buckets){ + bucket_ptr buckets_init = old_buckets + difference_type(old_num); + for(size_type i = 0; i < (new_num - old_num); ++i){ + ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); + } + } + else{ + bucket_ptr buckets_init = ret; + for(size_type i = 0; i < new_num; ++i){ + ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); + } + } + return ret; + } + + static void destroy_buckets + (allocator_type &alloc, bucket_ptr buckets, size_type num) + { + bucket_ptr buckets_destroy = buckets; + for(size_type i = 0; i < num; ++i){ + to_raw_pointer(buckets_destroy++)->~bucket_type(); + } + alloc.deallocate(buckets, num); + } + + iunordered_set_index* get_this_pointer() + { return this; } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + iunordered_set_index(segment_manager_base *mngr) + : allocator_holder(mngr) + , index_type(bucket_traits(&get_this_pointer()->init_bucket, 1)) + {} + + ~iunordered_set_index() + { + index_type::clear(); + if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){ + destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count()); + } + } + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(size_type new_n) + { + //Let's maintain a 1.0f load factor + size_type old_n = this->bucket_count(); + if(new_n <= old_n) + return; + bucket_ptr old_p = this->bucket_pointer(); + new_n = index_type::suggested_upper_bucket_count(new_n); + bucket_ptr new_p; + //This can throw + BOOST_TRY{ + if(old_p != bucket_ptr(&this->init_bucket)) + new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n); + else + new_p = create_buckets(this->alloc, new_n); + } + BOOST_CATCH(...){ + return; + } BOOST_CATCH_END + //Rehashing does not throw, since neither the hash nor the + //comparison function can throw + this->rehash(bucket_traits(new_p, new_n)); + if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){ + destroy_buckets(this->alloc, old_p, old_n); + } + } + + //!This tries to free unused memory + //!previously allocated. + void shrink_to_fit() + { + size_type cur_size = this->size(); + size_type cur_count = this->bucket_count(); + bucket_ptr old_p = this->bucket_pointer(); + + if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){ + this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1)); + destroy_buckets(this->alloc, old_p, cur_count); + } + else{ + size_type sug_count = 0; //gcc warning + sug_count = index_type::suggested_upper_bucket_count(cur_size); + + if(sug_count >= cur_count) + return; + + BOOST_TRY{ + shrink_buckets(old_p, cur_count, this->alloc, sug_count); + } + BOOST_CATCH(...){ + return; + } BOOST_CATCH_END + + //Rehashing does not throw, since neither the hash nor the + //comparison function can throw + this->rehash(bucket_traits(old_p, sug_count)); + } + } + + iterator find(const intrusive_compare_key_type &key) + { return index_type::find(key, hash_function(), equal_function()); } + + const_iterator find(const intrusive_compare_key_type &key) const + { return index_type::find(key, hash_function(), equal_function()); } + + std::pairinsert_check + (const intrusive_compare_key_type &key, insert_commit_data &commit_data) + { return index_type::insert_check(key, hash_function(), equal_function(), commit_data); } + + iterator insert_commit(value_type &val, insert_commit_data &commit_data) + { + iterator it = index_type::insert_commit(val, commit_data); + size_type cur_size = this->size(); + if(cur_size > this->bucket_count()){ + BOOST_TRY{ + this->reserve(cur_size); + } + BOOST_CATCH(...){ + //Strong guarantee: if something goes wrong + //we should remove the insertion. + // + //We can use the iterator because the hash function + //can't throw and this means that "reserve" will + //throw only because of the memory allocation: + //the iterator has not been invalidated. + index_type::erase(it); + BOOST_RETHROW + } BOOST_CATCH_END + } + return it; + } +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//!Trait class to detect if an index is an intrusive +//!index +template +struct is_intrusive_index + > +{ + static const bool value = true; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/map_index.hpp b/extern/boost/boost/interprocess/indexes/map_index.hpp new file mode 100644 index 00000000000..c7c3c865d13 --- /dev/null +++ b/extern/boost/boost/interprocess/indexes/map_index.hpp @@ -0,0 +1,109 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MAP_INDEX_HPP +#define BOOST_INTERPROCESS_MAP_INDEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include //std::pair +#include //std::less + +//!\file +//!Describes index adaptor of boost::map container, to use it +//!as name/shared memory index + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//!Helper class to define typedefs from IndexTraits +template +struct map_index_aux +{ + typedef typename MapConfig::key_type key_type; + typedef typename MapConfig::mapped_type mapped_type; + typedef std::less key_less; + typedef std::pair value_type; + + typedef private_adaptive_pool + allocator_type; + + typedef boost::interprocess::map + index_t; +}; + +} //namespace ipcdetail { + +//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map +//!and defines the interface needed by managed memory segments +template +class map_index + //Derive class from map specialization + : public ipcdetail::map_index_aux::index_t +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef ipcdetail::map_index_aux index_aux; + typedef typename index_aux::index_t base_type; + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + map_index(segment_manager_base *segment_mngr) + : base_type(typename index_aux::key_less(), + segment_mngr){} + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(typename segment_manager_base::size_type) + { /*Does nothing, map has not reserve or rehash*/ } + + //!This tries to free previously allocate + //!unused memory. + void shrink_to_fit() + { base_type::get_stored_allocator().deallocate_free_blocks(); } +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//!Trait class to detect if an index is a node +//!index. This allows more efficient operations +//!when deallocating named objects. +template +struct is_node_index + > +{ + static const bool value = true; +}; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/null_index.hpp b/extern/boost/boost/interprocess/indexes/null_index.hpp new file mode 100644 index 00000000000..ed4797f8f76 --- /dev/null +++ b/extern/boost/boost/interprocess/indexes/null_index.hpp @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NULL_INDEX_HPP +#define BOOST_INTERPROCESS_NULL_INDEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +//!\file +//!Describes a null index adaptor, so that if we don't want to construct +//!named objects, we can use this null index type to save resources. + +namespace boost { +namespace interprocess { + +//!Null index type +//!used to save compilation time when +//!named indexes are not needed. +template +class null_index +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef int * iterator; + typedef const int * const_iterator; + + //!begin() is equal + //!to end() + const_iterator begin() const + { return const_iterator(0); } + + //!begin() is equal + //!to end() + iterator begin() + { return iterator(0); } + + //!begin() is equal + //!to end() + const_iterator end() const + { return const_iterator(0); } + + //!begin() is equal + //!to end() + iterator end() + { return iterator(0); } + + //!Empty constructor + null_index(segment_manager_base *){} +}; + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP diff --git a/extern/boost/boost/interprocess/ipc/message_queue.hpp b/extern/boost/boost/interprocess/ipc/message_queue.hpp new file mode 100644 index 00000000000..bb70adaece6 --- /dev/null +++ b/extern/boost/boost/interprocess/ipc/message_queue.hpp @@ -0,0 +1,1131 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MESSAGE_QUEUE_HPP +#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //make_unsigned, alignment_of +#include +#include +#include +#include //std::lower_bound +#include //std::size_t +#include //memcpy + + +//!\file +//!Describes an inter-process message queue. This class allows sending +//!messages between processes and allows blocking, non-blocking and timed +//!sending and receiving. + +namespace boost{ namespace interprocess{ + +namespace ipcdetail +{ + template + class msg_queue_initialization_func_t; + +} + +//Blocking modes +enum mqblock_types { blocking, timed, non_blocking }; + +//!A class that allows sending messages +//!between processes. +template +class message_queue_t +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + message_queue_t(); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef VoidPointer void_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type char_ptr; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::container::dtl::make_unsigned::type size_type; + + //!Creates a process shared message queue with name "name". For this message queue, + //!the maximum number of messages will be "max_num_msg" and the maximum message size + //!will be "max_msg_size". Throws on error and if the queue was previously created. + message_queue_t(create_only_t, + const char *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens or creates a process shared message queue with name "name". + //!If the queue is created, the maximum number of messages will be "max_num_msg" + //!and the maximum message size will be "max_msg_size". If queue was previously + //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters + //!are ignored. Throws on error. + message_queue_t(open_or_create_t, + const char *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens a previously created process shared message queue with name "name". + //!If the queue was not previously created or there are no free resources, + //!throws an error. + message_queue_t(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a process shared message queue with name "name". For this message queue, + //!the maximum number of messages will be "max_num_msg" and the maximum message size + //!will be "max_msg_size". Throws on error and if the queue was previously created. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(create_only_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens or creates a process shared message queue with name "name". + //!If the queue is created, the maximum number of messages will be "max_num_msg" + //!and the maximum message size will be "max_msg_size". If queue was previously + //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters + //!are ignored. Throws on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(open_or_create_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens a previously created process shared message queue with name "name". + //!If the queue was not previously created or there are no free resources, + //!throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a process shared message queue in anonymous memory. For this message queue, + //!the maximum number of messages will be "max_num_msg" and the maximum message size + //!will be "max_msg_size". Throws on error. + message_queue_t(size_type max_num_msg, + size_type max_msg_size); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. All opened message queues are still + //!valid after destruction. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the message queue from the system + //!use remove(). + ~message_queue_t(); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!message queue with priority "priority". If the message queue is full + //!the sender is blocked. Throws interprocess_error on error. + void send (const void *buffer, size_type buffer_size, + unsigned int priority); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" through the + //!message queue with priority "priority". If the message queue is full + //!the sender is not blocked and returns false, otherwise returns true. + //!Throws interprocess_error on error. + bool try_send (const void *buffer, size_type buffer_size, + unsigned int priority); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!message queue with priority "priority". If the message queue is full + //!the sender retries until time "abs_time" is reached. Returns true if + //!the message has been successfully sent. Returns false if timeout is reached. + //!Throws interprocess_error on error. + template + bool timed_send (const void *buffer, size_type buffer_size, + unsigned int priority, const TimePoint& abs_time); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver is blocked. Throws interprocess_error on error. + void receive (void *buffer, size_type buffer_size, + size_type &recvd_size,unsigned int &priority); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver is not blocked and returns false, otherwise returns true. + //!Throws interprocess_error on error. + bool try_receive (void *buffer, size_type buffer_size, + size_type &recvd_size,unsigned int &priority); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver retries until time "abs_time" is reached. Returns true if + //!the message has been successfully sent. Returns false if timeout is reached. + //!Throws interprocess_error on error. + template + bool timed_receive (void *buffer, size_type buffer_size, + size_type &recvd_size,unsigned int &priority, + const TimePoint &abs_time); + + //!Returns the maximum number of messages allowed by the queue. The message + //!queue must be opened or created previously. Otherwise, returns 0. + //!Never throws + size_type get_max_msg() const; + + //!Returns the maximum size of message allowed by the queue. The message + //!queue must be opened or created previously. Otherwise, returns 0. + //!Never throws + size_type get_max_msg_size() const; + + //!Returns the number of messages currently stored. + //!Never throws + size_type get_num_msg() const; + + //!Removes the message queue 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) + + //!Removes the message queue 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 + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + friend class ipcdetail::msg_queue_initialization_func_t; + + template + bool do_receive(void *buffer, size_type buffer_size, + size_type &recvd_size, unsigned int &priority, + const TimePoint &abs_time); + + template + bool do_send(const void *buffer, size_type buffer_size, + unsigned int priority, const TimePoint &abs_time); + + //!Returns the needed memory size for the shared message queue. + //!Never throws + static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg); + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + + template + static bool do_cond_wait(ipcdetail::bool_, interprocess_condition &cond, Lock &lock, const TimePoint &abs_time) + { return cond.timed_wait(lock, abs_time); } + + template + static bool do_cond_wait(ipcdetail::bool_, interprocess_condition &cond, Lock &lock, const TimePoint &) + { cond.wait(lock); return true; } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace ipcdetail { + +//!This header is the prefix of each message in the queue +template +class msg_hdr_t +{ + typedef VoidPointer void_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type char_ptr; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::container::dtl::make_unsigned::type size_type; + + public: + size_type len; // Message length + unsigned int priority;// Message priority + //!Returns the data buffer associated with this this message + void * data(){ return this+1; } // +}; + +//!This functor is the predicate to order stored messages by priority +template +class priority_functor +{ + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer >::type msg_hdr_ptr_t; + + public: + bool operator()(const msg_hdr_ptr_t &msg1, + const msg_hdr_ptr_t &msg2) const + { return msg1->priority < msg2->priority; } +}; + +//!This header is placed in the beginning of the shared memory and contains +//!the data to control the queue. This class initializes the shared memory +//!in the following way: in ascending memory address with proper alignment +//!fillings: +//! +//!-> mq_hdr_t: +//! Main control block that controls the rest of the elements +//! +//!-> offset_ptr index [max_num_msg] +//! An array of pointers with size "max_num_msg" called index. Each pointer +//! points to a preallocated message. Elements of this array are +//! reordered in runtime in the following way: +//! +//! IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined: +//! +//! When the current number of messages is "cur_num_msg", the array +//! is treated like a circular buffer. Starting from position "cur_first_msg" +//! "cur_num_msg" in a circular way, pointers point to inserted messages and the rest +//! point to free messages. Those "cur_num_msg" pointers are +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be +//! used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg] +//! and the first free message ready to be used in a "send" operation is +//! [cur_first_msg] if circular buffer is extended from front, +//! [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise. +//! +//! This transforms the index in a circular buffer with an embedded free +//! message queue. +//! +//! ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined): +//! +//! When the current number of messages is "cur_num_msg", the first +//! "cur_num_msg" pointers point to inserted messages and the rest +//! point to free messages. The first "cur_num_msg" pointers are +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be +//! used in a "receive" is pointed by index [cur_num_msg-1] and the first free +//! message ready to be used in a "send" operation is index [cur_num_msg]. +//! +//! This transforms the index in a fixed size priority queue with an embedded free +//! message queue. +//! +//!-> struct message_t +//! { +//! msg_hdr_t header; +//! char[max_msg_size] data; +//! } messages [max_num_msg]; +//! +//! An array of buffers of preallocated messages, each one prefixed with the +//! msg_hdr_t structure. Each of this message is pointed by one pointer of +//! the index structure. +template +class mq_hdr_t + : public ipcdetail::priority_functor +{ + typedef VoidPointer void_pointer; + typedef msg_hdr_t msg_header; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type msg_hdr_ptr_t; + typedef typename boost::intrusive::pointer_traits + ::difference_type difference_type; + typedef typename boost::container:: + dtl::make_unsigned::type size_type; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type msg_hdr_ptr_ptr_t; + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + + public: + //!Constructor. This object must be constructed in the beginning of the + //!shared memory of the size returned by the function "get_mem_size". + //!This constructor initializes the needed resources and creates + //!the internal structures like the priority index. This can throw. + mq_hdr_t(size_type max_num_msg, size_type max_msg_size) + : m_max_num_msg(max_num_msg), + m_max_msg_size(max_msg_size), + m_cur_num_msg(0) + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + ,m_cur_first_msg(0u) + ,m_blocked_senders(0u) + ,m_blocked_receivers(0u) + #endif + { this->initialize_memory(); } + + //!Returns true if the message queue is full + bool is_full() const + { return m_cur_num_msg == m_max_num_msg; } + + //!Returns true if the message queue is empty + bool is_empty() const + { return !m_cur_num_msg; } + + //!Frees the top priority message and saves it in the free message list + void free_top_msg() + { --m_cur_num_msg; } + + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + + typedef msg_hdr_ptr_t *iterator; + + size_type end_pos() const + { + const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg; + return space_until_bufend > m_cur_num_msg + ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend; + } + + //!Returns the inserted message with top priority + msg_header &top_msg() + { + size_type pos = this->end_pos(); + return *mp_index[difference_type(pos ? --pos : m_max_num_msg - 1)]; + } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[difference_type(m_cur_first_msg)]; } + + iterator inserted_ptr_begin() const + { return &mp_index[difference_type(m_cur_first_msg)]; } + + iterator inserted_ptr_end() const + { return &mp_index[difference_type(this->end_pos())]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) + { + iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end()); + if(end < begin){ + iterator idx_end = &mp_index[difference_type(m_max_num_msg)]; + iterator ret = std::lower_bound(begin, idx_end, value, func); + if(idx_end == ret){ + iterator idx_beg = &mp_index[0]; + ret = std::lower_bound(idx_beg, end, value, func); + //sanity check, these cases should not call lower_bound (optimized out) + BOOST_ASSERT(ret != end); + BOOST_ASSERT(ret != begin); + return ret; + } + else{ + return ret; + } + } + else{ + return std::lower_bound(begin, end, value, func); + } + } + + msg_header & insert_at(iterator where) + { + iterator it_inserted_ptr_end = this->inserted_ptr_end(); + iterator it_inserted_ptr_beg = this->inserted_ptr_begin(); + if(where == it_inserted_ptr_beg){ + //unsigned integer guarantees underflow + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return *mp_index[difference_type(m_cur_first_msg)]; + } + else if(where == it_inserted_ptr_end){ + ++m_cur_num_msg; + return **it_inserted_ptr_end; + } + else{ + size_type pos = size_type(where - &mp_index[0]); + size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg); + //Check if it's more efficient to move back or move front + if(circ_pos < m_cur_num_msg/2){ + //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos + //indicates two step insertion + if(!pos){ + pos = m_max_num_msg; + where = &mp_index[difference_type(m_max_num_msg-1u)]; + } + else{ + --where; + } + const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos; + const size_type first_segment_beg = unique_segment ? m_cur_first_msg : 1u; + const size_type first_segment_end = pos; + const size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg; + const size_type second_segment_end = m_max_num_msg; + const msg_hdr_ptr_t backup = *(&mp_index[0] + (unique_segment ? first_segment_beg : second_segment_beg) - 1); + + //First segment + if(!unique_segment){ + std::copy( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_beg - 1); + mp_index[difference_type(m_max_num_msg-1u)] = mp_index[0]; + } + std::copy( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_beg - 1); + *where = backup; + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return **where; + } + else{ + //The queue can't be full so end_pos < m_cur_first_msg + //indicates two step insertion + const size_type pos_end = this->end_pos(); + const bool unique_segment = pos < pos_end; + const size_type first_segment_beg = pos; + const size_type first_segment_end = unique_segment ? pos_end : m_max_num_msg-1; + const size_type second_segment_beg = 0u; + const size_type second_segment_end = unique_segment ? 0u : pos_end; + const msg_hdr_ptr_t backup = *it_inserted_ptr_end; + + //First segment + if(!unique_segment){ + std::copy_backward( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_end + 1u); + mp_index[0] = mp_index[difference_type(m_max_num_msg-1u)]; + } + std::copy_backward( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_end + 1u); + *where = backup; + ++m_cur_num_msg; + return **where; + } + } + } + + #else //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + + typedef msg_hdr_ptr_t *iterator; + + //!Returns the inserted message with top priority + msg_header &top_msg() + { return *mp_index[difference_type(m_cur_num_msg-1u)]; } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[0]; } + + iterator inserted_ptr_begin() const + { return &mp_index[0]; } + + iterator inserted_ptr_end() const + { return &mp_index[difference_type(m_cur_num_msg)]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) + { return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); } + + msg_header & insert_at(iterator pos) + { + const msg_hdr_ptr_t backup = *inserted_ptr_end(); + std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1); + *pos = backup; + ++m_cur_num_msg; + return **pos; + } + + #endif //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + + //!Inserts the first free message in the priority queue + msg_header & queue_free_msg(unsigned int priority) + { + //Get priority queue's range + iterator it (inserted_ptr_begin()), it_end(inserted_ptr_end()); + //Optimize for non-priority usage + if(m_cur_num_msg && priority > this->bottom_msg().priority){ + //Check for higher priority than all stored messages + if(priority > this->top_msg().priority){ + it = it_end; + } + else{ + //Since we don't now which free message we will pick + //build a dummy header for searches + msg_header dummy_hdr; + dummy_hdr.priority = priority; + + //Get free msg + msg_hdr_ptr_t dummy_ptr(&dummy_hdr); + + //Check where the free message should be placed + it = this->lower_bound(dummy_ptr, static_cast&>(*this)); + } + } + //Insert the free message in the correct position + return this->insert_at(it); + } + + //!Returns the number of bytes needed to construct a message queue with + //!"max_num_size" maximum number of messages and "max_msg_size" maximum + //!message size. Never throws. + static size_type get_mem_size + (size_type max_msg_size, size_type max_num_msg) + { + const size_type + msg_hdr_align = ::boost::container::dtl::alignment_of::value, + index_align = ::boost::container::dtl::alignment_of::value, + r_hdr_size = ipcdetail::ct_rounded_size::value, + r_index_size = ipcdetail::get_rounded_size(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), + r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header); + return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + + open_create_impl_t::ManagedOpenOrCreateUserOffset; + } + + //!Initializes the memory structures to preallocate messages and constructs the + //!message index. Never throws. + void initialize_memory() + { + const size_type + msg_hdr_align = ::boost::container::dtl::alignment_of::value, + index_align = ::boost::container::dtl::alignment_of::value, + r_hdr_size = ipcdetail::ct_rounded_size::value, + r_index_size = ipcdetail::get_rounded_size(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), + r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header); + + //Pointer to the index + msg_hdr_ptr_t *index = move_detail::force_ptr + (reinterpret_cast(this)+r_hdr_size); + + //Pointer to the first message header + msg_header *msg_hdr = move_detail::force_ptr + (reinterpret_cast(this)+r_hdr_size+r_index_size); + + //Initialize the pointer to the index + mp_index = index; + + //Initialize the index so each slot points to a preallocated message + for(size_type i = 0; i < m_max_num_msg; ++i){ + index[i] = msg_hdr; + msg_hdr = move_detail::force_ptr + (reinterpret_cast(msg_hdr)+r_max_msg_size); + } + } + + public: + //Pointer to the index + msg_hdr_ptr_ptr_t mp_index; + //Maximum number of messages of the queue + const size_type m_max_num_msg; + //Maximum size of messages of the queue + const size_type m_max_msg_size; + //Current number of messages + size_type m_cur_num_msg; + //Mutex to protect data structures + interprocess_mutex m_mutex; + //Condition block receivers when there are no messages + interprocess_condition m_cond_recv; + //Condition block senders when the queue is full + interprocess_condition m_cond_send; + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + //Current start offset in the circular index + size_type m_cur_first_msg; + size_type m_blocked_senders; + size_type m_blocked_receivers; + #endif +}; + + +//!This is the atomic functor to be executed when creating or opening +//!shared memory. Never throws +template +class msg_queue_initialization_func_t +{ + public: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type char_ptr; + typedef typename boost::intrusive::pointer_traits:: + difference_type difference_type; + typedef typename boost::container::dtl:: + make_unsigned::type size_type; + + msg_queue_initialization_func_t(size_type maxmsg = 0, + size_type maxmsgsize = 0) + : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {} + + bool operator()(void *address, size_type, bool created) + { + char *mptr; + + if(created){ + mptr = reinterpret_cast(address); + //Construct the message queue header at the beginning + BOOST_TRY{ + new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END + } + return true; + } + + std::size_t get_min_size() const + { + return mq_hdr_t::get_mem_size(m_maxmsgsize, m_maxmsg) + - message_queue_t::open_create_impl_t::ManagedOpenOrCreateUserOffset; + } + + const size_type m_maxmsg; + const size_type m_maxmsgsize; +}; + +} //namespace ipcdetail { + +template +inline message_queue_t::~message_queue_t() +{} + +template +inline typename message_queue_t::size_type message_queue_t::get_mem_size + (size_type max_msg_size, size_type max_num_msg) +{ return ipcdetail::mq_hdr_t::get_mem_size(max_msg_size, max_num_msg); } + +template +inline message_queue_t::message_queue_t(create_only_t, + const char *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(create_only, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_or_create_t, + const char *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(open_or_create, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_only_t, const char *name) + //Create shared memory and execute functor atomically + : m_shmem(open_only, + name, + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t ()) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline message_queue_t::message_queue_t(create_only_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(create_only, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_or_create_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(open_or_create, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_only_t, const wchar_t *name) + //Create shared memory and execute functor atomically + : m_shmem(open_only, + name, + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t ()) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline message_queue_t::message_queue_t(size_type max_num_msg, + size_type max_msg_size) + : m_shmem(get_mem_size(max_msg_size, max_num_msg), + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size)) +{} + +template +inline void message_queue_t::send + (const void *buffer, size_type buffer_size, unsigned int priority) +{ this->do_send(buffer, buffer_size, priority, 0); } + +template +inline bool message_queue_t::try_send + (const void *buffer, size_type buffer_size, unsigned int priority) +{ return this->do_send(buffer, buffer_size, priority, 0); } + +template +template +inline bool message_queue_t::timed_send + (const void *buffer, size_type buffer_size + ,unsigned int priority, const TimePoint &abs_time) +{ + if(ipcdetail::is_pos_infinity(abs_time)){ + this->send(buffer, buffer_size, priority); + return true; + } + return this->do_send(buffer, buffer_size, priority, abs_time); +} + +template +template +inline bool message_queue_t::do_send( + const void *buffer, size_type buffer_size, + unsigned int priority, const TimePoint &abs_time) +{ + ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); + //Check if buffer is smaller than maximum allowed + if (buffer_size > p_hdr->m_max_msg_size) { + throw interprocess_exception(size_error); + } + + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + bool notify_blocked_receivers = false; + #endif + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + { + //If the queue is full execute blocking logic + if (p_hdr->is_full()) { + BOOST_TRY{ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + ++p_hdr->m_blocked_senders; + #endif + switch(Block){ + case non_blocking : + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + return false; + break; + + case blocking : + do{ + (void)do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_send, lock, abs_time); + } + while (p_hdr->is_full()); + break; + + case timed : + do{ + if(!do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_send, lock, abs_time)) { + if(p_hdr->is_full()){ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + return false; + } + break; + } + } + while (p_hdr->is_full()); + break; + default: + break; + } + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + } + BOOST_CATCH(...){ + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + --p_hdr->m_blocked_senders; + #endif + BOOST_RETHROW; + } BOOST_CATCH_END + } + + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + notify_blocked_receivers = 0 != p_hdr->m_blocked_receivers; + #endif + //Insert the first free message in the priority queue + ipcdetail::msg_hdr_t &free_msg_hdr = p_hdr->queue_free_msg(priority); + + //Sanity check, free msgs are always cleaned when received + BOOST_ASSERT(free_msg_hdr.priority == 0); + BOOST_ASSERT(free_msg_hdr.len == 0); + + //Copy control data to the free message + free_msg_hdr.priority = priority; + free_msg_hdr.len = buffer_size; + + //Copy user buffer to the message + std::memcpy(free_msg_hdr.data(), buffer, buffer_size); + } // Lock end + + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this message changes the queue empty state, notify it to receivers + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + if (notify_blocked_receivers){ + p_hdr->m_cond_recv.notify_one(); + } + #else + p_hdr->m_cond_recv.notify_one(); + #endif + + return true; +} + +template +inline void message_queue_t::receive(void *buffer, size_type buffer_size, + size_type &recvd_size, unsigned int &priority) +{ this->do_receive(buffer, buffer_size, recvd_size, priority, 0); } + +template +inline bool + message_queue_t::try_receive(void *buffer, size_type buffer_size, + size_type &recvd_size, unsigned int &priority) +{ return this->do_receive(buffer, buffer_size, recvd_size, priority, 0); } + +template +template +inline bool + message_queue_t::timed_receive(void *buffer, size_type buffer_size, + size_type &recvd_size, unsigned int &priority, + const TimePoint &abs_time) +{ + if(ipcdetail::is_pos_infinity(abs_time)){ + this->receive(buffer, buffer_size, recvd_size, priority); + return true; + } + return this->do_receive(buffer, buffer_size, recvd_size, priority, abs_time); +} + +template +template +inline bool + message_queue_t::do_receive( + void *buffer, size_type buffer_size, + size_type &recvd_size, unsigned int &priority, + const TimePoint &abs_time) +{ + ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); + //Check if buffer is big enough for any message + if (buffer_size < p_hdr->m_max_msg_size) { + throw interprocess_exception(size_error); + } + + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + bool notify_blocked_senders = false; + #endif + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + { + //If there are no messages execute blocking logic + if (p_hdr->is_empty()) { + BOOST_TRY{ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + ++p_hdr->m_blocked_receivers; + #endif + switch(Block){ + case non_blocking : + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + return false; + break; + + case blocking : + do{ + (void)do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_recv, lock, abs_time); + } + while (p_hdr->is_empty()); + break; + + case timed : + do{ + if(!do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_recv, lock, abs_time)) { + if(p_hdr->is_empty()){ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + return false; + } + break; + } + } + while (p_hdr->is_empty()); + break; + + //Paranoia check + default: + break; + } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + } + BOOST_CATCH(...){ + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + --p_hdr->m_blocked_receivers; + #endif + BOOST_RETHROW; + } BOOST_CATCH_END + } + + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + notify_blocked_senders = 0 != p_hdr->m_blocked_senders; + #endif + + //There is at least one message ready to pick, get the top one + ipcdetail::msg_hdr_t &top_msg = p_hdr->top_msg(); + + //Get data from the message + recvd_size = top_msg.len; + priority = top_msg.priority; + + //Some cleanup to ease debugging + top_msg.len = 0; + top_msg.priority = 0; + + //Copy data to receiver's bufers + std::memcpy(buffer, top_msg.data(), recvd_size); + + //Free top message and put it in the free message list + p_hdr->free_top_msg(); + } //Lock end + + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this reception changes the queue full state, notify senders + #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + if (notify_blocked_senders){ + p_hdr->m_cond_send.notify_one(); + } + #else + p_hdr->m_cond_send.notify_one(); + #endif + + return true; +} + +template +inline typename message_queue_t::size_type message_queue_t::get_max_msg() const +{ + ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); + return p_hdr ? p_hdr->m_max_num_msg : 0; } + +template +inline typename message_queue_t::size_type message_queue_t::get_max_msg_size() const +{ + ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); + return p_hdr ? p_hdr->m_max_msg_size : 0; +} + +template +inline typename message_queue_t::size_type message_queue_t::get_num_msg() const +{ + ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); + if(p_hdr){ + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + return p_hdr->m_cur_num_msg; + } + + return 0; +} + +template +inline bool message_queue_t::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline bool message_queue_t::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + +#else + +//!Typedef for a default message queue +//!to be used between processes +typedef message_queue_t > message_queue; + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +}} //namespace boost{ namespace interprocess{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP diff --git a/extern/boost/boost/interprocess/managed_external_buffer.hpp b/extern/boost/boost/interprocess/managed_external_buffer.hpp new file mode 100644 index 00000000000..0cf2d4d2b49 --- /dev/null +++ b/extern/boost/boost/interprocess/managed_external_buffer.hpp @@ -0,0 +1,143 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_EXTERNAL_BUFFER_HPP +#define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include +#include + +//!\file +//!Describes a named user memory allocation user class. + +namespace boost { +namespace interprocess { + +//!A basic user memory named object creation class. Inherits all +//!basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_external_buffer + : public ipcdetail::basic_managed_memory_impl +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef ipcdetail::basic_managed_memory_impl + base_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef typename base_t::size_type size_type; + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_external_buffer() BOOST_NOEXCEPT + {} + + //!Creates and places the segment manager. This can throw + //!The external memory supplied by the user shall be aligned to the maximum value between + //!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built + //!inside that memory. + basic_managed_external_buffer + (create_only_t, void *addr, size_type size) + { + //Check if alignment is correct + BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u))))); + if(!base_t::create_impl(addr, size)){ + throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor"); + } + } + + //!Creates and places the segment manager. This can throw + //!The external memory supplied by the user shall be aligned to the maximum value between + //!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built + //!inside that memory. + basic_managed_external_buffer + (open_only_t, void *addr, size_type size) + { + //Check if alignment is correct + BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u))))); + if(!base_t::open_impl(addr, size)){ + throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor"); + } + } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + basic_managed_external_buffer(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT + { + this->swap(moved); + } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + basic_managed_external_buffer &operator=(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT + { + basic_managed_external_buffer tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + void grow(size_type extra_bytes) + { base_t::grow(extra_bytes); } + + //!Swaps the ownership of the managed heap memories managed by *this and other. + //!Never throws. + void swap(basic_managed_external_buffer &other) BOOST_NOEXCEPT + { base_t::swap(other); } +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_external_buffer +//!of narrow characters +typedef basic_managed_external_buffer + + ,iset_index> +managed_external_buffer; + +//!Typedef for a default basic_managed_external_buffer +//!of wide characters +typedef basic_managed_external_buffer + + ,iset_index> +wmanaged_external_buffer; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP + diff --git a/extern/boost/boost/interprocess/managed_heap_memory.hpp b/extern/boost/boost/interprocess/managed_heap_memory.hpp new file mode 100644 index 00000000000..52b917acba9 --- /dev/null +++ b/extern/boost/boost/interprocess/managed_heap_memory.hpp @@ -0,0 +1,172 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_HEAP_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include +#include + +//!\file +//!Describes a named heap memory allocation user class. + +namespace boost { +namespace interprocess { + +//!A basic heap memory named object creation class. Initializes the +//!heap memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_heap_memory + : public ipcdetail::basic_managed_memory_impl +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + typedef ipcdetail::basic_managed_memory_impl + base_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + typedef typename base_t::size_type size_type; + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_heap_memory() BOOST_NOEXCEPT + {} + + //!Destructor. Liberates the heap memory holding the managed data. + //!Never throws. + ~basic_managed_heap_memory() + { this->priv_close(); } + + //!Creates heap memory and initializes the segment manager. + //!This can throw. + basic_managed_heap_memory(size_type size) + : m_heapmem(size, char(0)) + { + if(!base_t::create_impl(&m_heapmem[0], size)){ + this->priv_close(); + throw interprocess_exception("Could not initialize heap in basic_managed_heap_memory constructor"); + } + } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + basic_managed_heap_memory(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT + { this->swap(moved); } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + basic_managed_heap_memory &operator=(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT + { + basic_managed_heap_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Tries to resize internal heap memory so that + //!we have room for more objects. + //!WARNING: If memory is reallocated, all the objects will + //!be binary-copied to the new buffer. To be able to use + //!this function, all pointers constructed in this buffer + //!must be offset pointers. Otherwise, the result is undefined. + //!Returns true if the growth has been successful, so you will + //!have some extra bytes to allocate new objects. If returns + //!false, the heap allocation has failed. + bool grow(size_type extra_bytes) + { + //If memory is reallocated, data will + //be automatically copied + BOOST_TRY{ + m_heapmem.resize(m_heapmem.size()+extra_bytes); + } + BOOST_CATCH(...){ + return false; + } + BOOST_CATCH_END + + //Grow always works + base_t::close_impl(); + base_t::open_impl(&m_heapmem[0], m_heapmem.size()); + base_t::grow(extra_bytes); + return true; + } + + //!Swaps the ownership of the managed heap memories managed by *this and other. + //!Never throws. + void swap(basic_managed_heap_memory &other) BOOST_NOEXCEPT + { + base_t::swap(other); + m_heapmem.swap(other.m_heapmem); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + //!Frees resources. Never throws. + void priv_close() + { + base_t::destroy_impl(); + std::vector().swap(m_heapmem); + } + + std::vector m_heapmem; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_heap_memory +//!of narrow characters +typedef basic_managed_heap_memory + + ,iset_index> +managed_heap_memory; + +//!Typedef for a default basic_managed_heap_memory +//!of wide characters +typedef basic_managed_heap_memory + + ,iset_index> +wmanaged_heap_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP + diff --git a/extern/boost/boost/interprocess/managed_mapped_file.hpp b/extern/boost/boost/interprocess/managed_mapped_file.hpp new file mode 100644 index 00000000000..daca6adaa0d --- /dev/null +++ b/extern/boost/boost/interprocess/managed_mapped_file.hpp @@ -0,0 +1,370 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_MAPPED_FILE_HPP +#define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct mfile_open_or_create +{ + static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of + < segment_manager + < CharType + , AllocationAlgorithm + , IndexType> + >::value; + static const std::size_t final_segment_manager_alignment + = segment_manager_alignment > AllocationAlgorithm::Alignment + ? segment_manager_alignment : AllocationAlgorithm::Alignment; + + typedef ipcdetail::managed_open_or_create_impl + < file_wrapper + , final_segment_manager_alignment + , true + , false> type; +}; + +} //namespace ipcdetail { + +//!A basic mapped file named object creation class. Initializes the +//!mapped file. Inherits all basic functionality from +//!basic_managed_memory_impl +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_mapped_file + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + : public ipcdetail::basic_managed_memory_impl + < CharType, AllocationAlgorithm, IndexType + , ipcdetail::mfile_open_or_create + ::type::ManagedOpenOrCreateUserOffset> + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + public: + typedef ipcdetail::basic_managed_memory_impl + + ::type::ManagedOpenOrCreateUserOffset> base_t; + typedef ipcdetail::file_wrapper device_type; + + private: + + typedef ipcdetail::create_open_func create_open_func_t; + + basic_managed_mapped_file *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_mapped_file) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + + //!Unsigned integral type enough to represent + //!the size of a basic_managed_mapped_file. + typedef typename BOOST_INTERPROCESS_IMPDEF(base_t::size_type) size_type; + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + basic_managed_mapped_file() BOOST_NOEXCEPT + {} + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + basic_managed_mapped_file(create_only_t, const char *name, + size_type size, const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates mapped file and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_mapped_file (open_or_create_t, + const char *name, size_type size, + const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created mapped file and its segment manager. + //!This can throw. + basic_managed_mapped_file (open_only_t, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_mapped_file (open_copy_on_write_t, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_mapped_file (open_read_only_t, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file(create_only_t, const wchar_t *name, + size_type size, const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates mapped file and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created mapped file and its segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_only_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in copy_on_write mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_copy_on_write_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in read-only mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_read_only_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT + { + this->swap(moved); + } + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_mapped_file &operator=(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT + { + basic_managed_mapped_file tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_mapped_file() + {} + + //!Swaps the ownership of the managed mapped memories managed by *this and other. + //!Never throws. + void swap(basic_managed_mapped_file &other) BOOST_NOEXCEPT + { + base_t::swap(other); + m_mfile.swap(other.m_mfile); + } + + //!Flushes cached data to file. + //!Never throws + bool flush() + { return m_mfile.flush(); } + + //!Tries to resize mapped file so that we have room for + //!more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool grow(const char *filename, size_type extra_bytes) + { + return base_t::template grow + (filename, extra_bytes); + } + + //!Tries to resize mapped file to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool shrink_to_fit(const char *filename) + { + return base_t::template shrink_to_fit + (filename); + } + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to resize mapped file so that we have room for + //!more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool grow(const wchar_t *filename, size_type extra_bytes) + { + return base_t::template grow + (filename, extra_bytes); + } + + //!Tries to resize mapped file to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool shrink_to_fit(const wchar_t *filename) + { + return base_t::template shrink_to_fit + (filename); + } + + #endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(m_mfile.get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + private: + typename ipcdetail::mfile_open_or_create + ::type m_mfile; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_mapped_file +//!of narrow characters +typedef basic_managed_mapped_file + + ,iset_index> +managed_mapped_file; + +//!Typedef for a default basic_managed_mapped_file +//!of wide characters +typedef basic_managed_mapped_file + + ,iset_index> +wmanaged_mapped_file; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP diff --git a/extern/boost/boost/interprocess/managed_shared_memory.hpp b/extern/boost/boost/interprocess/managed_shared_memory.hpp new file mode 100644 index 00000000000..4e77c2a01e0 --- /dev/null +++ b/extern/boost/boost/interprocess/managed_shared_memory.hpp @@ -0,0 +1,388 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include + +namespace boost { +namespace interprocess { + +namespace ipcdetail { + +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct shmem_open_or_create +{ + static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of + < segment_manager + < CharType + , AllocationAlgorithm + , IndexType> + >::value; + static const std::size_t final_segment_manager_alignment + = segment_manager_alignment > AllocationAlgorithm::Alignment + ? segment_manager_alignment : AllocationAlgorithm::Alignment; + + typedef ipcdetail::managed_open_or_create_impl + < shared_memory_object + , final_segment_manager_alignment + , true + , false> type; +}; + +} //namespace ipcdetail { + +//!A basic shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_shared_memory + : public ipcdetail::basic_managed_memory_impl + < CharType, AllocationAlgorithm, IndexType + , ipcdetail::shmem_open_or_create::type::ManagedOpenOrCreateUserOffset> + , private ipcdetail::shmem_open_or_create::type +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef typename ipcdetail::shmem_open_or_create + < CharType + , AllocationAlgorithm + , IndexType>::type base2_t; + typedef ipcdetail::basic_managed_memory_impl + base_t; + + typedef ipcdetail::create_open_func create_open_func_t; + + basic_managed_shared_memory *get_this_pointer() + { return this; } + + public: + typedef shared_memory_object device_type; + typedef typename base_t::size_type size_type; + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_shared_memory() + {} + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_shared_memory() + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_shared_memory(create_only_t, const char *name, + size_type size, const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_shared_memory (open_or_create_t, + const char *name, size_type size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!in copy_on_write mode. + //!This can throw. + basic_managed_shared_memory (open_copy_on_write_t, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + basic_managed_shared_memory (open_read_only_t, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_shared_memory (open_only_t, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory(create_only_t, const wchar_t *name, + size_type size, const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!in copy_on_write mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_copy_on_write_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_read_only_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_only_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved) + { + basic_managed_shared_memory tmp; + this->swap(moved); + tmp.swap(moved); + } + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_shared_memory &operator=(BOOST_RV_REF(basic_managed_shared_memory) moved) + { + basic_managed_shared_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps the ownership of the managed shared memories managed by *this and other. + //!Never throws. + void swap(basic_managed_shared_memory &other) + { + base_t::swap(other); + base2_t::swap(other); + } + + //!Tries to resize the managed shared memory object so that we have + //!room for more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool grow(const char *shmname, size_type extra_bytes) + { + return base_t::template grow + (shmname, extra_bytes); + } + + //!Tries to resize the managed shared memory to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool shrink_to_fit(const char *shmname) + { + return base_t::template shrink_to_fit + (shmname); + } + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to resize the managed shared memory object so that we have + //!room for more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool grow(const wchar_t *shmname, size_type extra_bytes) + { + return base_t::template grow + (shmname, extra_bytes); + } + + //!Tries to resize the managed shared memory to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool shrink_to_fit(const wchar_t *shmname) + { + return base_t::template shrink_to_fit + (shmname); + } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(base2_t::get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters +typedef basic_managed_shared_memory + + ,iset_index> +managed_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of wide characters +typedef basic_managed_shared_memory + + ,iset_index> +wmanaged_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters to be placed in a fixed address +typedef basic_managed_shared_memory + + ,iset_index> +fixed_managed_shared_memory; + +//!Typedef for a default basic_managed_shared_memory +//!of narrow characters to be placed in a fixed address +typedef basic_managed_shared_memory + + ,iset_index> +wfixed_managed_shared_memory; + + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP + diff --git a/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp b/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp new file mode 100644 index 00000000000..07997b52d61 --- /dev/null +++ b/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp @@ -0,0 +1,288 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MANAGED_WINDOWS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include +#include + +namespace boost { +namespace interprocess { + +namespace ipcdetail { + +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct wshmem_open_or_create +{ + static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of + < segment_manager + < CharType + , AllocationAlgorithm + , IndexType> + >::value; + static const std::size_t final_segment_manager_alignment + = segment_manager_alignment > AllocationAlgorithm::Alignment + ? segment_manager_alignment : AllocationAlgorithm::Alignment; + + typedef ipcdetail::managed_open_or_create_impl + < windows_shared_memory + , final_segment_manager_alignment + , false + , false> type; +}; + + +} //namespace ipcdetail { + +//!A basic managed windows shared memory creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl +//!Unlike basic_managed_shared_memory, it has +//!no kernel persistence and the shared memory is destroyed +//!when all processes destroy all their windows_shared_memory +//!objects and mapped regions for the same shared memory +//!or the processes end/crash. +//! +//!Warning: basic_managed_windows_shared_memory and +//!basic_managed_shared_memory can't communicate between them. +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_windows_shared_memory + : public ipcdetail::basic_managed_memory_impl + < CharType, AllocationAlgorithm, IndexType + , ipcdetail::wshmem_open_or_create + ::type::ManagedOpenOrCreateUserOffset> +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef ipcdetail::basic_managed_memory_impl + < CharType, AllocationAlgorithm, IndexType + , ipcdetail::wshmem_open_or_create + ::type::ManagedOpenOrCreateUserOffset> base_t; + typedef ipcdetail::create_open_func create_open_func_t; + + basic_managed_windows_shared_memory *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_windows_shared_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + typedef typename base_t::size_type size_type; + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_windows_shared_memory() BOOST_NOEXCEPT + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (create_only_t, const char *name, + size_type size, const void *addr = 0, const permissions &perm = permissions()) + : m_wshm(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_windows_shared_memory + (open_or_create_t, + const char *name, size_type size, + const void *addr = 0, + const permissions &perm = permissions()) + : m_wshm(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (open_only_t, const char* name, const void *addr = 0) + : m_wshm(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_copy_on_write_t, const char* name, const void *addr = 0) + : m_wshm(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_read_only_t, const char* name, const void *addr = 0) + : base_t() + , m_wshm(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_windows_shared_memory + (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, + const permissions &perm = permissions()) + : m_wshm(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (open_only_t, const wchar_t* name, const void *addr = 0) + : m_wshm(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_copy_on_write_t, const wchar_t* name, const void *addr = 0) + : m_wshm(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_read_only_t, const wchar_t* name, const void *addr = 0) + : base_t() + , m_wshm(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_windows_shared_memory + (BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT + { this->swap(moved); } + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_windows_shared_memory &operator=(BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT + { + basic_managed_windows_shared_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. All mapped regions are still valid after + //!destruction. When all mapped regions and basic_managed_windows_shared_memory + //!objects referring the shared memory are destroyed, the + //!operating system will destroy the shared memory. + ~basic_managed_windows_shared_memory() + {} + + //!Swaps the ownership of the managed mapped memories managed by *this and other. + //!Never throws. + void swap(basic_managed_windows_shared_memory &other) BOOST_NOEXCEPT + { + base_t::swap(other); + m_wshm.swap(other.m_wshm); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(m_wshm.get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + private: + typename ipcdetail::wshmem_open_or_create + ::type m_wshm; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_windows_shared_memory +//!of narrow characters +typedef basic_managed_windows_shared_memory + + ,iset_index> +managed_windows_shared_memory; + +//!Typedef for a default basic_managed_windows_shared_memory +//!of wide characters +typedef basic_managed_windows_shared_memory + + ,iset_index> +wmanaged_windows_shared_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp b/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp new file mode 100644 index 00000000000..3c51294e79b --- /dev/null +++ b/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp @@ -0,0 +1,251 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-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_MANAGED_XSI_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include +//These includes needed to fulfill default template parameters of +//predeclarations in interprocess_fwd.hpp +#include +#include +#include + +namespace boost { + +namespace interprocess { + +namespace ipcdetail { + +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct xsishmem_open_or_create +{ + static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of + < segment_manager + < CharType + , AllocationAlgorithm + , IndexType> + >::value; + static const std::size_t final_segment_manager_alignment + = segment_manager_alignment > AllocationAlgorithm::Alignment + ? segment_manager_alignment : AllocationAlgorithm::Alignment; + + typedef ipcdetail::managed_open_or_create_impl + < xsi_shared_memory_file_wrapper + , final_segment_manager_alignment + , false + , true> type; +}; + + +} //namespace ipcdetail { + +//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_xsi_shared_memory + : public ipcdetail::basic_managed_memory_impl + + ::type::ManagedOpenOrCreateUserOffset> + , private ipcdetail::xsishmem_open_or_create + ::type +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + public: + typedef xsi_shared_memory_file_wrapper device_type; + + public: + typedef typename ipcdetail::xsishmem_open_or_create + ::type base2_t; + typedef ipcdetail::basic_managed_memory_impl + base_t; + + typedef ipcdetail::create_open_func create_open_func_t; + + basic_managed_xsi_shared_memory *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: //functions + typedef typename base_t::size_type size_type; + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_xsi_shared_memory() + {} + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_xsi_shared_memory() BOOST_NOEXCEPT + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_xsi_shared_memory(create_only_t, const xsi_key &key, + std::size_t size, const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(create_only, key, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_xsi_shared_memory (open_or_create_t, + const xsi_key &key, std::size_t size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, key, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key, + const void *addr = 0) + : base_t() + , base2_t(open_only, key, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_xsi_shared_memory (open_only_t, const xsi_key &key, + const void *addr = 0) + : base_t() + , base2_t(open_only, key, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_xsi_shared_memory(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT + { + basic_managed_xsi_shared_memory tmp; + this->swap(moved); + tmp.swap(moved); + } + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_xsi_shared_memory &operator=(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT + { + basic_managed_xsi_shared_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps the ownership of the managed shared memories managed by *this and other. + //!Never throws. + void swap(basic_managed_xsi_shared_memory &other) BOOST_NOEXCEPT + { + base_t::swap(other); + base2_t::swap(other); + } + + //!Erases a XSI shared memory object identified by shmid + //!from the system. + //!Returns false on error. Never throws + static bool remove(int shmid) + { return device_type::remove(shmid); } + + int get_shmid() const BOOST_NOEXCEPT + { return base2_t::get_device().get_shmid(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(base2_t::get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Typedef for a default basic_managed_xsi_shared_memory +//!of narrow characters +typedef basic_managed_xsi_shared_memory + + ,iset_index> +managed_xsi_shared_memory; + +//!Typedef for a default basic_managed_xsi_shared_memory +//!of wide characters +typedef basic_managed_xsi_shared_memory + + ,iset_index> +wmanaged_xsi_shared_memory; + +#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP + diff --git a/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp new file mode 100644 index 00000000000..c036ce94903 --- /dev/null +++ b/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -0,0 +1,599 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MEM_ALGO_COMMON_HPP +#define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess +#include +#include +// interprocess/detail +#include +#include +#include +#include +// container/detail +#include +#include +// move +#include +// move/detail +#include +// other boost +#include +#include + +//!\file +//!Implements common operations for memory algorithms. + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +class basic_multiallocation_chain + : public boost::container::dtl:: + basic_multiallocation_chain +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) + typedef boost::container::dtl:: + basic_multiallocation_chain base_t; + public: + + basic_multiallocation_chain() + : base_t() + {} + + basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) + : base_t(::boost::move(static_cast(other))) + {} + + basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) + { + this->base_t::operator=(::boost::move(static_cast(other))); + return *this; + } + + void *pop_front() + { + return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front()); + } +}; + + +//!This class implements several allocation functions shared by different algorithms +//!(aligned allocation, multiple allocation...). +template +class memory_algorithm_common +{ + public: + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef typename MemoryAlgorithm::block_ctrl block_ctrl; + typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; + typedef memory_algorithm_common this_type; + typedef typename MemoryAlgorithm::size_type size_type; + + static const size_type Alignment = MemoryAlgorithm::Alignment; + static const size_type MinBlockUnits = MemoryAlgorithm::MinBlockUnits; + static const size_type AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes; + static const size_type AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits; + static const size_type BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes; + static const size_type BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits; + static const size_type UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk; + + static void assert_alignment(const void *ptr) + { assert_alignment((std::size_t)ptr); } + + static void assert_alignment(size_type uint_ptr) + { + (void)uint_ptr; + BOOST_ASSERT(uint_ptr % Alignment == 0); + } + + static bool check_alignment(const void *ptr) + { return (((std::size_t)ptr) % Alignment == 0); } + + static size_type ceil_units(size_type size) + { return get_rounded_size(size, Alignment)/Alignment; } + + static size_type floor_units(size_type size) + { return size/Alignment; } + + static size_type multiple_of_units(size_type size) + { return get_rounded_size(size, Alignment); } + + static void allocate_many + (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { + return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain); + } + + static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) + { + return this_type::priv_deallocate_many(memory_algo, chain); + } + + static bool calculate_lcm_and_needs_backwards_lcmed + (size_type backwards_multiple, size_type received_size, size_type size_to_achieve, + size_type &lcm_out, size_type &needs_backwards_lcmed_out) + { + // Now calculate lcm_val + size_type max = backwards_multiple; + size_type min = Alignment; + size_type needs_backwards; + size_type needs_backwards_lcmed; + size_type lcm_val; + size_type current_forward; + //Swap if necessary + if(max < min){ + size_type tmp = min; + min = max; + max = tmp; + } + //Check if it's power of two + if((backwards_multiple & (backwards_multiple-1)) == 0){ + if(0 != (size_to_achieve & ((backwards_multiple-1)))){ + return false; + } + + lcm_val = max; + //If we want to use minbytes data to get a buffer between maxbytes + //and minbytes if maxbytes can't be achieved, calculate the + //biggest of all possibilities + current_forward = get_truncated_size_po2(received_size, backwards_multiple); + needs_backwards = size_to_achieve - current_forward; + BOOST_ASSERT((needs_backwards % backwards_multiple) == 0); + needs_backwards_lcmed = get_rounded_size_po2(needs_backwards, lcm_val); + lcm_out = lcm_val; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of alignment + else if((backwards_multiple & (Alignment - 1u)) == 0){ + lcm_val = backwards_multiple; + current_forward = get_truncated_size(received_size, backwards_multiple); + //No need to round needs_backwards because backwards_multiple == lcm_val + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + BOOST_ASSERT((needs_backwards_lcmed & (Alignment - 1u)) == 0); + lcm_out = lcm_val; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of the half of the alignmment + else if((backwards_multiple & ((Alignment/2u) - 1u)) == 0){ + lcm_val = backwards_multiple*2u; + current_forward = get_truncated_size(received_size, backwards_multiple); + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + if(0 != (needs_backwards_lcmed & (Alignment-1))) + //while(0 != (needs_backwards_lcmed & (Alignment-1))) + needs_backwards_lcmed += backwards_multiple; + BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0); + lcm_out = lcm_val; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of the quarter of the alignmment + else if((backwards_multiple & ((Alignment/4u) - 1u)) == 0){ + size_type remainder; + lcm_val = backwards_multiple*4u; + current_forward = get_truncated_size(received_size, backwards_multiple); + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + //while(0 != (needs_backwards_lcmed & (Alignment-1))) + //needs_backwards_lcmed += backwards_multiple; + if(0 != (remainder = ((needs_backwards_lcmed & (Alignment-1))>>(Alignment/8u)))){ + if(backwards_multiple & Alignment/2u){ + needs_backwards_lcmed += (remainder)*backwards_multiple; + } + else{ + needs_backwards_lcmed += (4-remainder)*backwards_multiple; + } + } + BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0); + lcm_out = lcm_val; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + else{ + lcm_val = lcm(max, min); + } + //If we want to use minbytes data to get a buffer between maxbytes + //and minbytes if maxbytes can't be achieved, calculate the + //biggest of all possibilities + current_forward = get_truncated_size(received_size, backwards_multiple); + needs_backwards = size_to_achieve - current_forward; + BOOST_ASSERT((needs_backwards % backwards_multiple) == 0); + needs_backwards_lcmed = get_rounded_size(needs_backwards, lcm_val); + lcm_out = lcm_val; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + + static void allocate_many + ( MemoryAlgorithm *memory_algo + , const size_type *elem_sizes + , size_type n_elements + , size_type sizeof_element + , multiallocation_chain &chain) + { + this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain); + } + + static void* allocate_aligned + (MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment) + { + + //Ensure power of 2 + if ((alignment & (alignment - size_type(1u))) != 0){ + //Alignment is not power of two + BOOST_ASSERT((alignment & (alignment - size_type(1u))) == 0); + return 0; + } + + size_type real_size = nbytes; + if(alignment <= Alignment){ + void *ignore_reuse = 0; + return memory_algo->priv_allocate + (boost::interprocess::allocate_new, nbytes, real_size, ignore_reuse); + } + + if(nbytes > UsableByPreviousChunk) + nbytes -= UsableByPreviousChunk; + + //We can find a aligned portion if we allocate a block that has alignment + //nbytes + alignment bytes or more. + size_type minimum_allocation = max_value + (nbytes + alignment, size_type(MinBlockUnits*Alignment)); + //Since we will split that block, we must request a bit more memory + //if the alignment is near the beginning of the buffer, because otherwise, + //there is no space for a new block before the alignment. + // + // ____ Aligned here + // | + // ----------------------------------------------------- + // | MBU | + // ----------------------------------------------------- + size_type request = + minimum_allocation + (2*MinBlockUnits*Alignment - AllocatedCtrlBytes + //prevsize - UsableByPreviousChunk + ); + + //Now allocate the buffer + real_size = request; + void *ignore_reuse = 0; + void *buffer = memory_algo->priv_allocate(boost::interprocess::allocate_new, request, real_size, ignore_reuse); + if(!buffer){ + return 0; + } + else if ((((std::size_t)(buffer)) % alignment) == 0){ + //If we are lucky and the buffer is aligned, just split it and + //return the high part + block_ctrl *first = memory_algo->priv_get_block(buffer); + size_type old_size = first->m_size; + const size_type first_min_units = + 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 = move_detail::force_ptr + (reinterpret_cast(first) + Alignment*first_min_units); + 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); + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second)); + } + return buffer; + } + + //Buffer not aligned, find the aligned part. + // + // ____ Aligned here + // | + // ----------------------------------------------------- + // | MBU +more | ACB | + // ----------------------------------------------------- + char *pos = reinterpret_cast + (reinterpret_cast(static_cast(buffer) + + //This is the minimum size of (2) + (MinBlockUnits*Alignment - AllocatedCtrlBytes) + + //This is the next MBU for the aligned memory + AllocatedCtrlBytes + + //This is the alignment trick + alignment - 1) & -alignment); + + //Now obtain the address of the blocks + block_ctrl *first = memory_algo->priv_get_block(buffer); + block_ctrl *second = memory_algo->priv_get_block(pos); + BOOST_ASSERT(pos <= (reinterpret_cast(first) + first->m_size*Alignment)); + BOOST_ASSERT(first->m_size >= 2*MinBlockUnits); + BOOST_ASSERT((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <= + (reinterpret_cast(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(size_type(reinterpret_cast(second) - reinterpret_cast(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 + // + // __"second" block + // | __Aligned here + // | | __"third" block + // -----------|-----|-----|------------------------------ + // | MBU +more | ACB | (3) | BCU | + // ----------------------------------------------------- + //This size will be the minimum size to be able to create a + //new block in the end. + const size_type second_min_units = max_value(size_type(MinBlockUnits), + ceil_units(nbytes) + AllocatedCtrlUnits ); + + //Check if we can create a new block (of size MinBlockUnits) in the end of the segment + if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){ + //Now obtain the address of the end block + block_ctrl *third = new (reinterpret_cast(second) + Alignment*second_min_units)block_ctrl; + 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) & block_ctrl::size_mask; + BOOST_ASSERT(second->m_size >= MinBlockUnits); + memory_algo->priv_mark_new_allocated_block(second); + } + + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(first)); + return memory_algo->priv_get_user_buffer(second); + } + + static bool try_shrink + (MemoryAlgorithm *memory_algo, void *ptr + ,const size_type max_size, size_type &received_size) + { + size_type const preferred_size = received_size; + (void)memory_algo; + //Obtain the real block + block_ctrl *block = memory_algo->priv_get_block(ptr); + size_type old_block_units = (size_type)block->m_size; + + //The block must be marked as allocated + BOOST_ASSERT(memory_algo->priv_is_allocated_block(block)); + + //Check if alignment and block size are right + assert_alignment(ptr); + + //Put this to a safe value + received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + + //Now translate it to Alignment units + const size_type max_user_units = floor_units(max_size - UsableByPreviousChunk); + const size_type preferred_user_units = ceil_units(preferred_size - UsableByPreviousChunk); + + //Check if rounded max and preferred are possible correct + if(max_user_units < preferred_user_units) + return false; + + //Check if the block is smaller than the requested minimum + size_type old_user_units = old_block_units - AllocatedCtrlUnits; + + if(old_user_units < preferred_user_units) + return false; + + //If the block is smaller than the requested minimum + if(old_user_units == preferred_user_units) + return true; + + size_type shrunk_user_units = + ((BlockCtrlUnits - AllocatedCtrlUnits) >= preferred_user_units) + ? (BlockCtrlUnits - AllocatedCtrlUnits) + : preferred_user_units; + + //Some parameter checks + if(max_user_units < shrunk_user_units) + return false; + + //We must be able to create at least a new empty block + if((old_user_units - shrunk_user_units) < BlockCtrlUnits ){ + return false; + } + + //Update new size + received_size = shrunk_user_units*Alignment + UsableByPreviousChunk; + return true; + } + + static bool shrink + (MemoryAlgorithm *memory_algo, void *ptr + ,const size_type max_size, size_type &received_size) + { + size_type const preferred_size = received_size; + //Obtain the real block + block_ctrl *block = memory_algo->priv_get_block(ptr); + size_type old_block_units = (size_type)block->m_size; + + if(!try_shrink(memory_algo, ptr, max_size, received_size)){ + return false; + } + + //Check if the old size was just the shrunk size (no splitting) + if((old_block_units - AllocatedCtrlUnits) == ceil_units(preferred_size - UsableByPreviousChunk)) + return true; + + //Now we can just rewrite the size of the old buffer + 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 = move_detail::force_ptr + (reinterpret_cast(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) & 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); + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(new_block)); + return true; + } + + private: + static void priv_allocate_many + ( MemoryAlgorithm *memory_algo + , const size_type *elem_sizes + , size_type n_elements + , size_type sizeof_element + , multiallocation_chain &chain) + { + //Note: sizeof_element == 0 indicates that we want to + //allocate n_elements of the same size "*elem_sizes" + + //Calculate the total size of all requests + size_type total_request_units = 0; + size_type elem_units = 0; + const size_type ptr_size_units = memory_algo->priv_get_total_units(sizeof(void_pointer)); + if(!sizeof_element){ + elem_units = memory_algo->priv_get_total_units(*elem_sizes); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + total_request_units = n_elements*elem_units; + } + else{ + for(size_type i = 0; i < n_elements; ++i){ + if(multiplication_overflows(elem_sizes[i], sizeof_element)){ + total_request_units = 0; + break; + } + elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + if(sum_overflows(total_request_units, elem_units)){ + total_request_units = 0; + break; + } + total_request_units += elem_units; + } + } + + if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){ + size_type low_idx = 0; + while(low_idx < n_elements){ + size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + size_type min_allocation = (!sizeof_element) + ? elem_units + : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + + size_type received_size = total_bytes; + void *ignore_reuse = 0; + void *ret = memory_algo->priv_allocate + (boost::interprocess::allocate_new, min_allocation, received_size, ignore_reuse); + if(!ret){ + break; + } + + block_ctrl *block = memory_algo->priv_get_block(ret); + size_type received_units = (size_type)block->m_size; + char *block_address = reinterpret_cast(block); + + size_type total_used_units = 0; + while(total_used_units < received_units){ + if(sizeof_element){ + elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + } + if(total_used_units + elem_units > received_units) + break; + total_request_units -= elem_units; + //This is the position where the new block must be created + block_ctrl *new_block = move_detail::force_ptr(block_address); + assert_alignment(new_block); + + //The last block should take all the remaining space + if((low_idx + 1) == n_elements || + (total_used_units + elem_units + + ((!sizeof_element) + ? elem_units + : 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) & block_ctrl::size_mask; + memory_algo->priv_mark_new_allocated_block(new_block); + + //If the remaining units are bigger than needed and we can + //split it obtaining a new free memory block do it. + if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ + size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + size_type shrunk_received = shrunk_request; + bool shrink_ok = shrink + (memory_algo + ,memory_algo->priv_get_user_buffer(new_block) + ,shrunk_request + ,shrunk_received); + (void)shrink_ok; + //Shrink must always succeed with passed parameters + BOOST_ASSERT(shrink_ok); + //Some sanity checks + BOOST_ASSERT(shrunk_request == shrunk_received); + BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); + //"new_block->m_size" must have been reduced to elem_units by "shrink" + BOOST_ASSERT(new_block->m_size == elem_units); + //Now update the total received units with the reduction + received_units = elem_units + total_used_units; + } + } + else{ + new_block->m_size = elem_units & block_ctrl::size_mask; + memory_algo->priv_mark_new_allocated_block(new_block); + } + + block_address += new_block->m_size*Alignment; + total_used_units += (size_type)new_block->m_size; + //Check we have enough room to overwrite the intrusive pointer + BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); + void_pointer p = ::new(memory_algo->priv_get_user_buffer(new_block), boost_container_new_t())void_pointer(0); + chain.push_back(p); + ++low_idx; + } + //Sanity check + BOOST_ASSERT(total_used_units == received_units); + } + + if(low_idx != n_elements){ + priv_deallocate_many(memory_algo, chain); + } + } + } + + static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) + { + while(!chain.empty()){ + memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front())); + } + } +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP diff --git a/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp new file mode 100644 index 00000000000..2c909acfe96 --- /dev/null +++ b/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -0,0 +1,1107 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP +#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //make_unsigned, alignment_of +#include +#include +#include +#include + +//!\file +//!Describes sequential fit algorithm used to allocate objects in shared memory. +//!This class is intended as a base class for single segment and multi-segment +//!implementations. + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//!This class implements the simple sequential fit algorithm with a simply +//!linked list of free buffers. +//!This class is intended as a base class for single segment and multi-segment +//!implementations. +template +class simple_seq_fit_impl +{ + //Non-copyable + simple_seq_fit_impl(); + simple_seq_fit_impl(const simple_seq_fit_impl &); + simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type char_ptr; + + public: + + //!Shared interprocess_mutex family used for the rest of the Interprocess framework + typedef MutexFamily mutex_family; + //!Pointer type to be used with the rest of the Interprocess framework + typedef VoidPointer void_pointer; + typedef boost::container::dtl:: + basic_multiallocation_chain multiallocation_chain; + + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::container::dtl::make_unsigned::type size_type; + + + private: + class block_ctrl; + friend class block_ctrl; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type block_ctrl_ptr; + + //!Block control structure + class block_ctrl + { + public: + static const size_type size_mask = size_type(-1); + //!Offset pointer to the next block. + block_ctrl_ptr m_next; + //!This block's memory size (including block_ctrl + //!header) in BasicSize units + size_type m_size; + + size_type get_user_bytes() const + { return this->m_size*Alignment - BlockCtrlBytes; } + + size_type get_total_bytes() const + { return this->m_size*Alignment; } + }; + + //!Shared interprocess_mutex to protect memory allocate/deallocate + typedef typename MutexFamily::mutex_type interprocess_mutex; + + //!This struct includes needed data and derives from + //!interprocess_mutex to allow EBO when using null interprocess_mutex + struct header_t : public interprocess_mutex + { + //!Pointer to the first free block + block_ctrl m_root; + //!Allocated bytes for internal checking + size_type m_allocated; + //!The size of the memory segment + size_type m_size; + //!The extra size required by the segment + size_type m_extra_hdr_bytes; + } m_header; + + friend class ipcdetail::memory_algorithm_common; + + typedef ipcdetail::memory_algorithm_common algo_impl_t; + + public: + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) + //!offset that the allocator should not use at all. + simple_seq_fit_impl (size_type size, size_type extra_hdr_bytes); + + //!Destructor + ~simple_seq_fit_impl(); + + //!Obtains the minimum size needed by the algorithm + static size_type get_min_size (size_type extra_hdr_bytes); + + //Functions for single segment management + + //!Allocates bytes, returns 0 if there is not more memory + void* allocate (size_type nbytes); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Multiple element allocation, same size + void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); + } + + //!Multiple element allocation, different size + void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); + } + + //!Multiple element deallocation + void deallocate_many(multiallocation_chain &chain); + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Deallocates previously allocated bytes + void deallocate (void *addr); + + //!Returns the size of the memory segment + size_type get_size() const; + + //!Returns the number of free bytes of the memory segment + size_type get_free_memory() const; + + //!Increases managed memory in extra_size bytes more + void grow(size_type extra_size); + + //!Decreases managed memory as much as possible + void shrink_to_fit(); + + //!Returns true if all allocated memory has been deallocated + bool all_memory_deallocated(); + + //!Makes an internal sanity check and returns true if success + bool check_sanity(); + + //!Initializes to zero all the memory that's not in use. + //!This function is normally used for security reasons. + void zero_free_memory(); + + template + T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse); + + void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object = 1); + + //!Returns the size of the buffer previously allocated pointed by ptr + size_type size(const void *ptr) const; + + //!Allocates aligned bytes, returns 0 if there is not more memory. + //!Alignment must be power of 2 + void* allocate_aligned (size_type nbytes, size_type alignment); + + private: + + //!Obtains the pointer returned to the user from the block control + static void *priv_get_user_buffer(const block_ctrl *block); + + //!Obtains the block control structure of the user buffer + static block_ctrl *priv_get_block(const void *ptr); + + //!Real allocation algorithm with min allocation option + void * priv_allocate(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size, void *&reuse_ptr); + + void * priv_allocation_command(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size + ,void *&reuse_ptr + ,size_type sizeof_object); + + //!Returns the number of total units that a user buffer + //!of "userbytes" bytes really occupies (including header) + static size_type priv_get_total_units(size_type userbytes); + + static size_type priv_first_block_offset(const void *this_ptr, size_type extra_hdr_bytes); + size_type priv_block_end_offset() const; + + //!Returns next block if it's free. + //!Returns 0 if next block is not free. + block_ctrl *priv_next_block_if_free(block_ctrl *ptr); + + //!Check if this block is free (not allocated) + bool priv_is_allocated_block(block_ctrl *ptr); + + //!Returns previous block's if it's free. + //!Returns 0 if previous block is not free. + std::pair priv_prev_block_if_free(block_ctrl *ptr); + + //!Real expand function implementation + bool priv_expand(void *ptr, size_type min_size, size_type &prefer_in_recvd_out_size); + + //!Real expand to both sides implementation + void* priv_expand_both_sides(boost::interprocess::allocation_type command + ,size_type min_size, size_type &prefer_in_recvd_out_size + ,void *reuse_ptr + ,bool only_preferred_backwards); + + //!Real private aligned allocation function + //void* priv_allocate_aligned (size_type nbytes, size_type alignment); + + //!Checks if block has enough memory and splits/unlinks the block + //!returning the address to the users + void* priv_check_and_allocate(size_type units + ,block_ctrl* prev + ,block_ctrl* block + ,size_type &received_size); + //!Real deallocation algorithm + void priv_deallocate(void *addr); + + //!Makes a new memory portion available for allocation + void priv_add_segment(void *addr, size_type size); + + void priv_mark_new_allocated_block(block_ctrl *block); + + public: + static const size_type Alignment = ::boost::container::dtl::alignment_of + < ::boost::container::dtl::max_align_t>::value; + private: + static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size::value; + static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; + static const size_type MinBlockUnits = BlockCtrlUnits; + static const size_type MinBlockSize = MinBlockUnits*Alignment; + static const size_type AllocatedCtrlBytes = BlockCtrlBytes; + static const size_type AllocatedCtrlUnits = BlockCtrlUnits; + static const size_type UsableByPreviousChunk = 0; + + public: + static const size_type PayloadPerAllocation = BlockCtrlBytes; +}; + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl + ::priv_first_block_offset(const void *this_ptr, size_type extra_hdr_bytes) +{ + //First align "this" pointer + size_type uint_this = (std::size_t)this_ptr; + size_type uint_aligned_this = uint_this/Alignment*Alignment; + size_type this_disalignment = (uint_this - uint_aligned_this); + size_type block1_off = + ipcdetail::get_rounded_size(sizeof(simple_seq_fit_impl) + extra_hdr_bytes + this_disalignment, Alignment) + - this_disalignment; + algo_impl_t::assert_alignment(this_disalignment + block1_off); + return block1_off; +} + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl + ::priv_block_end_offset() const +{ + //First align "this" pointer + size_type uint_this = (std::size_t)this; + size_type uint_aligned_this = uint_this/Alignment*Alignment; + size_type this_disalignment = (uint_this - uint_aligned_this); + size_type old_end = + ipcdetail::get_truncated_size(m_header.m_size + this_disalignment, Alignment) + - this_disalignment; + algo_impl_t::assert_alignment(old_end + this_disalignment); + return old_end; +} + +template +inline simple_seq_fit_impl:: + simple_seq_fit_impl(size_type segment_size, size_type extra_hdr_bytes) +{ + //Initialize sizes and counters + m_header.m_allocated = 0; + m_header.m_size = segment_size; + m_header.m_extra_hdr_bytes = extra_hdr_bytes; + + //Initialize pointers + size_type block1_off = priv_first_block_offset(this, extra_hdr_bytes); + + m_header.m_root.m_next = move_detail::force_ptr + ((reinterpret_cast(this) + block1_off)); + algo_impl_t::assert_alignment(ipcdetail::to_raw_pointer(m_header.m_root.m_next)); + m_header.m_root.m_next->m_size = (segment_size - block1_off)/Alignment; + m_header.m_root.m_next->m_next = &m_header.m_root; +} + +template +inline simple_seq_fit_impl::~simple_seq_fit_impl() +{ + //There is a memory leak! +// BOOST_ASSERT(m_header.m_allocated == 0); +// BOOST_ASSERT(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); +} + +template +inline void simple_seq_fit_impl::grow(size_type extra_size) +{ + //Old highest address block's end offset + size_type old_end = this->priv_block_end_offset(); + + //Update managed buffer's size + m_header.m_size += extra_size; + + //We need at least MinBlockSize blocks to create a new block + if((m_header.m_size - old_end) < MinBlockSize){ + return; + } + + //We'll create a new free block with extra_size bytes + + block_ctrl *new_block = move_detail::force_ptr + (reinterpret_cast(this) + old_end); + + algo_impl_t::assert_alignment(new_block); + new_block->m_next = 0; + new_block->m_size = (m_header.m_size - old_end)/Alignment; + m_header.m_allocated += new_block->m_size*Alignment; + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +void simple_seq_fit_impl::shrink_to_fit() +{ + //Get the root and the first memory block + block_ctrl *prev = &m_header.m_root; + block_ctrl *last = &m_header.m_root; + block_ctrl *block = ipcdetail::to_raw_pointer(last->m_next); + block_ctrl *root = &m_header.m_root; + + //No free block? + if(block == root) return; + + //Iterate through the free block list + while(block != root){ + prev = last; + last = block; + block = ipcdetail::to_raw_pointer(block->m_next); + } + + char *last_free_end_address = reinterpret_cast(last) + last->m_size*Alignment; + if(last_free_end_address != (reinterpret_cast(this) + priv_block_end_offset())){ + //there is an allocated block in the end of this block + //so no shrinking is possible + return; + } + + //Check if have only 1 big free block + void *unique_block = 0; + if(!m_header.m_allocated){ + BOOST_ASSERT(prev == root); + size_type ignore_recvd = 0; + void *ignore_reuse = 0; + unique_block = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); + if(!unique_block) + return; + last = ipcdetail::to_raw_pointer(m_header.m_root.m_next); + BOOST_ASSERT(last_free_end_address == (reinterpret_cast(last) + last->m_size*Alignment)); + } + size_type last_units = last->m_size; + + size_type received_size; + void *addr = priv_check_and_allocate(last_units, prev, last, received_size); + (void)addr; + BOOST_ASSERT(addr); + BOOST_ASSERT(received_size == last_units*Alignment - AllocatedCtrlBytes); + + //Shrink it + m_header.m_size /= Alignment; + m_header.m_size -= last->m_size; + m_header.m_size *= Alignment; + m_header.m_allocated -= last->m_size*Alignment; + + if(unique_block) + priv_deallocate(unique_block); +} + +template +inline void simple_seq_fit_impl:: + priv_mark_new_allocated_block(block_ctrl *new_block) +{ + new_block->m_next = 0; +} + +template +inline +typename simple_seq_fit_impl::block_ctrl * + simple_seq_fit_impl::priv_get_block(const void *ptr) +{ + return const_cast(move_detail::force_ptr + (reinterpret_cast(ptr) - AllocatedCtrlBytes)); +} + +template +inline +void *simple_seq_fit_impl:: + priv_get_user_buffer(const typename simple_seq_fit_impl::block_ctrl *block) +{ + return const_cast(reinterpret_cast(block) + AllocatedCtrlBytes); +} + +template +inline void simple_seq_fit_impl::priv_add_segment(void *addr, size_type segment_size) +{ + algo_impl_t::assert_alignment(addr); + //Check size + BOOST_ASSERT(!(segment_size < MinBlockSize)); + if(segment_size < MinBlockSize) + return; + //Construct big block using the new segment + block_ctrl *new_block = static_cast(addr); + new_block->m_size = segment_size/Alignment; + new_block->m_next = 0; + //Simulate this block was previously allocated + m_header.m_allocated += new_block->m_size*Alignment; + //Return block and insert it in the free block list + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl::get_size() const + { return m_header.m_size; } + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl::get_free_memory() const +{ + return m_header.m_size - m_header.m_allocated - + algo_impl_t::multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes); +} + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl:: + get_min_size (size_type extra_hdr_bytes) +{ + return ipcdetail::get_rounded_size((size_type)sizeof(simple_seq_fit_impl),Alignment) + + ipcdetail::get_rounded_size(extra_hdr_bytes,Alignment) + + MinBlockSize; +} + +template +inline bool simple_seq_fit_impl:: + all_memory_deallocated() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return m_header.m_allocated == 0 && + ipcdetail::to_raw_pointer(m_header.m_root.m_next->m_next) == &m_header.m_root; +} + +template +inline void simple_seq_fit_impl::zero_free_memory() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = ipcdetail::to_raw_pointer(m_header.m_root.m_next); + + //Iterate through all free portions + do{ + //Just clear user the memory part reserved for the user + std::memset( priv_get_user_buffer(block) + , 0 + , block->get_user_bytes()); + block = ipcdetail::to_raw_pointer(block->m_next); + } + while(block != &m_header.m_root); +} + +template +inline bool simple_seq_fit_impl:: + check_sanity() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = ipcdetail::to_raw_pointer(m_header.m_root.m_next); + + size_type free_memory = 0; + + //Iterate through all blocks obtaining their size + while(block != &m_header.m_root){ + algo_impl_t::assert_alignment(block); + if(!algo_impl_t::check_alignment(block)) + return false; + //Free blocks's next must be always valid + block_ctrl *next = ipcdetail::to_raw_pointer(block->m_next); + if(!next){ + return false; + } + free_memory += block->m_size*Alignment; + block = next; + } + + //Check allocated bytes are less than size + if(m_header.m_allocated > m_header.m_size){ + return false; + } + + //Check free bytes are less than size + if(free_memory > m_header.m_size){ + return false; + } + return true; +} + +template +inline void* simple_seq_fit_impl:: + allocate(size_type nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + size_type ignore_recvd = nbytes; + void *ignore_reuse = 0; + return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); +} + +template +inline void* simple_seq_fit_impl:: + allocate_aligned(size_type nbytes, size_type alignment) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t:: + allocate_aligned(this, nbytes, alignment); +} + +template +template +inline T* simple_seq_fit_impl:: + allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse_ptr) +{ + void *raw_reuse = reuse_ptr; + void * const ret = priv_allocation_command + (command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); + BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::dtl::alignment_of::value)); + reuse_ptr = static_cast(raw_reuse); + return static_cast(ret); +} + +template +inline void* simple_seq_fit_impl:: + raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) +{ + size_type const preferred_objects = prefer_in_recvd_out_size; + if(!sizeof_object){ + return reuse_ptr = 0, static_cast(0); + } + if(command & boost::interprocess::try_shrink_in_place){ + if(!reuse_ptr) return static_cast(0); + prefer_in_recvd_out_size = preferred_objects*sizeof_object; + bool success = algo_impl_t::try_shrink + ( this, reuse_ptr, limit_objects*sizeof_object, prefer_in_recvd_out_size); + prefer_in_recvd_out_size /= sizeof_object; + return success ? reuse_ptr : 0; + } + else{ + return priv_allocation_command + (command, limit_objects, prefer_in_recvd_out_size, reuse_ptr, sizeof_object); + } +} + +template +inline void* simple_seq_fit_impl:: + priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + command &= ~boost::interprocess::expand_bwd; + if(!command){ + return reuse_ptr = 0, static_cast(0); + } + + size_type max_count = m_header.m_size/sizeof_object; + if(limit_size > max_count || preferred_size > max_count){ + return reuse_ptr = 0, static_cast(0); + } + size_type l_size = limit_size*sizeof_object; + size_type r_size = preferred_size*sizeof_object; + void *ret = 0; + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + ret = priv_allocate(command, l_size, r_size, reuse_ptr); + } + prefer_in_recvd_out_size = r_size/sizeof_object; + return ret; +} + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl::size(const void *ptr) const +{ + //We need no synchronization since this block is not going + //to be modified + //Obtain the real size of the block + const block_ctrl *block = static_cast(priv_get_block(ptr)); + return block->get_user_bytes(); +} + +template +void* simple_seq_fit_impl:: + priv_expand_both_sides(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size + ,void *reuse_ptr + ,bool only_preferred_backwards) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + typedef std::pair prev_block_t; + block_ctrl *reuse = priv_get_block(reuse_ptr); + prefer_in_recvd_out_size = 0; + + if(this->size(reuse_ptr) > min_size){ + prefer_in_recvd_out_size = this->size(reuse_ptr); + return reuse_ptr; + } + + if(command & boost::interprocess::expand_fwd){ + if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) + return reuse_ptr; + } + else{ + prefer_in_recvd_out_size = this->size(reuse_ptr); + } + if(command & boost::interprocess::expand_bwd){ + size_type extra_forward = !prefer_in_recvd_out_size ? 0 : prefer_in_recvd_out_size + BlockCtrlBytes; + prev_block_t prev_pair = priv_prev_block_if_free(reuse); + block_ctrl *prev = prev_pair.second; + if(!prev){ + return 0; + } + + size_type needs_backwards = + ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); + + if(!only_preferred_backwards){ + max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) + ,min_value(prev->get_user_bytes(), needs_backwards)); + } + + //Check if previous block has enough size + if((prev->get_user_bytes()) >= needs_backwards){ + //Now take all next space. This will succeed + if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, prefer_in_recvd_out_size)){ + BOOST_ASSERT(0); + } + + //We need a minimum size to split the previous one + if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ + block_ctrl *new_block = move_detail::force_ptr + (reinterpret_cast(reuse) - needs_backwards - BlockCtrlBytes); + + new_block->m_next = 0; + new_block->m_size = + BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment; + prev->m_size = + (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits; + prefer_in_recvd_out_size = needs_backwards + extra_forward; + m_header.m_allocated += needs_backwards + BlockCtrlBytes; + return priv_get_user_buffer(new_block); + } + else{ + //Just merge the whole previous block + block_ctrl *prev_2_block = prev_pair.first; + //Update received size and allocation + prefer_in_recvd_out_size = extra_forward + prev->get_user_bytes(); + m_header.m_allocated += prev->get_total_bytes(); + //Now unlink it from previous block + prev_2_block->m_next = prev->m_next; + prev->m_size = reuse->m_size + prev->m_size; + prev->m_next = 0; + priv_get_user_buffer(prev); + } + } + } + return 0; +} + +template +inline void simple_seq_fit_impl:: + deallocate_many(typename simple_seq_fit_impl::multiallocation_chain &chain) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + while(!chain.empty()){ + this->priv_deallocate(to_raw_pointer(chain.pop_front())); + } +} + +template +inline typename simple_seq_fit_impl::size_type +simple_seq_fit_impl:: + priv_get_total_units(size_type userbytes) +{ + size_type s = ipcdetail::get_rounded_size(userbytes, Alignment)/Alignment; + if(!s) ++s; + return BlockCtrlUnits + s; +} + +template +void * simple_seq_fit_impl:: + priv_allocate(boost::interprocess::allocation_type command + ,size_type limit_size, size_type &prefer_in_recvd_out_size, void *&reuse_ptr) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + if(command & boost::interprocess::shrink_in_place){ + if(!reuse_ptr) return static_cast(0); + bool success = algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size); + return success ? reuse_ptr : 0; + } + prefer_in_recvd_out_size = 0; + + if(limit_size > preferred_size){ + return reuse_ptr = 0, static_cast(0); + } + + //Number of units to request (including block_ctrl header) + size_type nunits = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlUnits; + + //Get the root and the first memory block + block_ctrl *prev = &m_header.m_root; + block_ctrl *block = ipcdetail::to_raw_pointer(prev->m_next); + block_ctrl *root = &m_header.m_root; + block_ctrl *biggest_block = 0; + block_ctrl *prev_biggest_block = 0; + size_type biggest_size = 0; + + //Expand in place + if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ + void *ret = priv_expand_both_sides(command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, true); + if(ret){ + algo_impl_t::assert_alignment(ret); + return ret; + } + } + + if(command & boost::interprocess::allocate_new){ + prefer_in_recvd_out_size = 0; + while(block != root){ + //Update biggest block pointers + if(block->m_size > biggest_size){ + prev_biggest_block = prev; + biggest_size = block->m_size; + biggest_block = block; + } + algo_impl_t::assert_alignment(block); + void *addr = this->priv_check_and_allocate(nunits, prev, block, prefer_in_recvd_out_size); + if(addr){ + algo_impl_t::assert_alignment(addr); + return reuse_ptr = 0, addr; + } + //Bad luck, let's check next block + prev = block; + block = ipcdetail::to_raw_pointer(block->m_next); + } + + //Bad luck finding preferred_size, now if we have any biggest_block + //try with this block + if(biggest_block){ + size_type limit_units = ipcdetail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlUnits; + if(biggest_block->m_size < limit_units){ + return reuse_ptr = 0, static_cast(0); + } + void *ret = this->priv_check_and_allocate + (biggest_block->m_size, prev_biggest_block, biggest_block, prefer_in_recvd_out_size = biggest_block->m_size*Alignment - BlockCtrlUnits); + BOOST_ASSERT(ret != 0); + algo_impl_t::assert_alignment(ret); + return reuse_ptr = 0, ret; + } + } + //Now try to expand both sides with min size + if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ + void *ret = priv_expand_both_sides (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false); + algo_impl_t::assert_alignment(ret); + return ret; + } + return reuse_ptr = 0, static_cast(0); +} + +template inline +bool simple_seq_fit_impl::priv_is_allocated_block + (typename simple_seq_fit_impl::block_ctrl *block) +{ return block->m_next == 0; } + +template +inline typename simple_seq_fit_impl::block_ctrl * + simple_seq_fit_impl:: + priv_next_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + //Take the address where the next block should go + block_ctrl *next_block = move_detail::force_ptr + (reinterpret_cast(ptr) + ptr->m_size*Alignment); + + //Check if the adjacent block is in the managed segment + char *this_char_ptr = reinterpret_cast(this); + char *next_char_ptr = reinterpret_cast(next_block); + size_type distance = (size_type)(next_char_ptr - this_char_ptr)/Alignment; + + if(distance >= (m_header.m_size/Alignment)){ + //"next_block" does not exist so we can't expand "block" + return 0; + } + + if(!next_block->m_next) + return 0; + + return next_block; +} + +template +inline + std::pair::block_ctrl * + ,typename simple_seq_fit_impl::block_ctrl *> + simple_seq_fit_impl:: + priv_prev_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + typedef std::pair prev_pair_t; + //Take the address where the previous block should go + block_ctrl *root = &m_header.m_root; + block_ctrl *prev_2_block = root; + block_ctrl *prev_block = ipcdetail::to_raw_pointer(root->m_next); + + while((reinterpret_cast(prev_block) + prev_block->m_size*Alignment) + != reinterpret_cast(ptr) + && prev_block != root){ + prev_2_block = prev_block; + prev_block = ipcdetail::to_raw_pointer(prev_block->m_next); + } + + if(prev_block == root || !prev_block->m_next) + return prev_pair_t(static_cast(0), static_cast(0)); + + //Check if the previous block is in the managed segment + char *this_char_ptr = reinterpret_cast(this); + char *prev_char_ptr = reinterpret_cast(prev_block); + size_type distance = (size_type)(prev_char_ptr - this_char_ptr)/Alignment; + + if(distance >= (m_header.m_size/Alignment)){ + //"previous_block" does not exist so we can't expand "block" + return prev_pair_t(static_cast(0), static_cast(0)); + } + return prev_pair_t(prev_2_block, prev_block); +} + + +template +inline bool simple_seq_fit_impl:: + priv_expand (void *ptr, size_type min_size, size_type &received_size) +{ + size_type preferred_size = received_size; + //Obtain the real size of the block + block_ctrl *block = move_detail::force_ptr(priv_get_block(ptr)); + size_type old_block_size = block->m_size; + + //All used blocks' next is marked with 0 so check it + BOOST_ASSERT(block->m_next == 0); + + //Put this to a safe value + received_size = old_block_size*Alignment - BlockCtrlBytes; + + //Now translate it to Alignment units + min_size = ipcdetail::get_rounded_size(min_size, Alignment)/Alignment; + preferred_size = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment; + + //Some parameter checks + if(min_size > preferred_size) + return false; + + size_type data_size = old_block_size - BlockCtrlUnits; + + if(data_size >= min_size) + return true; + + block_ctrl *next_block = priv_next_block_if_free(block); + if(!next_block){ + return false; + } + + //Is "block" + "next_block" big enough? + size_type merged_size = old_block_size + next_block->m_size; + + //Now we can expand this block further than before + received_size = merged_size*Alignment - BlockCtrlBytes; + + if(merged_size < (min_size + BlockCtrlUnits)){ + return false; + } + + //We can fill expand. Merge both blocks, + block->m_next = next_block->m_next; + block->m_size = merged_size; + + //Find the previous free block of next_block + block_ctrl *prev = &m_header.m_root; + while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ + prev = ipcdetail::to_raw_pointer(prev->m_next); + } + + //Now insert merged block in the free list + //This allows reusing allocation logic in this function + m_header.m_allocated -= old_block_size*Alignment; + prev->m_next = block; + + //Now use check and allocate to do the allocation logic + preferred_size += BlockCtrlUnits; + size_type nunits = preferred_size < merged_size ? preferred_size : merged_size; + + //This must success since nunits is less than merged_size! + if(!this->priv_check_and_allocate (nunits, prev, block, received_size)){ + //Something very ugly is happening here. This is a bug + //or there is memory corruption + BOOST_ASSERT(0); + return false; + } + return true; +} + +template inline +void* simple_seq_fit_impl::priv_check_and_allocate + (size_type nunits + ,typename simple_seq_fit_impl::block_ctrl* prev + ,typename simple_seq_fit_impl::block_ctrl* block + ,size_type &received_size) +{ + size_type upper_nunits = nunits + BlockCtrlUnits; + bool found = false; + + if (block->m_size > upper_nunits){ + //This block is bigger than needed, split it in + //two blocks, the first's size will be "units" + //the second's size will be "block->m_size-units" + size_type total_size = block->m_size; + block->m_size = nunits; + + block_ctrl *new_block = move_detail::force_ptr + (reinterpret_cast(block) + Alignment*nunits); + new_block->m_size = total_size - nunits; + new_block->m_next = block->m_next; + prev->m_next = new_block; + found = true; + } + else if (block->m_size >= nunits){ + //This block has exactly the right size with an extra + //unusable extra bytes. + prev->m_next = block->m_next; + found = true; + } + + if(found){ + //We need block_ctrl for deallocation stuff, so + //return memory user can overwrite + m_header.m_allocated += block->m_size*Alignment; + received_size = block->get_user_bytes(); + //Mark the block as allocated + block->m_next = 0; + //Check alignment + algo_impl_t::assert_alignment(block); + return priv_get_user_buffer(block); + } + return 0; +} + +template +void simple_seq_fit_impl::deallocate(void* addr) +{ + if(!addr) return; + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return this->priv_deallocate(addr); +} + +template +void simple_seq_fit_impl::priv_deallocate(void* addr) +{ + if(!addr) return; + + //Let's get free block list. List is always sorted + //by memory address to allow block merging. + //Pointer next always points to the first + //(lower address) block + block_ctrl * prev = &m_header.m_root; + block_ctrl * pos = ipcdetail::to_raw_pointer(m_header.m_root.m_next); + block_ctrl * block = move_detail::force_ptr(priv_get_block(addr)); + + //All used blocks' next is marked with 0 so check it + BOOST_ASSERT(block->m_next == 0); + + //Check if alignment and block size are right + algo_impl_t::assert_alignment(addr); + + size_type total_size = Alignment*block->m_size; + BOOST_ASSERT(m_header.m_allocated >= total_size); + + //Update used memory count + m_header.m_allocated -= total_size; + + //Let's find the previous and the next block of the block to deallocate + //This ordering comparison must be done with original pointers + //types since their mapping to raw pointers can be different + //in each process + while((ipcdetail::to_raw_pointer(pos) != &m_header.m_root) && (block > pos)){ + prev = pos; + pos = ipcdetail::to_raw_pointer(pos->m_next); + } + + //Try to combine with upper block + char *block_char_ptr = reinterpret_cast(ipcdetail::to_raw_pointer(block)); + + if ((block_char_ptr + Alignment*block->m_size) == + reinterpret_cast(ipcdetail::to_raw_pointer(pos))){ + block->m_size += pos->m_size; + block->m_next = pos->m_next; + } + else{ + block->m_next = pos; + } + + //Try to combine with lower block + if ((reinterpret_cast(ipcdetail::to_raw_pointer(prev)) + + Alignment*prev->m_size) == + block_char_ptr){ + + + prev->m_size += block->m_size; + prev->m_next = block->m_next; + } + else{ + prev->m_next = block; + } +} + +} //namespace ipcdetail { + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + diff --git a/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp new file mode 100644 index 00000000000..d1dd9d12ff7 --- /dev/null +++ b/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -0,0 +1,1359 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MEM_ALGO_RBTREE_BEST_FIT_HPP +#define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// interprocess +#include +#include +#include +#include +#include +#include +// interprocess/detail +#include +#include +#include +#include +// container +#include +// container/detail +#include +// move/detail +#include //make_unsigned, alignment_of +#include //make_unsigned, alignment_of +// intrusive +#include +#include +// other boost +#include +#include +// std +#include +#include + +//#define BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP +//to maintain ABI compatible with the original version +//ABI had to be updated to fix compatibility issues when +//sharing shared memory between 32 adn 64 bit processes. + +//!\file +//!Describes a best-fit algorithm based in an intrusive red-black tree used to allocate +//!objects in shared memory. This class is intended as a base class for single segment +//!and multi-segment implementations. + +namespace boost { +namespace interprocess { + +//!This class implements an algorithm that stores the free nodes in a red-black tree +//!to have logarithmic search/insert times. +template +class rbtree_best_fit +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + rbtree_best_fit(); + rbtree_best_fit(const rbtree_best_fit &); + rbtree_best_fit &operator=(const rbtree_best_fit &); + + private: + struct block_ctrl; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type block_ctrl_ptr; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type char_ptr; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Shared mutex family used for the rest of the Interprocess framework + typedef MutexFamily mutex_family; + //!Pointer type to be used with the rest of the Interprocess framework + typedef VoidPointer void_pointer; + typedef ipcdetail::basic_multiallocation_chain multiallocation_chain; + + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::container::dtl::make_unsigned::type size_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + private: + + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + , bi::link_mode >::type TreeHook; + + struct SizeHolder + { + static const size_type size_mask = size_type(-1) >> 2; + //!This block's memory size (including block_ctrl + //!header) in Alignment units + size_type m_prev_size; + size_type m_size : sizeof(size_type)*CHAR_BIT - 2; + size_type m_prev_allocated : 1; + size_type m_allocated : 1; + }; + + //!Block control structure + struct block_ctrl + : public SizeHolder, public TreeHook + { + block_ctrl() + { this->m_size = 0; this->m_allocated = 0, this->m_prev_allocated = 0; } + + friend bool operator<(const block_ctrl &a, const block_ctrl &b) + { return a.m_size < b.m_size; } + friend bool operator==(const block_ctrl &a, const block_ctrl &b) + { return a.m_size == b.m_size; } + }; + + struct size_block_ctrl_compare + { + bool operator()(size_type size, const block_ctrl &block) const + { return size < block.m_size; } + + bool operator()(const block_ctrl &block, size_type size) const + { return block.m_size < size; } + }; + + //!Shared mutex to protect memory allocate/deallocate + typedef typename MutexFamily::mutex_type mutex_type; + typedef typename bi::make_multiset + >::type Imultiset; + + typedef typename Imultiset::iterator imultiset_iterator; + typedef typename Imultiset::const_iterator imultiset_const_iterator; + + //!This struct includes needed data and derives from + //!mutex_type to allow EBO when using null mutex_type + struct header_t : public mutex_type + { + Imultiset m_imultiset; + + //!The extra size required by the segment + size_type m_extra_hdr_bytes; + //!Allocated bytes for internal checking + size_type m_allocated; + //!The size of the memory segment + size_type m_size; + } m_header; + + friend class ipcdetail::memory_algorithm_common; + + typedef ipcdetail::memory_algorithm_common algo_impl_t; + + public: + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(rbtree_best_fit) + //!offset that the allocator should not use at all. + rbtree_best_fit (size_type size, size_type extra_hdr_bytes); + + //!Destructor. + ~rbtree_best_fit(); + + //!Obtains the minimum size needed by the algorithm + static size_type get_min_size (size_type extra_hdr_bytes); + + //Functions for single segment management + + //!Allocates bytes, returns 0 if there is not more memory + void* allocate (size_type nbytes); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Experimental. Dont' use + + //!Multiple element allocation, same size + void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); + } + + //!Multiple element allocation, different size + void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); + } + + //!Multiple element allocation, different size + void deallocate_many(multiallocation_chain &chain); + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Deallocates previously allocated bytes + void deallocate (void *addr); + + //!Returns the size of the memory segment + size_type get_size() const; + + //!Returns the number of free bytes of the segment + size_type get_free_memory() const; + + //!Initializes to zero all the memory that's not in use. + //!This function is normally used for security reasons. + void zero_free_memory(); + + //!Increases managed memory in + //!extra_size bytes more + void grow(size_type extra_size); + + //!Decreases managed memory as much as possible + void shrink_to_fit(); + + //!Returns true if all allocated memory has been deallocated + bool all_memory_deallocated(); + + //!Makes an internal sanity check + //!and returns true if success + bool check_sanity(); + + template + T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse); + + void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_object, + size_type &prefer_in_recvd_out_size, + void *&reuse_ptr, size_type sizeof_object = 1); + + //!Returns the size of the buffer previously allocated pointed by ptr + size_type size(const void *ptr) const; + + //!Allocates aligned bytes, returns 0 if there is not more memory. + //!Alignment must be power of 2 + void* allocate_aligned (size_type nbytes, size_type alignment); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + static size_type priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes); + + block_ctrl *priv_first_block(); + + block_ctrl *priv_end_block(); + + void* priv_allocation_command(boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object); + + + //!Real allocation algorithm with min allocation option + void * priv_allocate( boost::interprocess::allocation_type command + , size_type limit_size, size_type &prefer_in_recvd_out_size + , void *&reuse_ptr, size_type backwards_multiple = 1); + + //!Obtains the block control structure of the user buffer + static block_ctrl *priv_get_block(const void *ptr); + + //!Obtains the pointer returned to the user from the block control + static void *priv_get_user_buffer(const block_ctrl *block); + + //!Returns the number of total units that a user buffer + //!of "userbytes" bytes really occupies (including header) + static size_type priv_get_total_units(size_type userbytes); + + //!Real expand function implementation + bool priv_expand(void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size); + + //!Real expand to both sides implementation + void* priv_expand_both_sides(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size + ,void *reuse_ptr + ,bool only_preferred_backwards + ,size_type backwards_multiple); + + //!Returns true if the previous block is allocated + bool priv_is_prev_allocated(block_ctrl *ptr); + + //!Get a pointer of the "end" block from the first block of the segment + static block_ctrl * priv_end_block(block_ctrl *first_segment_block); + + //!Get a pointer of the "first" block from the end block of the segment + static block_ctrl * priv_first_block(block_ctrl *end_segment_block); + + //!Get poitner of the previous block (previous block must be free) + static block_ctrl * priv_prev_block(block_ctrl *ptr); + + //!Get the size in the tail of the previous block + static block_ctrl * priv_next_block(block_ctrl *ptr); + + //!Check if this block is free (not allocated) + bool priv_is_allocated_block(block_ctrl *ptr); + + //!Marks the block as allocated + void priv_mark_as_allocated_block(block_ctrl *ptr); + + //!Marks the block as allocated + void priv_mark_new_allocated_block(block_ctrl *ptr) + { return priv_mark_as_allocated_block(ptr); } + + //!Marks the block as allocated + void priv_mark_as_free_block(block_ctrl *ptr); + + //!Checks if block has enough memory and splits/unlinks the block + //!returning the address to the users + void* priv_check_and_allocate(size_type units + ,block_ctrl* block + ,size_type &received_size); + //!Real deallocation algorithm + void priv_deallocate(void *addr); + + //!Makes a new memory portion available for allocation + void priv_add_segment(void *addr, size_type size); + + public: + + static const size_type Alignment = !MemAlignment + ? size_type(::boost::container::dtl::alignment_of + < ::boost::container::dtl::max_align_t>::value) + : size_type(MemAlignment) + ; + + private: + //Due to embedded bits in size, Alignment must be at least 4 + BOOST_STATIC_ASSERT((Alignment >= 4)); + //Due to rbtree size optimizations, Alignment must have at least pointer alignment + BOOST_STATIC_ASSERT((Alignment >= ::boost::container::dtl::alignment_of::value)); + static const size_type AlignmentMask = (Alignment - 1); + static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size::value; + static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; + static const size_type AllocatedCtrlBytes = ipcdetail::ct_rounded_size::value; + static const size_type AllocatedCtrlUnits = AllocatedCtrlBytes/Alignment; + static const size_type EndCtrlBlockBytes = ipcdetail::ct_rounded_size::value; + static const size_type EndCtrlBlockUnits = EndCtrlBlockBytes/Alignment; + static const size_type MinBlockUnits = BlockCtrlUnits; + static const size_type UsableByPreviousChunk = sizeof(size_type); + + //Make sure the maximum alignment is power of two + BOOST_STATIC_ASSERT((0 == (Alignment & (Alignment - size_type(1u))))); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + static const size_type PayloadPerAllocation = AllocatedCtrlBytes - UsableByPreviousChunk; +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline typename rbtree_best_fit::size_type + rbtree_best_fit + ::priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes) +{ + size_type uint_this = (std::size_t)this_ptr; + size_type main_hdr_end = uint_this + sizeof(rbtree_best_fit) + extra_hdr_bytes; + size_type aligned_main_hdr_end = ipcdetail::get_rounded_size(main_hdr_end, Alignment); + size_type block1_off = aligned_main_hdr_end - uint_this; + algo_impl_t::assert_alignment(aligned_main_hdr_end); + algo_impl_t::assert_alignment(uint_this + block1_off); + return block1_off; +} + +template +void rbtree_best_fit:: + priv_add_segment(void *addr, size_type segment_size) +{ + //Check alignment + algo_impl_t::check_alignment(addr); + //Check size + BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes)); + + //Initialize the first big block and the "end" node + block_ctrl *first_big_block = ::new(addr, boost_container_new_t()) block_ctrl; + first_big_block->m_size = (segment_size/Alignment - EndCtrlBlockUnits) & block_ctrl::size_mask; + BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits); + + //The "end" node is just a node of size 0 with the "end" bit set + SizeHolder *end_block = + ::new(reinterpret_cast(addr) + first_big_block->m_size*Alignment, boost_container_new_t()) SizeHolder; + + //This will overwrite the prev part of the "end" node + priv_mark_as_free_block (first_big_block); + #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP + first_big_block->m_prev_size = end_block->m_size = + size_type(reinterpret_cast(first_big_block) - reinterpret_cast(end_block))/Alignmen) & block_ctrl::size_mask; + #else + first_big_block->m_prev_size = end_block->m_size = + size_type(reinterpret_cast(end_block) - reinterpret_cast(first_big_block))/Alignment & block_ctrl::size_mask; + #endif + end_block->m_allocated = 1; + first_big_block->m_prev_allocated = 1; + + BOOST_ASSERT(priv_next_block(first_big_block) == end_block); + BOOST_ASSERT(priv_prev_block((block_ctrl*)end_block) == first_big_block); + BOOST_ASSERT(priv_first_block() == first_big_block); + BOOST_ASSERT(priv_end_block() == end_block); + + //Some check to validate the algorithm, since it makes some assumptions + //to optimize the space wasted in bookkeeping: + + //Check that the sizes of the header are placed before the rbtree + BOOST_ASSERT(static_cast(static_cast(first_big_block)) + < static_cast(static_cast(first_big_block))); + //Insert it in the intrusive containers + m_header.m_imultiset.insert(*first_big_block); +} + +template +inline typename rbtree_best_fit::block_ctrl * + rbtree_best_fit + ::priv_first_block() +{ + const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); + return move_detail::force_ptr(reinterpret_cast(this) + block1_off); +} + +template +inline typename rbtree_best_fit::block_ctrl * + rbtree_best_fit + ::priv_end_block() +{ + const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); + const size_type original_first_block_size = (m_header.m_size - block1_off)/Alignment - EndCtrlBlockUnits; + block_ctrl *end_block = move_detail::force_ptr + (reinterpret_cast(this) + block1_off + original_first_block_size*Alignment); + return end_block; +} + +template +inline rbtree_best_fit:: + rbtree_best_fit(size_type segment_size, size_type extra_hdr_bytes) +{ + //Initialize the header + m_header.m_allocated = 0; + m_header.m_size = segment_size; + m_header.m_extra_hdr_bytes = extra_hdr_bytes; + + //Now write calculate the offset of the first big block that will + //cover the whole segment + BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= segment_size); + size_type block1_off = priv_first_block_offset_from_this(this, extra_hdr_bytes); + priv_add_segment(reinterpret_cast(this) + block1_off, segment_size - block1_off); +} + +template +inline rbtree_best_fit::~rbtree_best_fit() +{ + //There is a memory leak! +// BOOST_ASSERT(m_header.m_allocated == 0); +// BOOST_ASSERT(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); +} + +template +void rbtree_best_fit::grow(size_type extra_size) +{ + //Get the address of the first block + block_ctrl *first_block = priv_first_block(); + block_ctrl *old_end_block = priv_end_block(); + size_type old_border_offset = (size_type)(reinterpret_cast(old_end_block) - + reinterpret_cast(this)) + EndCtrlBlockBytes; + + //Update managed buffer's size + m_header.m_size += extra_size; + + //We need at least MinBlockUnits blocks to create a new block + if((m_header.m_size - old_border_offset) < MinBlockUnits){ + return; + } + + //Now create a new block between the old end and the new end + size_type align_offset = (m_header.m_size - old_border_offset)/Alignment; + block_ctrl *new_end_block = move_detail::force_ptr + (reinterpret_cast(old_end_block) + align_offset*Alignment); + + //the last and first block are special: + //new_end_block->m_size & first_block->m_prev_size store the absolute value + //between them + new_end_block->m_allocated = 1; + #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP + new_end_block->m_size = size_type(reinterpret_cast(first_block) - + reinterpret_cast(new_end_block))/Alignment & block_ctrl::size_mask; + #else + new_end_block->m_size = size_type(reinterpret_cast(new_end_block) - + reinterpret_cast(first_block))/Alignment & block_ctrl::size_mask; + #endif + first_block->m_prev_size = new_end_block->m_size; + first_block->m_prev_allocated = 1; + BOOST_ASSERT(new_end_block == priv_end_block()); + + //The old end block is the new block + block_ctrl *new_block = old_end_block; + new_block->m_size = size_type(reinterpret_cast(new_end_block) - + reinterpret_cast(new_block))/Alignment & block_ctrl::size_mask; + BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); + priv_mark_as_allocated_block(new_block); + BOOST_ASSERT(priv_next_block(new_block) == new_end_block); + + m_header.m_allocated += (size_type)new_block->m_size*Alignment; + + //Now deallocate the newly created block + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +void rbtree_best_fit::shrink_to_fit() +{ + //Get the address of the first block + block_ctrl *first_block = priv_first_block(); + algo_impl_t::assert_alignment(first_block); + + //block_ctrl *old_end_block = priv_end_block(first_block); + block_ctrl *old_end_block = priv_end_block(); + algo_impl_t::assert_alignment(old_end_block); + size_type old_end_block_size = old_end_block->m_size; + + void *unique_buffer = 0; + block_ctrl *last_block; + //Check if no memory is allocated between the first and last block + if(priv_next_block(first_block) == old_end_block){ + //If so check if we can allocate memory + size_type ignore_recvd = 0; + void *ignore_reuse = 0; + unique_buffer = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); + //If not, return, we can't shrink + if(!unique_buffer) + return; + //If we can, mark the position just after the new allocation as the new end + algo_impl_t::assert_alignment(unique_buffer); + block_ctrl *unique_block = priv_get_block(unique_buffer); + BOOST_ASSERT(priv_is_allocated_block(unique_block)); + algo_impl_t::assert_alignment(unique_block); + last_block = priv_next_block(unique_block); + BOOST_ASSERT(!priv_is_allocated_block(last_block)); + algo_impl_t::assert_alignment(last_block); + } + else{ + //If memory is allocated, check if the last block is allocated + if(priv_is_prev_allocated(old_end_block)) + return; + //If not, mark last block after the free block + last_block = priv_prev_block(old_end_block); + } + + size_type last_block_size = last_block->m_size; + + //Erase block from the free tree, since we will erase it + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*last_block)); + + size_type shrunk_border_offset = (size_type)(reinterpret_cast(last_block) - + reinterpret_cast(this)) + EndCtrlBlockBytes; + + block_ctrl *new_end_block = last_block; + algo_impl_t::assert_alignment(new_end_block); + + //Write new end block attributes + #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP + new_end_block->m_size = + size_type(reinterpret_cast(first_block) - reinterpret_cast(new_end_block))/Alignment & block_ctrl::size_mask; + first_block->m_prev_size = new_end_block->m_size; + #else + new_end_block->m_size = + size_type(reinterpret_cast(new_end_block) - reinterpret_cast(first_block))/Alignment & block_ctrl::size_mask; + first_block->m_prev_size = new_end_block->m_size; + #endif + + new_end_block->m_allocated = 1; + (void)last_block_size; + (void)old_end_block_size; + BOOST_ASSERT(new_end_block->m_size == (old_end_block_size - last_block_size)); + + //Update managed buffer's size + m_header.m_size = shrunk_border_offset & block_ctrl::size_mask; + BOOST_ASSERT(priv_end_block() == new_end_block); + if(unique_buffer) + priv_deallocate(unique_buffer); +} + +template +inline typename rbtree_best_fit::size_type +rbtree_best_fit::get_size() const +{ return m_header.m_size; } + +template +typename rbtree_best_fit::size_type +rbtree_best_fit::get_free_memory() const +{ + return m_header.m_size - m_header.m_allocated - + priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); +} + +template +typename rbtree_best_fit::size_type +rbtree_best_fit:: + get_min_size (size_type extra_hdr_bytes) +{ + return (algo_impl_t::ceil_units(sizeof(rbtree_best_fit)) + + algo_impl_t::ceil_units(extra_hdr_bytes) + + MinBlockUnits + EndCtrlBlockUnits)*Alignment; +} + +template +inline bool rbtree_best_fit:: + all_memory_deallocated() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + size_type block1_off = + priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); + + return m_header.m_allocated == 0 && + m_header.m_imultiset.begin() != m_header.m_imultiset.end() && + (++m_header.m_imultiset.begin()) == m_header.m_imultiset.end() + && m_header.m_imultiset.begin()->m_size == + (m_header.m_size - block1_off - EndCtrlBlockBytes)/Alignment; +} + +template +bool rbtree_best_fit:: + check_sanity() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); + + size_type free_memory = 0; + + //Iterate through all blocks obtaining their size + for(; ib != ie; ++ib){ + free_memory += (size_type)ib->m_size*Alignment; + if(!algo_impl_t::check_alignment(&*ib)) + return false; + } + + //Check allocated bytes are less than size + if(m_header.m_allocated > m_header.m_size){ + return false; + } + + size_type block1_off = + priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); + + //Check free bytes are less than size + if(free_memory > (m_header.m_size - block1_off)){ + return false; + } + return true; +} + +template +inline void* rbtree_best_fit:: + allocate(size_type nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + size_type ignore_recvd = nbytes; + void *ignore_reuse = 0; + return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); +} + +template +inline void* rbtree_best_fit:: + allocate_aligned(size_type nbytes, size_type alignment) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t::allocate_aligned(this, nbytes, alignment); +} + +template +template +inline T* rbtree_best_fit:: + allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse) +{ + void* raw_reuse = reuse; + void* const ret = priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); + reuse = static_cast(raw_reuse); + BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::dtl::alignment_of::value)); + return static_cast(ret); +} + +template +inline void* rbtree_best_fit:: + raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, + size_type &prefer_in_recvd_out_objects, void *&reuse_ptr, size_type sizeof_object) +{ + size_type const preferred_objects = prefer_in_recvd_out_objects; + if(!sizeof_object) + return reuse_ptr = 0, static_cast(0); + if(command & boost::interprocess::try_shrink_in_place){ + if(!reuse_ptr) return static_cast(0); + const bool success = algo_impl_t::try_shrink + ( this, reuse_ptr, limit_objects*sizeof_object + , prefer_in_recvd_out_objects = preferred_objects*sizeof_object); + prefer_in_recvd_out_objects /= sizeof_object; + return success ? reuse_ptr : 0; + } + else{ + return priv_allocation_command + (command, limit_objects, prefer_in_recvd_out_objects, reuse_ptr, sizeof_object); + } +} + + +template +inline void* rbtree_best_fit:: + priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, + void *&reuse_ptr, size_type sizeof_object) +{ + void* ret; + size_type const preferred_size = prefer_in_recvd_out_size; + size_type const max_count = m_header.m_size/sizeof_object; + if(limit_size > max_count || preferred_size > max_count){ + return reuse_ptr = 0, static_cast(0); + } + size_type l_size = limit_size*sizeof_object; + size_type p_size = preferred_size*sizeof_object; + size_type r_size; + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + ret = priv_allocate(command, l_size, r_size = p_size, reuse_ptr, sizeof_object); + } + prefer_in_recvd_out_size = r_size/sizeof_object; + return ret; +} + +template +typename rbtree_best_fit::size_type +rbtree_best_fit:: + size(const void *ptr) const +{ + //We need no synchronization since this block's size is not going + //to be modified by anyone else + //Obtain the real size of the block + return ((size_type)priv_get_block(ptr)->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; +} + +template +inline void rbtree_best_fit::zero_free_memory() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); + + //Iterate through all blocks obtaining their size + while(ib != ie){ + //Just clear user the memory part reserved for the user + volatile char *ptr = reinterpret_cast(&*ib) + BlockCtrlBytes; + size_type s = (size_type)ib->m_size*Alignment - BlockCtrlBytes; + while(s--){ + *ptr++ = 0; + } + + //This surprisingly is optimized out by Visual C++ 7.1 in release mode! + //std::memset( reinterpret_cast(&*ib) + BlockCtrlBytes + // , 0 + // , ib->m_size*Alignment - BlockCtrlBytes); + ++ib; + } +} + +template +void* rbtree_best_fit:: + priv_expand_both_sides(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size + ,void *reuse_ptr + ,bool only_preferred_backwards + ,size_type backwards_multiple) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + algo_impl_t::assert_alignment(reuse_ptr); + if(command & boost::interprocess::expand_fwd){ + if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) + return reuse_ptr; + } + else{ + prefer_in_recvd_out_size = this->size(reuse_ptr); + if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) + return reuse_ptr; + } + + if(backwards_multiple){ + BOOST_ASSERT(0 == (min_size % backwards_multiple)); + BOOST_ASSERT(0 == (preferred_size % backwards_multiple)); + } + + if(command & boost::interprocess::expand_bwd){ + //Obtain the real size of the block + block_ctrl *reuse = priv_get_block(reuse_ptr); + + //Sanity check + algo_impl_t::assert_alignment(reuse); + + block_ctrl *prev_block; + + //If the previous block is not free, there is nothing to do + if(priv_is_prev_allocated(reuse)){ + return 0; + } + + prev_block = priv_prev_block(reuse); + BOOST_ASSERT(!priv_is_allocated_block(prev_block)); + + //Some sanity checks + BOOST_ASSERT(prev_block->m_size == reuse->m_prev_size); + algo_impl_t::assert_alignment(prev_block); + + size_type needs_backwards_aligned; + size_type lcm; + if(!algo_impl_t::calculate_lcm_and_needs_backwards_lcmed + ( backwards_multiple + , prefer_in_recvd_out_size + , only_preferred_backwards ? preferred_size : min_size + , lcm, needs_backwards_aligned)){ + return 0; + } + + //Check if previous block has enough size + if(size_type(prev_block->m_size*Alignment) >= needs_backwards_aligned){ + //Now take all next space. This will succeed + if(command & boost::interprocess::expand_fwd){ + size_type received_size2; + if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, received_size2 = prefer_in_recvd_out_size)){ + BOOST_ASSERT(0); + } + BOOST_ASSERT(prefer_in_recvd_out_size == received_size2); + } + //We need a minimum size to split the previous one + if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){ + block_ctrl *new_block = move_detail::force_ptr + (reinterpret_cast(reuse) - needs_backwards_aligned); + + //Free old previous buffer + new_block->m_size = + (AllocatedCtrlUnits + (needs_backwards_aligned + (prefer_in_recvd_out_size - UsableByPreviousChunk))/Alignment) & block_ctrl::size_mask; + BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); + priv_mark_as_allocated_block(new_block); + + prev_block->m_size = size_type(reinterpret_cast(new_block) - + reinterpret_cast(prev_block))/Alignment & block_ctrl::size_mask; + BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(prev_block); + + //Update the old previous block in the free blocks tree + //If the new size fulfills tree invariants do nothing, + //otherwise erase() + insert() + { + imultiset_iterator prev_block_it(Imultiset::s_iterator_to(*prev_block)); + imultiset_iterator was_smaller_it(prev_block_it); + if(prev_block_it != m_header.m_imultiset.begin() && + (--(was_smaller_it = prev_block_it))->m_size > prev_block->m_size){ + m_header.m_imultiset.erase(prev_block_it); + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *prev_block); + } + } + + prefer_in_recvd_out_size = needs_backwards_aligned + prefer_in_recvd_out_size; + m_header.m_allocated += needs_backwards_aligned; + + //Check alignment + algo_impl_t::assert_alignment(new_block); + + //If the backwards expansion has remaining bytes in the + //first bytes, fill them with a pattern + void *p = priv_get_user_buffer(new_block); + void *user_ptr = reinterpret_cast(p); + BOOST_ASSERT(size_type(static_cast(reuse_ptr) - static_cast(user_ptr)) % backwards_multiple == 0); + algo_impl_t::assert_alignment(user_ptr); + return user_ptr; + } + //Check if there is no place to create a new block and + //the whole new block is multiple of the backwards expansion multiple + else if(prev_block->m_size >= needs_backwards_aligned/Alignment && + 0 == ((prev_block->m_size*Alignment) % lcm)) { + //Erase old previous block, since we will change it + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*prev_block)); + + //Just merge the whole previous block + //prev_block->m_size*Alignment is multiple of lcm (and backwards_multiple) + prefer_in_recvd_out_size = prefer_in_recvd_out_size + (size_type)prev_block->m_size*Alignment; + + m_header.m_allocated += (size_type)prev_block->m_size*Alignment; + //Now update sizes + prev_block->m_size = size_type(prev_block->m_size + reuse->m_size) & block_ctrl::size_mask; + BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); + priv_mark_as_allocated_block(prev_block); + + //If the backwards expansion has remaining bytes in the + //first bytes, fill them with a pattern + void *user_ptr = priv_get_user_buffer(prev_block); + BOOST_ASSERT(size_type(static_cast(reuse_ptr) - static_cast(user_ptr)) % backwards_multiple == 0); + algo_impl_t::assert_alignment(user_ptr); + return user_ptr; + } + else{ + //Alignment issues + } + } + } + return 0; +} + +template +inline void rbtree_best_fit:: + deallocate_many(typename rbtree_best_fit::multiallocation_chain &chain) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + algo_impl_t::deallocate_many(this, chain); +} + +template +void * rbtree_best_fit:: + priv_allocate(boost::interprocess::allocation_type command + ,size_type limit_size + ,size_type &prefer_in_recvd_out_size + ,void *&reuse_ptr + ,size_type backwards_multiple) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + if(command & boost::interprocess::shrink_in_place){ + if(!reuse_ptr) return static_cast(0); + bool success = + algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size = preferred_size); + return success ? reuse_ptr : 0; + } + + prefer_in_recvd_out_size = 0; + + if(limit_size > preferred_size) + return reuse_ptr = 0, static_cast(0); + + //Number of units to request (including block_ctrl header) + size_type preferred_units = priv_get_total_units(preferred_size); + + //Number of units to request (including block_ctrl header) + size_type limit_units = priv_get_total_units(limit_size); + + //Expand in place + prefer_in_recvd_out_size = preferred_size; + if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ + void *ret = priv_expand_both_sides + (command, limit_size, prefer_in_recvd_out_size, reuse_ptr, true, backwards_multiple); + if(ret) + return ret; + } + + if(command & boost::interprocess::allocate_new){ + size_block_ctrl_compare comp; + imultiset_iterator it(m_header.m_imultiset.lower_bound(preferred_units, comp)); + + if(it != m_header.m_imultiset.end()){ + return reuse_ptr = 0, this->priv_check_and_allocate + (preferred_units, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); + } + + if(it != m_header.m_imultiset.begin()&& + (--it)->m_size >= limit_units){ + return reuse_ptr = 0, this->priv_check_and_allocate + (it->m_size, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); + } + } + + + //Now try to expand both sides with min size + if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ + return priv_expand_both_sides + (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false, backwards_multiple); + } + return reuse_ptr = 0, static_cast(0); +} + +template +inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_get_block(const void *ptr) +{ + return const_cast + (move_detail::force_ptr + (reinterpret_cast(ptr) - AllocatedCtrlBytes)); +} + +template +inline +void *rbtree_best_fit:: + priv_get_user_buffer(const typename rbtree_best_fit::block_ctrl *block) +{ return const_cast(reinterpret_cast(block) + AllocatedCtrlBytes); } + +template +inline typename rbtree_best_fit::size_type +rbtree_best_fit:: + priv_get_total_units(size_type userbytes) +{ + if(userbytes < UsableByPreviousChunk) + userbytes = UsableByPreviousChunk; + size_type units = ipcdetail::get_rounded_size(userbytes - UsableByPreviousChunk, Alignment)/Alignment + AllocatedCtrlUnits; + if(units < BlockCtrlUnits) units = BlockCtrlUnits; + return units; +} + +template +bool rbtree_best_fit:: + priv_expand (void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size) +{ + size_type const preferred_size = prefer_in_recvd_out_size; + //Obtain the real size of the block + block_ctrl *block = priv_get_block(ptr); + size_type old_block_units = block->m_size; + + //The block must be marked as allocated and the sizes must be equal + BOOST_ASSERT(priv_is_allocated_block(block)); + + //Put this to a safe value + prefer_in_recvd_out_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) + return true; + + //Now translate it to Alignment units + const size_type min_user_units = algo_impl_t::ceil_units(min_size - UsableByPreviousChunk); + const size_type preferred_user_units = algo_impl_t::ceil_units(preferred_size - UsableByPreviousChunk); + + //Some parameter checks + BOOST_ASSERT(min_user_units <= preferred_user_units); + + block_ctrl *next_block; + + if(priv_is_allocated_block(next_block = priv_next_block(block))){ + return prefer_in_recvd_out_size >= min_size; + } + algo_impl_t::assert_alignment(next_block); + + //Is "block" + "next_block" big enough? + const size_type merged_units = old_block_units + (size_type)next_block->m_size; + + //Now get the expansion size + const size_type merged_user_units = merged_units - AllocatedCtrlUnits; + + if(merged_user_units < min_user_units){ + prefer_in_recvd_out_size = merged_units*Alignment - UsableByPreviousChunk; + return false; + } + + //Now get the maximum size the user can allocate + size_type intended_user_units = (merged_user_units < preferred_user_units) ? + merged_user_units : preferred_user_units; + + //These are total units of the merged block (supposing the next block can be split) + const size_type intended_units = AllocatedCtrlUnits + intended_user_units; + + //Check if we can split the next one in two parts + if((merged_units - intended_units) >= BlockCtrlUnits){ + //This block is bigger than needed, split it in + //two blocks, the first one will be merged and + //the second's size will be the remaining space + BOOST_ASSERT(next_block->m_size == priv_next_block(next_block)->m_prev_size); + const size_type rem_units = merged_units - intended_units; + + //Check if we we need to update the old next block in the free blocks tree + //If the new size fulfills tree invariants, we just need to replace the node + //(the block start has been displaced), otherwise erase() + insert(). + // + //This fixup must be done in two parts, because the new next block might + //overwrite the tree hook of the old next block. So we first erase the + //old if needed and we'll insert the new one after creating the new next + imultiset_iterator old_next_block_it(Imultiset::s_iterator_to(*next_block)); + m_header.m_imultiset.erase(old_next_block_it); + + //This is the remaining block + block_ctrl *rem_block = + ::new(reinterpret_cast(block) + intended_units*Alignment, boost_container_new_t()) block_ctrl; + rem_block->m_size = rem_units & block_ctrl::size_mask; + algo_impl_t::assert_alignment(rem_block); + BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(rem_block); + m_header.m_imultiset.insert(*rem_block); + + //Write the new length + block->m_size = (intended_user_units + AllocatedCtrlUnits) & block_ctrl::size_mask; + BOOST_ASSERT(block->m_size >= BlockCtrlUnits); + m_header.m_allocated += (intended_units - old_block_units)*Alignment; + } + //There is no free space to create a new node: just merge both blocks + else{ + //Now we have to update the data in the tree + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block)); + + //Write the new length + block->m_size = merged_units & block_ctrl::size_mask; + BOOST_ASSERT(block->m_size >= BlockCtrlUnits); + m_header.m_allocated += (merged_units - old_block_units)*Alignment; + } + priv_mark_as_allocated_block(block); + prefer_in_recvd_out_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + return true; +} + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_prev_block + (typename rbtree_best_fit::block_ctrl *ptr) +{ + BOOST_ASSERT(!ptr->m_prev_allocated); + return move_detail::force_ptr + (reinterpret_cast(ptr) - ptr->m_prev_size*Alignment); +} + + + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_end_block + (typename rbtree_best_fit::block_ctrl *first_segment_block) +{ + //The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute + //distance with the end block + BOOST_ASSERT(first_segment_block->m_prev_allocated); + block_ctrl *end_block = move_detail::force_ptr + (reinterpret_cast(first_segment_block) + first_segment_block->m_prev_size*Alignment); + (void)end_block; + BOOST_ASSERT(end_block->m_allocated == 1); + BOOST_ASSERT(end_block->m_size == first_segment_block->m_prev_size); + BOOST_ASSERT(end_block > first_segment_block); + return end_block; +} + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_first_block + (typename rbtree_best_fit::block_ctrl *end_segment_block) +{ + //The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute + //distance with the end block + BOOST_ASSERT(end_segment_block->m_allocated); + block_ctrl *first_block = move_detail::force_ptr + (reinterpret_cast(end_segment_block) - end_segment_block->m_size*Alignment); + (void)first_block; + BOOST_ASSERT(first_block->m_prev_allocated == 1); + BOOST_ASSERT(first_block->m_prev_size == end_segment_block->m_size); + BOOST_ASSERT(end_segment_block > first_block); + return first_block; +} + + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_next_block + (typename rbtree_best_fit::block_ctrl *ptr) +{ + return move_detail::force_ptr + (reinterpret_cast(ptr) + ptr->m_size*Alignment); +} + +template inline +bool rbtree_best_fit::priv_is_allocated_block + (typename rbtree_best_fit::block_ctrl *block) +{ + bool allocated = block->m_allocated != 0; + #ifndef NDEBUG + if(block != priv_end_block()){ + block_ctrl *next_block = move_detail::force_ptr + (reinterpret_cast(block) + block->m_size*Alignment); + bool next_block_prev_allocated = next_block->m_prev_allocated != 0; + (void)next_block_prev_allocated; + BOOST_ASSERT(allocated == next_block_prev_allocated); + } + #endif + return allocated; +} + +template inline +bool rbtree_best_fit::priv_is_prev_allocated + (typename rbtree_best_fit::block_ctrl *block) +{ + if(block->m_prev_allocated){ + return true; + } + else{ + #ifndef NDEBUG + if(block != priv_first_block()){ + block_ctrl *prev = priv_prev_block(block); + (void)prev; + BOOST_ASSERT(!prev->m_allocated); + BOOST_ASSERT(prev->m_size == block->m_prev_size); + } + #endif + return false; + } +} + +template inline +void rbtree_best_fit::priv_mark_as_allocated_block + (typename rbtree_best_fit::block_ctrl *block) +{ + block->m_allocated = 1; + move_detail::force_ptr + (reinterpret_cast(block)+ block->m_size*Alignment)->m_prev_allocated = 1; +} + +template inline +void rbtree_best_fit::priv_mark_as_free_block + (typename rbtree_best_fit::block_ctrl *block) +{ + block->m_allocated = 0; + block_ctrl *next_block = priv_next_block(block); + next_block->m_prev_allocated = 0; + next_block->m_prev_size = block->m_size; +} + +template inline +void* rbtree_best_fit::priv_check_and_allocate + (size_type nunits + ,typename rbtree_best_fit::block_ctrl* block + ,size_type &received_size) +{ + size_type upper_nunits = nunits + BlockCtrlUnits; + imultiset_iterator it_old = Imultiset::s_iterator_to(*block); + algo_impl_t::assert_alignment(block); + + if (block->m_size >= upper_nunits){ + //This block is bigger than needed, split it in + //two blocks, the first's size will be "units" and + //the second's size "block->m_size-units" + size_type block_old_size = block->m_size; + block->m_size = nunits & block_ctrl::size_mask; + BOOST_ASSERT(block->m_size >= BlockCtrlUnits); + + //This is the remaining block + block_ctrl *rem_block = + ::new(reinterpret_cast(block) + Alignment*nunits, boost_container_new_t()) block_ctrl; + algo_impl_t::assert_alignment(rem_block); + rem_block->m_size = (block_old_size - nunits) & block_ctrl::size_mask; + BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(rem_block); + + //Now we have to update the data in the tree. + //Use the position of the erased one as a hint + m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block); + } + else if (block->m_size >= nunits){ + m_header.m_imultiset.erase(it_old); + } + else{ + BOOST_ASSERT(0); + return 0; + } + //We need block_ctrl for deallocation stuff, so + //return memory user can overwrite + m_header.m_allocated += (size_type)block->m_size*Alignment; + received_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + + //Mark the block as allocated + priv_mark_as_allocated_block(block); + + //Clear the memory occupied by the tree hook, since this won't be + //cleared with zero_free_memory + TreeHook *t = static_cast(block); + //Just clear the memory part reserved for the user + std::size_t tree_hook_offset_in_block = std::size_t((char*)t - (char*)block); + //volatile char *ptr = + char *ptr = reinterpret_cast(block)+tree_hook_offset_in_block; + const std::size_t s = BlockCtrlBytes - tree_hook_offset_in_block; + std::memset(ptr, 0, s); + this->priv_next_block(block)->m_prev_size = 0; + return priv_get_user_buffer(block); +} + +template +void rbtree_best_fit::deallocate(void* addr) +{ + if(!addr) return; + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return this->priv_deallocate(addr); +} + +template +void rbtree_best_fit::priv_deallocate(void* addr) +{ + if(!addr) return; + + block_ctrl *block = priv_get_block(addr); + + //The blocks must be marked as allocated and the sizes must be equal + BOOST_ASSERT(priv_is_allocated_block(block)); + + //Check if alignment and block size are right + algo_impl_t::assert_alignment(addr); + + size_type block_old_size = Alignment*(size_type)block->m_size; + BOOST_ASSERT(m_header.m_allocated >= block_old_size); + + //Update used memory count + m_header.m_allocated -= block_old_size; + + //The block to insert in the tree + block_ctrl *block_to_insert = block; + + //Get the next block + block_ctrl *const next_block = priv_next_block(block); + const bool merge_with_prev = !priv_is_prev_allocated(block); + const bool merge_with_next = !priv_is_allocated_block(next_block); + + //Merge logic. First just update block sizes, then fix free blocks tree + if(merge_with_prev || merge_with_next){ + //Merge if the previous is free + if(merge_with_prev){ + //Get the previous block + block_to_insert = priv_prev_block(block); + block_to_insert->m_size = size_type(block_to_insert->m_size + block->m_size) & block_ctrl::size_mask; + BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*block_to_insert)); + } + //Merge if the next is free + if(merge_with_next){ + block_to_insert->m_size = size_type(block_to_insert->m_size + next_block->m_size) & block_ctrl::size_mask; + BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); + const imultiset_iterator next_it = Imultiset::s_iterator_to(*next_block); + m_header.m_imultiset.erase(next_it); + } + } + priv_mark_as_free_block(block_to_insert); + m_header.m_imultiset.insert(*block_to_insert); +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP diff --git a/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp b/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp new file mode 100644 index 00000000000..69813f41bca --- /dev/null +++ b/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SIMPLE_SEQ_FIT_HPP +#define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +//!\file +//!Describes sequential fit algorithm used to allocate objects in shared memory. + +namespace boost { +namespace interprocess { + +//!This class implements the simple sequential fit algorithm with a simply +//!linked list of free buffers. +template +class simple_seq_fit + : public ipcdetail::simple_seq_fit_impl +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef ipcdetail::simple_seq_fit_impl base_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef typename base_t::size_type size_type; + + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit) + //!offset that the allocator should not use at all.*/ + simple_seq_fit(size_type segment_size, size_type extra_hdr_bytes) + : base_t(segment_size, extra_hdr_bytes){} +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP + diff --git a/extern/boost/boost/interprocess/offset_ptr.hpp b/extern/boost/boost/interprocess/offset_ptr.hpp new file mode 100644 index 00000000000..5619ec30774 --- /dev/null +++ b/extern/boost/boost/interprocess/offset_ptr.hpp @@ -0,0 +1,776 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP +#define BOOST_INTERPROCESS_OFFSET_PTR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include //alignment_of, aligned_storage +#include +#include +#include + +#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + + +//!\file +//!Describes a smart pointer that stores the offset between this pointer and +//!target pointee, called offset_ptr. + +namespace boost { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +//Predeclarations +template +struct has_trivial_destructor; + +#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail { + + template + union offset_ptr_internal + { + BOOST_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t)); + BOOST_STATIC_ASSERT(boost::is_integral::value && boost::is_unsigned::value); + + explicit offset_ptr_internal(OffsetType off) + : m_offset(off) + {} + + OffsetType m_offset; //Distance between this object and pointee address + + typename ::boost::container::dtl::aligned_storage + < sizeof(OffsetType)//for offset_type_alignment m_offset will be enough + , (OffsetAlignment == offset_type_alignment) ? 1u : OffsetAlignment + >::type alignment_helper; + }; + + //Note: using the address of a local variable to point to another address + //is not standard conforming and this can be optimized-away by the compiler. + //Non-inlining is a method to remain illegal but correct + + //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline + //this code without breaking the library + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_raw_pointer + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + template + BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset) + { + typedef pointer_offset_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + if(offset == 1){ + return 0; + } + else{ + return caster_t(caster_t(this_ptr).offset() + offset).pointer(); + } + #else + OffsetType mask = offset == 1; + --mask; + OffsetType target_offset = caster_t(this_ptr).offset() + offset; + target_offset &= mask; + return caster_t(target_offset).pointer(); + #endif + } + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) + { + typedef pointer_offset_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + //offset == 1 && ptr != 0 is not legal for this pointer + if(!ptr){ + return 1; + } + else{ + OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset(); + BOOST_ASSERT(offset != 1); + return offset; + } + #else + //const OffsetType other = -OffsetType(ptr != 0); + //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other; + //return offset + OffsetType(!other); + // + OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset(); + --offset; + OffsetType mask = ptr == 0; + --mask; + offset &= mask; + return ++offset; + #endif + } + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset_from_other + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other + (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset) + { + typedef pointer_offset_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + if(other_offset == 1){ + return 1; + } + else{ + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset; + BOOST_ASSERT(offset != 1); + return offset; + } + #else + OffsetType mask = other_offset == 1; + --mask; + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); + offset &= mask; + return offset + other_offset; + + //OffsetType mask = -OffsetType(other_offset != 1); + //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); + //offset &= mask; + //return offset + other_offset; + #endif + } + + //////////////////////////////////////////////////////////////////////// + // + // Let's assume cast to void and cv cast don't change any target address + // + //////////////////////////////////////////////////////////////////////// + template + struct offset_ptr_maintains_address + { + static const bool value = ipcdetail::is_cv_same::value + || ipcdetail::is_cv_same::value + || ipcdetail::is_cv_same::value + ; + }; + + template + struct enable_if_convertible_equal_address + : enable_if_c< ::boost::is_convertible::value + && offset_ptr_maintains_address::value + , Ret> + {}; + + template + struct enable_if_convertible_unequal_address + : enable_if_c< ::boost::is_convertible::value + && !offset_ptr_maintains_address::value + , Ret> + {}; + +} //namespace ipcdetail { +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!A smart pointer that stores the offset between the pointer and the +//!object it points to. This allows special properties, since +//!the pointer is independent from the address of the pointee, if the +//!pointer and the pointee are still separated by the same offset. This feature +//!converts offset_ptr in a smart pointer that can be placed in shared memory and +//!memory mapped files mapped at different addresses in every process. +//! +//! \tparam PointedType The type of the pointee. +//! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer +//! \tparam OffsetType An unsigned integer type that can represent the +//! distance between two pointers reinterpret_cast-ed as unsigned integers. This type +//! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate +//! between 32 and 64 bit processes using 64 bit offsets. +//! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary +//! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets. +//! +//!Note: offset_ptr uses implementation defined properties, present in most platforms, for +//!performance reasons: +//! - Assumes that OffsetType representation of nullptr is (OffsetType)zero. +//! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent +//! to incrementing the pointer and then converting it back to OffsetType. +template +class offset_ptr +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef offset_ptr self_t; + void unspecified_bool_type_func() const {} + typedef void (self_t::*unspecified_bool_type)() const; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef PointedType element_type; + typedef PointedType * pointer; + typedef typename ipcdetail:: + add_reference::type reference; + typedef typename ipcdetail:: + remove_volatile::type + >::type value_type; + typedef DifferenceType difference_type; + typedef std::random_access_iterator_tag iterator_category; + typedef OffsetType offset_type; + + public: //Public Functions + + //!Default constructor (null pointer). + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr() BOOST_NOEXCEPT + : internal(1) + {} + + //!Constructor from raw pointer (allows "0" pointer conversion). + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(ptr, this)) + {} + + //!Constructor from other pointer. + //!Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr + , typename ipcdetail::enable_if< ::boost::is_convertible >::type * = 0) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr), this)) + {} + + //!Constructor from other offset_ptr + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)) + {} + + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if T2* is convertible to PointedType*. Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_convertible_equal_address::type* = 0 + #endif + ) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())) + {} + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr + , typename ipcdetail::enable_if_convertible_unequal_address::type* = 0) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) + {} + + #endif + + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< + !::boost::is_convertible::value && ::boost::is_constructible::value + >::type * = 0 + #endif + ) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) + {} + + //!Emulates static_cast operator. + //!Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this)) + {} + + //!Emulates const_cast operator. + //!Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this)) + {} + + //!Emulates dynamic_cast operator. + //!Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this)) + {} + + //!Emulates reinterpret_cast operator. + //!Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this)) + {} + + //!Obtains raw pointer from offset. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT + { return static_cast(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); } + + BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT + { return this->internal.m_offset; } + + //!Pointer-like -> operator. It can return 0 pointer. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT + { return this->get(); } + + //!Dereferencing operator, if it is a null offset_ptr behavior + //! is undefined. Never throws. + BOOST_INTERPROCESS_FORCEINLINE reference operator* () const BOOST_NOEXCEPT + { + pointer p = this->get(); + reference r = *p; + return r; + } + + //!Indexing operator. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE reference operator[](difference_type idx) const BOOST_NOEXCEPT + { return this->get()[idx]; } + + //!Assignment from pointer (saves extra conversion). + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT + { + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(from, this); + return *this; + } + + //!Assignment from other offset_ptr. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT + { + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset); + return *this; + } + + //!Assignment from related offset_ptr. If pointers of pointee types + //! are assignable, offset_ptrs will be assignable. Never throws. + template BOOST_INTERPROCESS_FORCEINLINE + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typename ipcdetail::enable_if_c + < ::boost::is_convertible::value, offset_ptr&>::type + #else + offset_ptr& + #endif + operator= (const offset_ptr &ptr) BOOST_NOEXCEPT + { + this->assign(ptr, ipcdetail::bool_::value>()); + return *this; + } + + public: + + //!offset_ptr += difference_type. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT + { this->inc_offset(offset * difference_type(sizeof(PointedType))); return *this; } + + //!offset_ptr -= difference_type. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT + { this->dec_offset(offset * difference_type(sizeof(PointedType))); return *this; } + + //!++offset_ptr. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT + { this->inc_offset(difference_type(sizeof(PointedType))); return *this; } + + //!offset_ptr++. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator++ (int) BOOST_NOEXCEPT + { + offset_ptr tmp(*this); + this->inc_offset(sizeof (PointedType)); + return tmp; + } + + //!--offset_ptr. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator-- (void) BOOST_NOEXCEPT + { this->dec_offset(sizeof (PointedType)); return *this; } + + //!offset_ptr--. + //!Never throws. + BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator-- (int) BOOST_NOEXCEPT + { + offset_ptr tmp(*this); + this->dec_offset(sizeof (PointedType)); + return tmp; + } + + //!safe bool conversion operator. + //!Never throws. + #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const BOOST_NOEXCEPT + { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; } + #else + explicit operator bool() const BOOST_NOEXCEPT + { return this->internal.m_offset != 1; } + #endif + + //!Not operator. Not needed in theory, but improves portability. + //!Never throws + BOOST_INTERPROCESS_FORCEINLINE bool operator! () const BOOST_NOEXCEPT + { return this->internal.m_offset == 1; } + + //!Compatibility with pointer_traits + //! + #if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + struct rebind + { typedef offset_ptr other; }; + #else + template + using rebind = offset_ptr; + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef offset_ptr other; + #endif //BOOST_INTERPROCESS_DOXYGEN_INVOKED + #endif + + //!Compatibility with pointer_traits + //! + BOOST_INTERPROCESS_FORCEINLINE static offset_ptr pointer_to(reference r) BOOST_NOEXCEPT + { return offset_ptr(&r); } + + //!difference_type + offset_ptr + //!operation + BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(difference_type diff, offset_ptr right) BOOST_NOEXCEPT + { right += diff; return right; } + + //!offset_ptr + difference_type + //!operation + BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(offset_ptr left, difference_type diff) BOOST_NOEXCEPT + { left += diff; return left; } + + //!offset_ptr - diff + //!operation + BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(offset_ptr left, difference_type diff) BOOST_NOEXCEPT + { left -= diff; return left; } + + //!offset_ptr - diff + //!operation + BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(difference_type diff, offset_ptr right) BOOST_NOEXCEPT + { right -= diff; return right; } + + //!offset_ptr - offset_ptr + //!operation + BOOST_INTERPROCESS_FORCEINLINE friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) BOOST_NOEXCEPT + { return difference_type(pt.get()- pt2.get()); } + + //Comparison + BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() == pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() != pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() < pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() <= pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() > pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1.get() >= pt2.get(); } + + //Comparison to raw ptr to support literal 0 + BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 == pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 != pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 < pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 <= pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 > pt2.get(); } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT + { return pt1 >= pt2.get(); } + + //Comparison + BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() == pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() != pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() < pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() <= pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() > pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT + { return pt1.get() >= pt2; } + + BOOST_INTERPROCESS_FORCEINLINE friend void swap(offset_ptr &left, offset_ptr &right) BOOST_NOEXCEPT + { + pointer ptr = right.get(); + right = left; + left = ptr; + } + + private: + template + BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT + { //no need to pointer adjustment + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()); + } + + template + BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT + { //we must convert to raw before calculating the offset + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + BOOST_INTERPROCESS_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT + { internal.m_offset += OffsetType(bytes); } + + BOOST_INTERPROCESS_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT + { internal.m_offset -= OffsetType(bytes); } + + ipcdetail::offset_ptr_internal internal; + + public: + BOOST_INTERPROCESS_FORCEINLINE const OffsetType &priv_offset() const BOOST_NOEXCEPT + { return internal.m_offset; } + + BOOST_INTERPROCESS_FORCEINLINE OffsetType &priv_offset() BOOST_NOEXCEPT + { return internal.m_offset; } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!operator<< +//!for offset ptr +template +inline std::basic_ostream & operator<< + (std::basic_ostream & os, offset_ptr const & p) +{ return os << p.get_offset(); } + +//!operator>> +//!for offset ptr +template +inline std::basic_istream & operator>> + (std::basic_istream & is, offset_ptr & p) +{ return is >> p.get_offset(); } + +//!Simulation of static_cast between pointers. Never throws. +template +BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr + static_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::ipcdetail::static_cast_tag()); +} + +//!Simulation of const_cast between pointers. Never throws. +template +BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr + const_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::ipcdetail::const_cast_tag()); +} + +//!Simulation of dynamic_cast between pointers. Never throws. +template +BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr + dynamic_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); +} + +//!Simulation of reinterpret_cast between pointers. Never throws. +template +BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr + reinterpret_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); +} + +} //namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +///has_trivial_destructor<> == true_type specialization for optimizations +template +struct has_trivial_destructor< ::boost::interprocess::offset_ptr > +{ + static const bool value = true; +}; + +namespace move_detail { + +///has_trivial_destructor<> == true_type specialization for optimizations +template +struct is_trivially_destructible< ::boost::interprocess::offset_ptr > +{ + static const bool value = true; +}; + +} //namespace move_detail { + +namespace interprocess { + +//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. +//!Never throws. +template +BOOST_INTERPROCESS_FORCEINLINE T * to_raw_pointer(boost::interprocess::offset_ptr const & p) BOOST_NOEXCEPT +{ return ipcdetail::to_raw_pointer(p); } + +} //namespace interprocess + + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +} //namespace boost { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +namespace boost{ + +//This is to support embedding a bit in the pointer +//for intrusive containers, saving space +namespace intrusive { + +//Predeclaration to avoid including header +template +struct max_pointer_plus_bits; + +template +struct max_pointer_plus_bits, OffsetAlignment> +{ + //The offset ptr can embed one bit less than the alignment since it + //uses offset == 1 to store the null pointer. + static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros::value - 1; +}; + +//Predeclaration +template +struct pointer_plus_bits; + +template +struct pointer_plus_bits, NumBits> +{ + typedef boost::interprocess::offset_ptr pointer; + //Bits are stored in the lower bits of the pointer except the LSB, + //because this bit is used to represent the null pointer. + static const O Mask = ((static_cast(1) << NumBits) - static_cast(1)) << 1; + BOOST_STATIC_ASSERT(0 ==(Mask&1)); + + //We must ALWAYS take argument "n" by reference as a copy of a null pointer + //with a bit (e.g. offset == 3) would be incorrectly copied and interpreted as non-null. + + BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT + { + pointer p; + O const tmp_off = n.priv_offset() & ~Mask; + p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off); + return p; + } + + BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT + { + BOOST_ASSERT(0 == (get_bits)(p)); + O const stored_bits = n.priv_offset() & Mask; + n = p; + n.priv_offset() |= stored_bits; + } + + BOOST_INTERPROCESS_FORCEINLINE static std::size_t get_bits(const pointer &n) BOOST_NOEXCEPT + { + return std::size_t((n.priv_offset() & Mask) >> 1u); + } + + BOOST_INTERPROCESS_FORCEINLINE static void set_bits(pointer &n, std::size_t const b) BOOST_NOEXCEPT + { + BOOST_ASSERT(b < (std::size_t(1) << NumBits)); + O tmp = n.priv_offset(); + tmp &= ~Mask; + tmp |= O(b << 1u); + n.priv_offset() = tmp; + } +}; + +} //namespace intrusive + +//Predeclaration +template +struct pointer_to_other; + +//Backwards compatibility with pointer_to_other +template +struct pointer_to_other + < ::boost::interprocess::offset_ptr, U > +{ + typedef ::boost::interprocess::offset_ptr type; +}; + +} //namespace boost{ +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +#include + +#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) +#pragma GCC diagnostic pop +#endif + +#endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP diff --git a/extern/boost/boost/interprocess/segment_manager.hpp b/extern/boost/boost/interprocess/segment_manager.hpp new file mode 100644 index 00000000000..d292c505b77 --- /dev/null +++ b/extern/boost/boost/interprocess/segment_manager.hpp @@ -0,0 +1,1357 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SEGMENT_MANAGER_HPP +#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// container/detail +#include +#include +// std +#include //std::size_t +#include +#include +#ifndef BOOST_NO_EXCEPTIONS +#include +#endif +#include + +//!\file +//!Describes the object placed in a memory segment that provides +//!named object allocation capabilities for single-segment and +//!multi-segment allocations. + +namespace boost{ +namespace interprocess{ + +//!This object is the public base class of segment manager. +//!This class only depends on the memory allocation algorithm +//!and implements all the allocation features not related +//!to named or unique objects. +//! +//!Storing a reference to segment_manager forces +//!the holder class to be dependent on index types and character types. +//!When such dependence is not desirable and only anonymous and raw +//!allocations are needed, segment_manager_base is the correct answer. +template +class segment_manager_base + : private MemoryAlgorithm +{ + public: + typedef segment_manager_base segment_manager_base_type; + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef typename MemoryAlgorithm::mutex_family mutex_family; + typedef MemoryAlgorithm memory_algorithm; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Experimental. Don't use + typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; + typedef typename MemoryAlgorithm::difference_type difference_type; + typedef typename MemoryAlgorithm::size_type size_type; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!This constant indicates the payload size + //!associated with each allocation of the memory algorithm + static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation; + + //!Constructor of the segment_manager_base + //! + //!"size" is the size of the memory segment where + //!the basic segment manager is being constructed. + //! + //!"reserved_bytes" is the number of bytes + //!after the end of the memory algorithm object itself + //!that the memory algorithm will exclude from + //!dynamic allocation + //! + //!Can throw + segment_manager_base(size_type sz, size_type reserved_bytes) + : MemoryAlgorithm(sz, reserved_bytes) + { + BOOST_ASSERT((sizeof(segment_manager_base) == sizeof(MemoryAlgorithm))); + } + + //!Returns the size of the memory + //!segment + size_type get_size() const + { return MemoryAlgorithm::get_size(); } + + //!Returns the number of free bytes of the memory + //!segment + size_type get_free_memory() const + { return MemoryAlgorithm::get_free_memory(); } + + //!Obtains the minimum size needed by + //!the segment manager + static size_type get_min_size (size_type size) + { return MemoryAlgorithm::get_min_size(size); } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Never throws + void * allocate (size_type nbytes, const std::nothrow_t &) + { return MemoryAlgorithm::allocate(nbytes); } + + //!Returns a reference to the internal memory algorithm. + //!This function is useful for custom memory algorithms that + //!need additional configuration options after construction. Never throws. + //!This function should be only used by advanced users. + MemoryAlgorithm &get_memory_algorithm() + { return static_cast(*this); } + + //!Returns a const reference to the internal memory algorithm. + //!This function is useful for custom memory algorithms that + //!need additional configuration options after construction. Never throws. + //!This function should be only used by advanced users. + const MemoryAlgorithm &get_memory_algorithm() const + { return static_cast(*this); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Experimental. Dont' use. + //!Allocates n_elements of elem_bytes bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { + size_type prev_size = chain.size(); + MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); + if(!elem_bytes || chain.size() == prev_size){ + throw bad_alloc(); + } + } + + //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { + size_type prev_size = chain.size(); + MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain); + if(!sizeof_element || chain.size() == prev_size){ + throw bad_alloc(); + } + } + + //!Allocates n_elements of elem_bytes bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); } + + //!Allocates n_elements, each one of + //!element_lengths[i]*sizeof_element bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); } + + //!Deallocates all elements contained in chain. + //!Never throws. + void deallocate_many(multiallocation_chain &chain) + { MemoryAlgorithm::deallocate_many(chain); } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc + //!on failure + void * allocate(size_type nbytes) + { + void * ret = MemoryAlgorithm::allocate(nbytes); + if(!ret) + throw bad_alloc(); + return ret; + } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Never throws + void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &) + { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Throws bad_alloc when fails + void * allocate_aligned(size_type nbytes, size_type alignment) + { + void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment); + if(!ret) + throw bad_alloc(); + return ret; + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + template + T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse) + { + T *ret = MemoryAlgorithm::allocation_command + (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse); + if(!(command & boost::interprocess::nothrow_allocation) && !ret) + throw bad_alloc(); + return ret; + } + + void *raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, + size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1) + { + void *ret = MemoryAlgorithm::raw_allocation_command + ( command | boost::interprocess::nothrow_allocation, limit_objects, + prefer_in_recvd_out_size, reuse, sizeof_object); + if(!(command & boost::interprocess::nothrow_allocation) && !ret) + throw bad_alloc(); + return ret; + } + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Deallocates the bytes allocated with allocate/allocate_many() + //!pointed by addr + void deallocate (void *addr) + { MemoryAlgorithm::deallocate(addr); } + + //!Increases managed memory in extra_size bytes more. This only works + //!with single-segment management. + void grow(size_type extra_size) + { MemoryAlgorithm::grow(extra_size); } + + //!Decreases managed memory to the minimum. This only works + //!with single-segment management. + void shrink_to_fit() + { MemoryAlgorithm::shrink_to_fit(); } + + //!Returns the result of "all_memory_deallocated()" function + //!of the used memory algorithm + bool all_memory_deallocated() + { return MemoryAlgorithm::all_memory_deallocated(); } + + //!Returns the result of "check_sanity()" function + //!of the used memory algorithm + bool check_sanity() + { return MemoryAlgorithm::check_sanity(); } + + //!Writes to zero free memory (memory not yet allocated) + //!of the memory algorithm + void zero_free_memory() + { MemoryAlgorithm::zero_free_memory(); } + + //!Returns the size of the buffer previously allocated pointed by ptr + size_type size(const void *ptr) const + { return MemoryAlgorithm::size(ptr); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + protected: + void * prot_anonymous_construct + (size_type num, bool dothrow, ipcdetail::in_place_interface &table) + { + typedef ipcdetail::block_header block_header_t; + block_header_t block_info ( size_type(table.size*num) + , size_type(table.alignment) + , anonymous_type + , 1 + , 0); + + //Allocate memory + void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get()); + + //Check if there is enough memory + if(!ptr_struct){ + if(dothrow){ + throw bad_alloc(); + } + else{ + return 0; + } + } + + //Build scoped ptr to avoid leaks with constructor exception + ipcdetail::mem_algo_deallocator mem(ptr_struct, *this); + + //Now construct the header + block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Now call constructors + table.construct_n(ptr, num); + + //All constructors successful, we don't want erase memory + mem.release(); + return ptr; + } + + //!Calls the destructor and makes an anonymous deallocate + void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table) + { + + //Get control data from associated with this object + typedef ipcdetail::block_header block_header_t; + block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment); + + //------------------------------- + //scoped_lock guard(m_header); + //------------------------------- + + if(ctrl_data->alloc_type() != anonymous_type){ + //This is not an anonymous object, the pointer is wrong! + BOOST_ASSERT(0); + } + + //Call destructors and free memory + //Build scoped ptr to avoid leaks with destructor exception + table.destroy_n(const_cast(object), ctrl_data->m_value_bytes/table.size); + this->deallocate(ctrl_data); + } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!This object is placed in the beginning of memory segment and +//!implements the allocation (named or anonymous) of portions +//!of the segment. This object contains two indexes that +//!maintain an association between a name and a portion of the segment. +//! +//!The first index contains the mappings for normal named objects using the +//!char type specified in the template parameter. +//! +//!The second index contains the association for unique instances. The key will +//!be the const char * returned from type_info.name() function for the unique +//!type to be constructed. +//! +//!segment_manager inherits publicly +//!from segment_manager_base and inherits from it +//!many public functions related to anonymous object and raw memory allocation. +//!See segment_manager_base reference to know about those functions. +template class IndexType> +class segment_manager + : public segment_manager_base +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + segment_manager(); + segment_manager(const segment_manager &); + segment_manager &operator=(const segment_manager &); + typedef segment_manager_base segment_manager_base_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef MemoryAlgorithm memory_algorithm; + typedef typename segment_manager_base_t::void_pointer void_pointer; + typedef typename segment_manager_base_t::size_type size_type; + typedef typename segment_manager_base_t::difference_type difference_type; + typedef CharType char_type; + + typedef segment_manager_base segment_manager_base_type; + + static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef ipcdetail::block_header block_header_t; + typedef ipcdetail::index_config index_config_named; + typedef ipcdetail::index_config index_config_unique; + typedef IndexType index_type; + typedef ipcdetail::bool_::value > is_intrusive_t; + typedef ipcdetail::bool_::value> is_node_index_t; + + public: + typedef IndexType named_index_t; + typedef IndexType unique_index_t; + typedef ipcdetail::char_ptr_holder char_ptr_holder_t; + typedef ipcdetail::segment_manager_iterator_transform + ::value> named_transform; + + typedef ipcdetail::segment_manager_iterator_transform + ::value> unique_transform; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + typedef typename segment_manager_base_t::mutex_family mutex_family; + + typedef transform_iterator + const_named_iterator; + typedef transform_iterator + const_unique_iterator; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Constructor proxy object definition helper class + template + struct construct_proxy + { + typedef ipcdetail::named_proxy type; + }; + + //!Constructor proxy object definition helper class + template + struct construct_iter_proxy + { + typedef ipcdetail::named_proxy type; + }; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Constructor of the segment manager + //!"size" is the size of the memory segment where + //!the segment manager is being constructed. + //!Can throw + explicit segment_manager(size_type segment_size) + : segment_manager_base_t(segment_size, priv_get_reserved_bytes()) + , m_header(static_cast(get_this_pointer())) + { + (void) anonymous_instance; (void) unique_instance; + //Check EBO is applied, it's required + const void * const this_addr = this; + const void *const segm_addr = static_cast(this); + (void)this_addr; (void)segm_addr; + BOOST_ASSERT( this_addr == segm_addr); + const std::size_t void_ptr_alignment = boost::move_detail::alignment_of::value; (void)void_ptr_alignment; + BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of::value)); + } + + //!Tries to find a previous named/unique allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair find (char_ptr_holder_t name) + { return this->priv_find_impl(name, true); } + + //!Tries to find a previous named/unique allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. This search is not mutex-protected! + //!Use it only inside atomic_func() calls, where the internal mutex + //!is guaranteed to be locked. + template + std::pair find_no_lock (char_ptr_holder_t name) + { return this->priv_find_impl(name, false); } + + //!Returns throwing "construct" proxy + //!object + template + typename construct_proxy::type + construct(char_ptr_holder_t name) + { return typename construct_proxy::type (this, name, false, true); } + + //!Returns throwing "search or construct" proxy + //!object + template + typename construct_proxy::type find_or_construct(char_ptr_holder_t name) + { return typename construct_proxy::type (this, name, true, true); } + + //!Returns no throwing "construct" proxy + //!object + template + typename construct_proxy::type + construct(char_ptr_holder_t name, const std::nothrow_t &) + { return typename construct_proxy::type (this, name, false, false); } + + //!Returns no throwing "search or construct" + //!proxy object + template + typename construct_proxy::type + find_or_construct(char_ptr_holder_t name, const std::nothrow_t &) + { return typename construct_proxy::type (this, name, true, false); } + + //!Returns throwing "construct from iterators" proxy object + template + typename construct_iter_proxy::type + construct_it(char_ptr_holder_t name) + { return typename construct_iter_proxy::type (this, name, false, true); } + + //!Returns throwing "search or construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name) + { return typename construct_iter_proxy::type (this, name, true, true); } + + //!Returns no throwing "construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + construct_it(char_ptr_holder_t name, const std::nothrow_t &) + { return typename construct_iter_proxy::type (this, name, false, false); } + + //!Returns no throwing "search or construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &) + { return typename construct_iter_proxy::type (this, name, true, false); } + + //!Calls object function blocking recursive interprocess_mutex and guarantees that + //!no new named_alloc or destroy will be executed by any process while + //!executing the object function call + template + void atomic_func(Func &f) + { scoped_lock guard(m_header); f(); } + + //!Tries to calls a functor guaranteeing that no new construction, search or + //!destruction will be executed by any process while executing the object + //!function call. If the atomic function can't be immediatelly executed + //!because the internal mutex is already locked, returns false. + //!If the functor throws, this function throws. + template + bool try_atomic_func(Func &f) + { + scoped_lock guard(m_header, try_to_lock); + if(guard){ + f(); + return true; + } + else{ + return false; + } + } + + //!Destroys a previously created named/unique instance. + //!Returns false if the object was not present. + template + bool destroy(char_ptr_holder_t name) + { + BOOST_ASSERT(!name.is_anonymous()); + ipcdetail::placement_destroy dtor; + + if(name.is_unique()){ + return this->priv_generic_named_destroy + ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t()); + } + else{ + return this->priv_generic_named_destroy + ( name.get(), m_header.m_named_index, dtor, is_intrusive_t()); + } + } + + //!Destroys an anonymous, unique or named object + //!using its address + template + void destroy_ptr(const T *p) + { + //If T is void transform it to char + typedef typename ipcdetail::char_if_void::type data_t; + ipcdetail::placement_destroy dtor; + priv_destroy_ptr(p, dtor); + } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw + template + static const CharType *get_instance_name(const T *ptr) + { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); } + + //!Returns the length of an object created with construct/find_or_construct + //!functions. Does not throw. + template + static size_type get_instance_length(const T *ptr) + { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); } + + //!Returns is the the name of an object created with construct/find_or_construct + //!functions. Does not throw + template + static instance_type get_instance_type(const T *ptr) + { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" named objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_named_objects(size_type num) + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_named_index.reserve(num); + } + + //!Preallocates needed index resources to optimize the + //!creation of "num" unique objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_unique_objects(size_type num) + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_unique_index.reserve(num); + } + + //!Calls shrink_to_fit in both named and unique object indexes + //!to try to free unused memory from those indexes. + void shrink_to_fit_indexes() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_named_index.shrink_to_fit(); + m_header.m_unique_index.shrink_to_fit(); + } + + //!Returns the number of named objects stored in + //!the segment. + size_type get_num_named_objects() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + return m_header.m_named_index.size(); + } + + //!Returns the number of unique objects stored in + //!the segment. + size_type get_num_unique_objects() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + return m_header.m_unique_index.size(); + } + + //!Obtains the minimum size needed by the + //!segment manager + static size_type get_min_size() + { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); } + + //!Returns a constant iterator to the beginning of the information about + //!the named allocations performed in this segment manager + const_named_iterator named_begin() const + { + return (make_transform_iterator) + (m_header.m_named_index.begin(), named_transform()); + } + + //!Returns a constant iterator to the end of the information about + //!the named allocations performed in this segment manager + const_named_iterator named_end() const + { + return (make_transform_iterator) + (m_header.m_named_index.end(), named_transform()); + } + + //!Returns a constant iterator to the beginning of the information about + //!the unique allocations performed in this segment manager + const_unique_iterator unique_begin() const + { + return (make_transform_iterator) + (m_header.m_unique_index.begin(), unique_transform()); + } + + //!Returns a constant iterator to the end of the information about + //!the unique allocations performed in this segment manager + const_unique_iterator unique_end() const + { + return (make_transform_iterator) + (m_header.m_unique_index.end(), unique_transform()); + } + + //!This is the default allocator to allocate types T + //!from this managed segment + template + struct allocator + { + typedef boost::interprocess::allocator type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename allocator::type + get_allocator() + { return typename allocator::type(this); } + + //!This is the default deleter to delete types T + //!from this managed segment. + template + struct deleter + { + typedef boost::interprocess::deleter type; + }; + + //!Returns an instance of the default deleter for type T + //!that will delete an object constructed in this segment manager. + template + typename deleter::type + get_deleter() + { return typename deleter::type(this); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Generic named/anonymous new function. Offers all the possibilities, + //!such as throwing, search before creating, and the constructor is + //!encapsulated in an object function. + template + T *generic_construct(const CharType *name, + size_type num, + bool try2find, + bool dothrow, + ipcdetail::in_place_interface &table) + { + return static_cast + (priv_generic_construct(name, num, try2find, dothrow, table)); + } + + private: + //!Tries to find a previous named allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair priv_find_impl (const CharType* name, bool lock) + { + //The name can't be null, no anonymous object can be found by name + BOOST_ASSERT(name != 0); + ipcdetail::placement_destroy table; + size_type sz; + void *ret; + + if(name == reinterpret_cast(-1)){ + ret = priv_generic_find (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock); + } + else{ + ret = priv_generic_find (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock); + } + return std::pair(static_cast(ret), sz); + } + + //!Tries to find a previous unique allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair priv_find_impl (const ipcdetail::unique_instance_t* name, bool lock) + { + ipcdetail::placement_destroy table; + size_type size; + void *ret = priv_generic_find(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock); + return std::pair(static_cast(ret), size); + } + + void *priv_generic_construct + (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table) + { + void *ret; + //Security overflow check + if(num > ((std::size_t)-1)/table.size){ + if(dothrow) + throw bad_alloc(); + else + return 0; + } + if(name == 0){ + ret = this->prot_anonymous_construct(num, dothrow, table); + } + else if(name == reinterpret_cast(-1)){ + ret = this->priv_generic_named_construct + (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t()); + } + else{ + ret = this->priv_generic_named_construct + (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t()); + } + return ret; + } + + void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor) + { + block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment); + switch(ctrl_data->alloc_type()){ + case anonymous_type: + this->prot_anonymous_destroy(ptr, dtor); + break; + + case named_type: + this->priv_generic_named_destroy + (ctrl_data, m_header.m_named_index, dtor, is_node_index_t()); + break; + + case unique_type: + this->priv_generic_named_destroy + (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t()); + break; + + default: + //This type is unknown, bad pointer passed to this function! + BOOST_ASSERT(0); + break; + } + } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw + static const CharType *priv_get_instance_name(block_header_t *ctrl_data) + { + boost::interprocess::allocation_type type = ctrl_data->alloc_type(); + if(type == anonymous_type){ + BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) || + (type == unique_type && ctrl_data->m_num_char != 0) ); + return 0; + } + CharType *name = static_cast(ctrl_data->template name()); + + //Sanity checks + BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType)); + BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits::length(name)); + return name; + } + + static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue) + { + //Get header + BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0); + return ctrl_data->value_bytes()/sizeofvalue; + } + + //!Returns is the the name of an object created with construct/find_or_construct + //!functions. Does not throw + static instance_type priv_get_instance_type(block_header_t *ctrl_data) + { + //Get header + BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type); + return (instance_type)ctrl_data->alloc_type(); + } + + static size_type priv_get_reserved_bytes() + { + //Get the number of bytes until the end of (*this) + //beginning in the end of the segment_manager_base_t base. + return sizeof(segment_manager) - sizeof(segment_manager_base_t); + } + + template + void *priv_generic_find + (const CharT* name, + IndexType > &index, + ipcdetail::in_place_interface &table, + size_type &length, ipcdetail::true_ is_intrusive, bool use_lock) + { + (void)is_intrusive; + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; + + //------------------------------- + scoped_lock guard(priv_get_lock(use_lock)); + //------------------------------- + //Find name in index + ipcdetail::intrusive_compare_key key + (name, std::char_traits::length(name)); + index_it it = index.find(key); + + //Initialize return values + void *ret_ptr = 0; + length = 0; + + //If found, assign values + if(it != index.end()){ + //Get header + block_header_t *ctrl_data = it->get_block_header(); + + //Sanity check + BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); + BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT)); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; + } + return ret_ptr; + } + + template + void *priv_generic_find + (const CharT* name, + IndexType > &index, + ipcdetail::in_place_interface &table, + size_type &length, ipcdetail::false_ is_intrusive, bool use_lock) + { + (void)is_intrusive; + typedef IndexType > char_aware_index_type; + typedef typename char_aware_index_type::key_type key_type; + typedef typename char_aware_index_type::iterator index_it; + + //------------------------------- + scoped_lock guard(priv_get_lock(use_lock)); + //------------------------------- + //Find name in index + index_it it = index.find(key_type(name, std::char_traits::length(name))); + + //Initialize return values + void *ret_ptr = 0; + length = 0; + + //If found, assign values + if(it != index.end()){ + //Get header + block_header_t *ctrl_data = reinterpret_cast + (ipcdetail::to_raw_pointer(it->second.m_ptr)); + + //Sanity check + BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); + BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT)); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; + } + return ret_ptr; + } + + template + bool priv_generic_named_destroy + (block_header_t *block_header, + IndexType > &index, + ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index) + { + (void)is_node_index; + typedef typename IndexType >::iterator index_it; + + index_it *ihdr = block_header_t::template to_first_header(block_header); + return this->priv_generic_named_destroy_impl(*ihdr, index, table); + } + + template + bool priv_generic_named_destroy + (block_header_t *block_header, + IndexType > &index, + ipcdetail::in_place_interface &table, + ipcdetail::false_ is_node_index) + { + (void)is_node_index; + CharT *name = static_cast(block_header->template name()); + return this->priv_generic_named_destroy(name, index, table, is_intrusive_t()); + } + + template + bool priv_generic_named_destroy(const CharT *name, + IndexType > &index, + ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index) + { + (void)is_intrusive_index; + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; + typedef typename index_type_t::value_type intrusive_value_type; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Find name in index + ipcdetail::intrusive_compare_key key + (name, std::char_traits::length(name)); + index_it it = index.find(key); + + //If not found, return false + if(it == index.end()){ + //This name is not present in the index, wrong pointer or name! + //BOOST_ASSERT(0); + return false; + } + + block_header_t *ctrl_data = it->get_block_header(); + intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data); + void *memory = iv; + void *values = ctrl_data->value(); + std::size_t num = ctrl_data->m_value_bytes/table.size; + + //Sanity check + BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); + BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); + + //Erase node from index + index.erase(it); + + //Destroy the headers + ctrl_data->~block_header_t(); + iv->~intrusive_value_type(); + + //Call destructors and free memory + table.destroy_n(values, num); + this->deallocate(memory); + return true; + } + + template + bool priv_generic_named_destroy(const CharT *name, + IndexType > &index, + ipcdetail::in_place_interface &table, + ipcdetail::false_ is_intrusive_index) + { + (void)is_intrusive_index; + typedef IndexType > char_aware_index_type; + typedef typename char_aware_index_type::iterator index_it; + typedef typename char_aware_index_type::key_type key_type; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Try to find the name in the index + index_it it = index.find(key_type (name, + std::char_traits::length(name))); + + //If not found, return false + if(it == index.end()){ + //This name is not present in the index, wrong pointer or name! + //BOOST_ASSERT(0); + return false; + } + return this->priv_generic_named_destroy_impl(it, index, table); + } + + template + bool priv_generic_named_destroy_impl + (const typename IndexType >::iterator &it, + IndexType > &index, + ipcdetail::in_place_interface &table) + { + typedef IndexType > char_aware_index_type; + typedef typename char_aware_index_type::iterator index_it; + + //Get allocation parameters + block_header_t *ctrl_data = reinterpret_cast + (ipcdetail::to_raw_pointer(it->second.m_ptr)); + char *stored_name = static_cast(static_cast(const_cast(it->first.name()))); + (void)stored_name; + + //Check if the distance between the name pointer and the memory pointer + //is correct (this can detect incorrect type in destruction) + std::size_t num = ctrl_data->m_value_bytes/table.size; + void *values = ctrl_data->value(); + + //Sanity check + BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); + BOOST_ASSERT(static_cast(stored_name) == static_cast(ctrl_data->template name())); + BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); + + //Erase node from index + index.erase(it); + + //Destroy the header + ctrl_data->~block_header_t(); + + void *memory; + if(is_node_index_t::value){ + index_it *ihdr = block_header_t::template + to_first_header(ctrl_data); + ihdr->~index_it(); + memory = ihdr; + } + else{ + memory = ctrl_data; + } + + //Call destructors and free memory + table.destroy_n(values, num); + this->deallocate(memory); + return true; + } + + template + void * priv_generic_named_construct + (unsigned char type, const CharT *name, size_type num, bool try2find, + bool dothrow, ipcdetail::in_place_interface &table, + IndexType > &index, ipcdetail::true_ is_intrusive) + { + (void)is_intrusive; + std::size_t namelen = std::char_traits::length(name); + + block_header_t block_info ( size_type(table.size*num) + , size_type(table.alignment) + , type + , sizeof(CharT) + , namelen); + + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; + typedef std::pair index_ib; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Insert the node. This can throw. + //First, we want to know if the key is already present before + //we allocate any memory, and if the key is not present, we + //want to allocate all memory in a single buffer that will + //contain the name and the user buffer. + // + //Since equal_range(key) + insert(hint, value) approach is + //quite inefficient in container implementations + //(they re-test if the position is correct), I've chosen + //to insert the node, do an ugly un-const cast and modify + //the key (which is a smart pointer) to an equivalent one + index_ib insert_ret; + + typename index_type_t::insert_commit_data commit_data; + typedef typename index_type_t::value_type intrusive_value_type; + + BOOST_TRY{ + ipcdetail::intrusive_compare_key key(name, namelen); + insert_ret = index.insert_check(key, commit_data); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW + return 0; + } + BOOST_CATCH_END + + index_it it = insert_ret.first; + + //If found and this is find or construct, return data + //else return null + if(!insert_ret.second){ + if(try2find){ + return it->get_block_header()->value(); + } + if(dothrow){ + throw interprocess_exception(already_exists_error); + } + else{ + return 0; + } + } + + //Allocates buffer for name + data, this can throw (it hurts) + void *buffer_ptr; + + //Check if there is enough memory + if(dothrow){ + buffer_ptr = this->allocate + (block_info.template total_size_with_header()); + } + else{ + buffer_ptr = this->allocate + (block_info.template total_size_with_header(), nothrow<>::get()); + if(!buffer_ptr) + return 0; + } + + //Now construct the intrusive hook plus the header + intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type(); + block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t())block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Copy name to memory segment and insert data + CharT *name_ptr = static_cast(hdr->template name()); + std::char_traits::copy(name_ptr, name, namelen+1); + + BOOST_TRY{ + //Now commit the insertion using previous context data + it = index.insert_commit(*intrusive_hdr, commit_data); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW + return 0; + } + BOOST_CATCH_END + + //Avoid constructions if constructor is trivial + //Build scoped ptr to avoid leaks with constructor exception + ipcdetail::mem_algo_deallocator mem + (buffer_ptr, *static_cast(this)); + + //Initialize the node value_eraser to erase inserted node + //if something goes wrong. This will be executed *before* + //the memory allocation as the intrusive value is built in that + //memory + value_eraser v_eraser(index, it); + + //Construct array, this can throw + table.construct_n(ptr, num); + + //Release rollbacks since construction was successful + v_eraser.release(); + mem.release(); + return ptr; + } + + //!Generic named new function for + //!named functions + template + void * priv_generic_named_construct + (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow, + ipcdetail::in_place_interface &table, + IndexType > &index, ipcdetail::false_ is_intrusive) + { + (void)is_intrusive; + std::size_t namelen = std::char_traits::length(name); + + block_header_t block_info ( size_type(table.size*num) + , size_type(table.alignment) + , type + , sizeof(CharT) + , namelen); + + typedef IndexType > index_type_t; + typedef typename index_type_t::key_type key_type; + typedef typename index_type_t::mapped_type mapped_type; + typedef typename index_type_t::value_type value_type; + typedef typename index_type_t::iterator index_it; + typedef std::pair index_ib; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Insert the node. This can throw. + //First, we want to know if the key is already present before + //we allocate any memory, and if the key is not present, we + //want to allocate all memory in a single buffer that will + //contain the name and the user buffer. + // + //Since equal_range(key) + insert(hint, value) approach is + //quite inefficient in container implementations + //(they re-test if the position is correct), I've chosen + //to insert the node, do an ugly un-const cast and modify + //the key (which is a smart pointer) to an equivalent one + index_ib insert_ret; + BOOST_TRY{ + insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0))); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW; + return 0; + } + BOOST_CATCH_END + + index_it it = insert_ret.first; + + //If found and this is find or construct, return data + //else return null + if(!insert_ret.second){ + if(try2find){ + block_header_t *hdr = static_cast + (ipcdetail::to_raw_pointer(it->second.m_ptr)); + return hdr->value(); + } + return 0; + } + //Initialize the node value_eraser to erase inserted node + //if something goes wrong + value_eraser v_eraser(index, it); + + //Allocates buffer for name + data, this can throw (it hurts) + void *buffer_ptr; + block_header_t * hdr; + + //Allocate and construct the headers + if(is_node_index_t::value){ + size_type total_size = block_info.template total_size_with_header(); + if(dothrow){ + buffer_ptr = this->allocate(total_size); + } + else{ + buffer_ptr = this->allocate(total_size, nothrow<>::get()); + if(!buffer_ptr) + return 0; + } + index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it); + hdr = block_header_t::template from_first_header(idr); + } + else{ + if(dothrow){ + buffer_ptr = this->allocate(block_info.total_size()); + } + else{ + buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get()); + if(!buffer_ptr) + return 0; + } + hdr = static_cast(buffer_ptr); + } + + hdr = ::new(hdr, boost_container_new_t())block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Copy name to memory segment and insert data + CharT *name_ptr = static_cast(hdr->template name()); + std::char_traits::copy(name_ptr, name, namelen+1); + + //Do the ugly cast, please mama, forgive me! + //This new key points to an identical string, so it must have the + //same position than the overwritten key according to the predicate + const_cast(it->first).name(name_ptr); + it->second.m_ptr = hdr; + + //Build scoped ptr to avoid leaks with constructor exception + ipcdetail::mem_algo_deallocator mem + (buffer_ptr, *static_cast(this)); + + //Construct array, this can throw + table.construct_n(ptr, num); + + //All constructors successful, we don't want to release memory + mem.release(); + + //Release node v_eraser since construction was successful + v_eraser.release(); + return ptr; + } + + private: + //!Returns the this pointer + segment_manager *get_this_pointer() + { return this; } + + typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex; + + scoped_lock priv_get_lock(bool use_lock) + { + scoped_lock local(m_header, defer_lock); + if(use_lock){ + local.lock(); + } + return scoped_lock(boost::move(local)); + } + + //!This struct includes needed data and derives from + //!rmutex to allow EBO when using null interprocess_mutex + struct header_t + : public rmutex + { + named_index_t m_named_index; + unique_index_t m_unique_index; + + header_t(segment_manager_base_t *segment_mngr_base) + : m_named_index (segment_mngr_base) + , m_unique_index(segment_mngr_base) + {} + } m_header; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + + +}} //namespace boost { namespace interprocess + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP + diff --git a/extern/boost/boost/interprocess/smart_ptr/deleter.hpp b/extern/boost/boost/interprocess/smart_ptr/deleter.hpp new file mode 100644 index 00000000000..bc0f8c8aaf5 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/deleter.hpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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_DELETER_HPP +#define BOOST_INTERPROCESS_DELETER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include + +//!\file +//!Describes the functor to delete objects from the segment. + +namespace boost { +namespace interprocess { + +//!A deleter that uses the segment manager's destroy_ptr +//!function to destroy the passed pointer resource. +//! +//!This deleter is used +template +class deleter +{ + public: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + + private: + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type segment_manager_pointer; + + segment_manager_pointer mp_mngr; + + public: + deleter(segment_manager_pointer pmngr) BOOST_NOEXCEPT + : mp_mngr(pmngr) + {} + + void operator()(const pointer &p) + { mp_mngr->destroy_ptr(ipcdetail::to_raw_pointer(p)); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DELETER_HPP diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp new file mode 100644 index 00000000000..e2ce9a78d87 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/detail/bad_weak_ptr.hpp +// +// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006. 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_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#ifndef BOOST_NO_EXCEPTIONS +#include +#endif + +namespace boost{ +namespace interprocess{ + +class bad_weak_ptr + : public std::exception +{ + public: + + virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE + { return "boost::interprocess::bad_weak_ptr"; } +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp new file mode 100644 index 00000000000..9b0244e4230 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -0,0 +1,347 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/detail/shared_count.hpp +// +// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 +// (C) Copyright Peter Dimov 2004-2005 +// (C) Copyright Ion Gaztanaga 2006-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_SHARED_COUNT_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include //std::less +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +template +class weak_count; + +template +class shared_count +{ + public: + + typedef typename boost::container:: + allocator_traits::pointer void_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + + private: + typedef sp_counted_impl_pd counted_impl; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type counted_impl_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type counted_base_ptr; + + typedef boost::container::allocator_traits vallocator_traits; + + typedef typename vallocator_traits::template + portable_rebind_alloc::type counted_impl_allocator; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_deleter_pointer; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_allocator_pointer; + + pointer m_px; + counted_impl_ptr m_pi; + + template + friend class weak_count; + + template + friend class shared_count; + + public: + + shared_count() + : m_px(0), m_pi(0) // nothrow + {} + + template + shared_count(const shared_count &other_shared_count, const Ptr &p) + : m_px(p), m_pi(other_shared_count.m_pi) + {} + + template + shared_count(const Ptr &p, const VoidAllocator &a, Deleter d) + : m_px(p), m_pi(0) + { + BOOST_TRY{ + if(p){ + counted_impl_allocator alloc(a); + m_pi = alloc.allocate(1); + //Anti-exception deallocator + scoped_ptr > + deallocator(m_pi, alloc); + //It's more correct to use VoidAllocator::construct but + //this needs copy constructor and we don't like it + ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d); + deallocator.release(); + } + } + BOOST_CATCH (...){ + d(p); // delete p + BOOST_RETHROW + } + BOOST_CATCH_END + } + + ~shared_count() // nothrow + { + if(m_pi) + m_pi->release(); + } + + shared_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template + explicit shared_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template + explicit shared_count(const pointer & ptr, shared_count const & r) + : m_px(ptr), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + +/* + explicit shared_count(weak_count const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + boost::throw_exception( boost::interprocess::bad_weak_ptr() ); + } + } +*/ + template + explicit shared_count(weak_count const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_px(r.m_px), m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + throw( boost::interprocess::bad_weak_ptr() ); + } + } + + const pointer &to_raw_pointer() const + { return m_px; } + + pointer &to_raw_pointer() + { return m_px; } + + shared_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + template + shared_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + void swap(shared_count & r) // nothrow + { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count(): 0; } + + bool unique() const // nothrow + { return use_count() == 1; } + + const_deleter_pointer get_deleter() const + { return m_pi ? m_pi->get_deleter() : 0; } + +// const_allocator_pointer get_allocator() const +// { return m_pi ? m_pi->get_allocator() : 0; } + + template + bool internal_equal (shared_count const & other) const + { return this->m_pi == other.m_pi; } + + template + bool internal_less (shared_count const & other) const + { return std::less()(this->m_pi, other.m_pi); } +}; + +template inline +bool operator==(shared_count const & a, shared_count const & b) +{ return a.internal_equal(b); } + +template inline +bool operator<(shared_count const & a, shared_count const & b) +{ return a.internal_less(b); } + + +template +class weak_count +{ + public: + typedef typename boost::container:: + allocator_traits::pointer void_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + + private: + + typedef sp_counted_impl_pd counted_impl; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type counted_impl_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type counted_base_ptr; + + pointer m_px; + counted_impl_ptr m_pi; + + template + friend class weak_count; + + template + friend class shared_count; + + public: + + weak_count(): m_px(0), m_pi(0) // nothrow + {} + + template + explicit weak_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + weak_count(weak_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + template + weak_count(weak_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + ~weak_count() // nothrow + { if(m_pi != 0) m_pi->weak_release(); } + + template + weak_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void set_pointer(const pointer &ptr) + { m_px = ptr; } + + template + weak_count & operator= (weak_count const& r) // nothrow + { + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void swap(weak_count & r) // nothrow + { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count() : 0; } + + template + bool internal_equal (weak_count const & other) const + { return this->m_pi == other.m_pi; } + + template + bool internal_less (weak_count const & other) const + { return std::less()(this->m_pi, other.m_pi); } +}; + +template inline +bool operator==(weak_count const & a, weak_count const & b) +{ return a.internal_equal(b); } + +template inline +bool operator<(weak_count const & a, weak_count const & b) +{ return a.internal_less(b); } + +} // namespace ipcdetail +} // namespace interprocess +} // namespace boost + + +#include + + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp new file mode 100644 index 00000000000..3b6a0876f92 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp @@ -0,0 +1,26 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +# include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp new file mode 100644 index 00000000000..50392741d0e --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp @@ -0,0 +1,94 @@ +#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2007-2012 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include +#include + +#include +#include + +namespace boost { + +namespace interprocess { + +namespace ipcdetail { + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + boost::uint32_t use_count_; // #shared + boost::uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + {} + + ~sp_counted_base() // nothrow + {} + + void add_ref_copy() + { + ipcdetail::atomic_inc32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + boost::uint32_t tmp = static_cast< boost::uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( ipcdetail::atomic_cas32( &use_count_, tmp + 1, tmp ) == tmp ) + return true; + } + } + + bool ref_release() // nothrow + { return 1 == ipcdetail::atomic_dec32( &use_count_ ); } + + void weak_add_ref() // nothrow + { ipcdetail::atomic_inc32( &weak_count_ ); } + + bool weak_release() // nothrow + { return 1 == ipcdetail::atomic_dec32( &weak_count_ ); } + + long use_count() const // nothrow + { return (long)static_cast( use_count_ ); } +}; + +} // namespace ipcdetail + +} // namespace interprocess + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp new file mode 100644 index 00000000000..ed1d72706f4 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp @@ -0,0 +1,164 @@ +#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +// +// This file is the adaptation for shared memory memory mapped +// files of boost/detail/sp_counted_impl.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 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) +// + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace interprocess { + +namespace ipcdetail { + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an object using a STL allocator. +template +struct scoped_ptr_dealloc_functor +{ + typedef typename boost::container:: + allocator_traits::pointer pointer; + + typedef ipcdetail::integral_constant::value> alloc_version; + typedef ipcdetail::integral_constant allocator_v1; + typedef ipcdetail::integral_constant allocator_v2; + + private: + void priv_deallocate(const pointer &p, allocator_v1) + { m_alloc.deallocate(p, 1); } + + void priv_deallocate(const pointer &p, allocator_v2) + { m_alloc.deallocate_one(p); } + + public: + Allocator& m_alloc; + + scoped_ptr_dealloc_functor(Allocator& a) + : m_alloc(a) {} + + void operator()(pointer ptr) + { if (ptr) priv_deallocate(ptr, alloc_version()); } +}; + + + +template +class sp_counted_impl_pd + : public sp_counted_base + , boost::container::allocator_traits::template + portable_rebind_alloc< sp_counted_impl_pd >::type + , D // copy constructor must not throw +{ + private: + typedef sp_counted_impl_pd this_type; + typedef typename boost::container:: + allocator_traits::template + portable_rebind_alloc + < this_type >::type this_allocator; + typedef typename boost::container:: + allocator_traits::template + portable_rebind_alloc + < const this_type >::type const_this_allocator; + typedef typename boost::container:: + allocator_traits + ::pointer this_pointer; + typedef typename boost::container:: + allocator_traits::pointer a_pointer; + typedef typename boost::intrusive:: + pointer_traits this_pointer_traits; + + sp_counted_impl_pd( sp_counted_impl_pd const & ); + sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_deleter_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_allocator_pointer; + + typedef typename D::pointer pointer; + pointer m_ptr; + + public: + // pre: d(p) must not throw + template + sp_counted_impl_pd(const Ptr & p, const A &a, const D &d ) + : this_allocator(a), D(d), m_ptr(p) + {} + + const_deleter_pointer get_deleter() const + { return const_deleter_pointer(&static_cast(*this)); } + + const_allocator_pointer get_allocator() const + { return const_allocator_pointer(&static_cast(*this)); } + + void dispose() // nothrow + { static_cast(*this)(m_ptr); } + + void destroy() // nothrow + { + //Self destruction, so move the allocator + this_allocator a_copy(::boost::move(static_cast(*this))); + BOOST_ASSERT(a_copy == *this); + this_pointer this_ptr(this_pointer_traits::pointer_to(*this)); + //Do it now! + scoped_ptr< this_type, scoped_ptr_dealloc_functor > + deleter_ptr(this_ptr, a_copy); + ipcdetail::to_raw_pointer(this_ptr)->~this_type(); + } + + void release() // nothrow + { + if(this->ref_release()){ + this->dispose(); + this->weak_release(); + } + } + + void weak_release() // nothrow + { + if(sp_counted_base::weak_release()){ + this->destroy(); + } + } +}; + + +} // namespace ipcdetail + +} // namespace interprocess + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp new file mode 100644 index 00000000000..188b68d6784 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp @@ -0,0 +1,87 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp +// +// (C) Copyright Peter Dimov 2002 +// (C) Copyright Ion Gaztanaga 2006-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_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +//!\file +//!Describes an utility to form a shared pointer from this + +namespace boost{ +namespace interprocess{ + +//!This class is used as a base class that allows a shared_ptr to the current +//!object to be obtained from within a member function. +//!enable_shared_from_this defines two member functions called shared_from_this +//!that return a shared_ptr and shared_ptr, depending on constness, to this. +template +class enable_shared_from_this +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + protected: + enable_shared_from_this() + {} + + enable_shared_from_this(enable_shared_from_this const &) + {} + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { return *this; } + + ~enable_shared_from_this() + {} + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + shared_ptr shared_from_this() + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(ipcdetail::to_raw_pointer(p.get()) == this); + return p; + } + + shared_ptr shared_from_this() const + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(ipcdetail::to_raw_pointer(p.get()) == this); + return p; + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef T element_type; + mutable weak_ptr _internal_weak_this; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + diff --git a/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp new file mode 100644 index 00000000000..585b9952d52 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp @@ -0,0 +1,333 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp +// +// (C) Copyright Peter Dimov 2001, 2002 +// (C) Copyright Ion Gaztanaga 2006-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_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +//!\file +//!Describes an intrusive ownership pointer. + +#include +#include + +#include +#include +#include +#include +#include + +#include // for std::basic_ostream + +#include //std::less + +namespace boost { +namespace interprocess { + +//!The intrusive_ptr class template stores a pointer to an object +//!with an embedded reference count. intrusive_ptr is parameterized on +//!T (the type of the object pointed to) and VoidPointer(a void pointer type +//!that defines the type of pointer that intrusive_ptr will store). +//!intrusive_ptr defines a class with a T* member whereas +//!intrusive_ptr > defines a class with a offset_ptr member. +//!Relies on unqualified calls to: +//! +//! void intrusive_ptr_add_ref(T * p) BOOST_NOEXCEPT; +//! void intrusive_ptr_release(T * p) BOOST_NOEXCEPT; +//! +//! with (p != 0) +//! +//!The object is responsible for destroying itself. +template +class intrusive_ptr +{ + public: + //!Provides the type of the internal stored pointer. + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + //!Provides the type of the stored pointer. + typedef T element_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef VoidPointer VP; + typedef intrusive_ptr this_type; + typedef pointer this_type::*unspecified_bool_type; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + BOOST_COPYABLE_AND_MOVABLE(intrusive_ptr) + + public: + //!Constructor. Initializes internal pointer to 0. + //!Does not throw + intrusive_ptr() BOOST_NOEXCEPT + : m_ptr(0) + {} + + //!Constructor. Copies pointer and if "p" is not zero and + //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)). + //!Does not throw + intrusive_ptr(const pointer &p, bool add_ref = true) BOOST_NOEXCEPT + : m_ptr(p) + { + if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); + } + + //!Copy constructor. Copies the internal pointer and if "p" is not + //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw + intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT + : m_ptr(rhs.m_ptr) + { + if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); + } + + //!Move constructor. Moves the internal pointer. Does not throw + intrusive_ptr(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT + : m_ptr(rhs.m_ptr) + { + rhs.m_ptr = 0; + } + + //!Constructor from related. Copies the internal pointer and if "p" is not + //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw + template intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT + : m_ptr(rhs.get()) + { + if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); + } + + //!Destructor. Calls reset(). Does not throw + ~intrusive_ptr() + { + reset(); + } + + //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + intrusive_ptr & operator=(BOOST_COPY_ASSIGN_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT + { + this_type(rhs).swap(*this); + return *this; + } + + //!Move Assignment operator + //!Does not throw + intrusive_ptr & operator=(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT + { + rhs.swap(*this); + rhs.reset(); + return *this; + } + + //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + template intrusive_ptr & operator=(intrusive_ptr const & rhs) BOOST_NOEXCEPT + { + this_type(rhs).swap(*this); + return *this; + } + + //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + intrusive_ptr & operator=(pointer rhs) BOOST_NOEXCEPT + { + this_type(rhs).swap(*this); + return *this; + } + + //!Release internal pointer and set it to 0. If internal pointer is not 0, calls + //!intrusive_ptr_release(to_raw_pointer(m_ptr)). Does not throw + void reset() BOOST_NOEXCEPT { + if(m_ptr != 0) { + pointer ptr = m_ptr; + m_ptr = 0; + intrusive_ptr_release(ipcdetail::to_raw_pointer(ptr)); + } + } + + //!Returns a reference to the internal pointer. + //!Does not throw + pointer &get() BOOST_NOEXCEPT + { return m_ptr; } + + //!Returns a reference to the internal pointer. + //!Does not throw + const pointer &get() const BOOST_NOEXCEPT + { return m_ptr; } + + //!Returns *get(). + //!Does not throw + T & operator*() const BOOST_NOEXCEPT + { return *m_ptr; } + + //!Returns *get(). + //!Does not throw + const pointer &operator->() const BOOST_NOEXCEPT + { return m_ptr; } + + //!Returns get(). + //!Does not throw + pointer &operator->() BOOST_NOEXCEPT + { return m_ptr; } + + //!Conversion to boolean. + //!Does not throw + operator unspecified_bool_type () const BOOST_NOEXCEPT + { return m_ptr == 0? 0: &this_type::m_ptr; } + + //!Not operator. + //!Does not throw + bool operator! () const BOOST_NOEXCEPT + { return m_ptr == 0; } + + //!Exchanges the contents of the two smart pointers. + //!Does not throw + void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT + { ::boost::adl_move_swap(m_ptr, rhs.m_ptr); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + pointer m_ptr; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Returns a.get() == b.get(). +//!Does not throw +template inline +bool operator==(intrusive_ptr const & a, + intrusive_ptr const & b) BOOST_NOEXCEPT +{ return a.get() == b.get(); } + +//!Returns a.get() != b.get(). +//!Does not throw +template inline +bool operator!=(intrusive_ptr const & a, + intrusive_ptr const & b) BOOST_NOEXCEPT +{ return a.get() != b.get(); } + +//!Returns a.get() == b. +//!Does not throw +template inline +bool operator==(intrusive_ptr const & a, + const typename intrusive_ptr::pointer &b) BOOST_NOEXCEPT +{ return a.get() == b; } + +//!Returns a.get() != b. +//!Does not throw +template inline +bool operator!=(intrusive_ptr const & a, + const typename intrusive_ptr::pointer &b) BOOST_NOEXCEPT +{ return a.get() != b; } + +//!Returns a == b.get(). +//!Does not throw +template inline +bool operator==(const typename intrusive_ptr::pointer &a, + intrusive_ptr const & b) BOOST_NOEXCEPT +{ return a == b.get(); } + +//!Returns a != b.get(). +//!Does not throw +template inline +bool operator!=(const typename intrusive_ptr::pointer &a, + intrusive_ptr const & b) BOOST_NOEXCEPT +{ return a != b.get(); } + +//!Returns a.get() < b.get(). +//!Does not throw +template inline +bool operator<(intrusive_ptr const & a, + intrusive_ptr const & b) BOOST_NOEXCEPT +{ + return std::less::pointer>() + (a.get(), b.get()); +} + +//!Exchanges the contents of the two intrusive_ptrs. +//!Does not throw +template inline +void swap(intrusive_ptr & lhs, + intrusive_ptr & rhs) BOOST_NOEXCEPT +{ lhs.swap(rhs); } + +// operator<< +template +inline std::basic_ostream & operator<< + (std::basic_ostream & os, intrusive_ptr const & p) BOOST_NOEXCEPT +{ os << p.get(); return os; } + +//!Returns p.get(). +//!Does not throw +template +inline typename boost::interprocess::intrusive_ptr::pointer + to_raw_pointer(intrusive_ptr p) BOOST_NOEXCEPT +{ return p.get(); } + +/*Emulates static cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr static_pointer_cast + (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT +{ return do_static_cast(p.get()); } +*/ +/*Emulates const cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr const_pointer_cast + (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT +{ return do_const_cast(p.get()); } +*/ + +/*Emulates dynamic cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr dynamic_pointer_cast + (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT +{ return do_dynamic_cast(p.get()); } +*/ + +/*Emulates reinterpret cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptrreinterpret_pointer_cast + (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT +{ return do_reinterpret_cast(p.get()); } +*/ + +} // namespace interprocess + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +//!Returns p.get(). +//!Does not throw +template +inline T *to_raw_pointer(boost::interprocess::intrusive_ptr p) BOOST_NOEXCEPT +{ return p.get(); } +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp new file mode 100644 index 00000000000..f480428ca89 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp @@ -0,0 +1,176 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/scoped_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// (C) Copyright Peter Dimov 2001, 2002 +// (C) Copyright Ion Gaztanaga 2006-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_SCOPED_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the smart pointer scoped_ptr + +namespace boost { +namespace interprocess { + +//!scoped_ptr stores a pointer to a dynamically allocated object. +//!The object pointed to is guaranteed to be deleted, either on destruction +//!of the scoped_ptr, or via an explicit reset. The user can avoid this +//!deletion using release(). +//!scoped_ptr is parameterized on T (the type of the object pointed to) and +//!Deleter (the functor to be executed to delete the internal pointer). +//!The internal pointer will be of the same pointer type as typename +//!Deleter::pointer type (that is, if typename Deleter::pointer is +//!offset_ptr, the internal pointer will be offset_ptr). +template +class scoped_ptr + : private Deleter +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + typedef typename ipcdetail::add_reference::type reference; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + + typedef T element_type; + typedef Deleter deleter_type; + typedef typename ipcdetail::pointer_type::type pointer; + + //!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d. + //!Does not throw. + explicit scoped_ptr(const pointer &p = 0, const Deleter &d = Deleter()) + : Deleter(d), m_ptr(p) // throws if pointer/Deleter copy ctor throws + {} + + //!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. + //!calling the operator() of the stored deleter. Never throws + ~scoped_ptr() + { + if(m_ptr){ + Deleter &del = static_cast(*this); + del(m_ptr); + } + } + + //!Deletes the object pointed to by the stored pointer and then + //!stores a copy of p. Never throws + void reset(const pointer &p = 0) // never throws + { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p).swap(*this); } + + //!Deletes the object pointed to by the stored pointer and then + //!stores a copy of p and a copy of d. + void reset(const pointer &p, const Deleter &d) // never throws + { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p, d).swap(*this); } + + //!Assigns internal pointer as 0 and returns previous pointer. This will + //!avoid deletion on destructor + 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 BOOST_NOEXCEPT + { BOOST_ASSERT(m_ptr != 0); return *m_ptr; } + + //!Returns the internal stored pointer. + //!Never throws. + pointer &operator->() BOOST_NOEXCEPT + { BOOST_ASSERT(m_ptr != 0); return m_ptr; } + + //!Returns the internal stored pointer. + //!Never throws. + const pointer &operator->() const BOOST_NOEXCEPT + { BOOST_ASSERT(m_ptr != 0); return m_ptr; } + + //!Returns the stored pointer. + //!Never throws. + pointer & get() BOOST_NOEXCEPT + { return m_ptr; } + + //!Returns the stored pointer. + //!Never throws. + 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 BOOST_NOEXCEPT + { return m_ptr == 0? 0: &this_type::m_ptr; } + + //!Returns true if the stored pointer is 0. + //!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) BOOST_NOEXCEPT // never throws + { + ::boost::adl_move_swap(static_cast(*this), static_cast(b)); + ::boost::adl_move_swap(m_ptr, b.m_ptr); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + pointer m_ptr; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!Exchanges the internal pointer and deleter with other scoped_ptr +//!Never throws. +template inline +void swap(scoped_ptr & a, scoped_ptr & b) BOOST_NOEXCEPT +{ a.swap(b); } + +//!Returns a copy of the stored pointer +//!Never throws +template inline +typename scoped_ptr::pointer to_raw_pointer(scoped_ptr const & p) +{ return p.get(); } + +} // namespace interprocess + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +template inline +T *to_raw_pointer(boost::interprocess::scoped_ptr const & p) +{ return p.get(); } +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp new file mode 100644 index 00000000000..7633bd5de73 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp @@ -0,0 +1,430 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// (C) Copyright Peter Dimov 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006-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_SHARED_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for std::basic_ostream + +//!\file +//!Describes the smart pointer shared_ptr + +namespace boost{ +namespace interprocess{ + +template class weak_ptr; +template class enable_shared_from_this; + +namespace ipcdetail{ + +template +inline void sp_enable_shared_from_this + (shared_count const & pn + ,enable_shared_from_this const*pe + ,T *ptr) + +{ + (void)ptr; + if(pe != 0){ + pe->_internal_weak_this._internal_assign(pn); + } +} + +template +inline void sp_enable_shared_from_this(shared_count const &, ...) +{} + +} // namespace ipcdetail + +//!shared_ptr stores a pointer to a dynamically allocated object. +//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to +//!it is destroyed or reset. +//! +//!shared_ptr is parameterized on +//!T (the type of the object pointed to), VoidAllocator (the void allocator to be used +//!to allocate the auxiliary data) and Deleter (the deleter whose +//!operator() will be used to delete the object. +//! +//!The internal pointer will be of the same pointer type as typename +//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is +//!offset_ptr, the internal pointer will be offset_ptr). +//! +//!Because the implementation uses reference counting, cycles of shared_ptr +//!instances will not be reclaimed. For example, if main() holds a +//!shared_ptr to A, which directly or indirectly holds a shared_ptr back +//!to A, A's use count will be 2. Destruction of the original shared_ptr +//!will leave A dangling with a use count of 1. +//!Use weak_ptr to "break cycles." +template +class shared_ptr +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef shared_ptr this_type; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + + typedef T element_type; + typedef T value_type; + typedef typename boost::container:: + allocator_traits::pointer void_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_deleter_pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_allocator_pointer; + + BOOST_COPYABLE_AND_MOVABLE(shared_ptr) + public: + + //!Constructs an empty shared_ptr. + //!Use_count() == 0 && get()== 0. + shared_ptr() + : m_pn() // never throws + {} + + //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated + //!with a copy of a and the object will be deleted with a copy of d. + //!Requirements: Deleter and A's copy constructor must not throw. + explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) + : m_pn(p, a, d) + { + //Check that the pointer passed is of the same type that + //the pointer the allocator defines or it's a raw pointer + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type ParameterPointer; + + BOOST_STATIC_ASSERT((ipcdetail::is_same::value) || + (ipcdetail::is_pointer::value)); + ipcdetail::sp_enable_shared_from_this( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) ); + } + + //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs + //!a shared_ptr that shares ownership with r. Never throws. + shared_ptr(const shared_ptr &r) + : m_pn(r.m_pn) // never throws + {} + + //!Constructs a shared_ptr that shares ownership with other and stores p. + //!Postconditions: get() == p && use_count() == r.use_count(). + //!Throws: nothing. + shared_ptr(const shared_ptr &other, const pointer &p) + : m_pn(other.m_pn, p) + {} + + //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs + //!a shared_ptr that shares ownership with r. Never throws. + template + shared_ptr(shared_ptr const & r) + : m_pn(r.m_pn) // never throws + {} + + //!Constructs a shared_ptr that shares ownership with r and stores + //!a copy of the pointer stored in r. + template + explicit shared_ptr(weak_ptr const & r) + : m_pn(r.m_pn) // may throw + {} + + //!Move-Constructs a shared_ptr that takes ownership of other resource and + //!other is put in default-constructed state. + //!Throws: nothing. + explicit shared_ptr(BOOST_RV_REF(shared_ptr) other) + : m_pn() + { this->swap(other); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + template + shared_ptr(shared_ptr const & r, ipcdetail::static_cast_tag) + : m_pn( pointer(static_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) + , r.m_pn) + {} + + template + shared_ptr(shared_ptr const & r, ipcdetail::const_cast_tag) + : m_pn( pointer(const_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) + , r.m_pn) + {} + + template + shared_ptr(shared_ptr const & r, ipcdetail::dynamic_cast_tag) + : m_pn( pointer(dynamic_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) + , r.m_pn) + { + if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed + m_pn = ipcdetail::shared_count(); + } + } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Equivalent to shared_ptr(r).swap(*this). + //!Never throws + template + shared_ptr & operator=(shared_ptr const & r) + { + m_pn = r.m_pn; // shared_count::op= doesn't throw + return *this; + } + + //!Equivalent to shared_ptr(r).swap(*this). + //!Never throws + shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r) + { + m_pn = r.m_pn; // shared_count::op= doesn't throw + return *this; + } + + //!Move-assignment. Equivalent to shared_ptr(other).swap(*this). + //!Never throws + shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws + { + this_type(other).swap(*this); + return *this; + } + + //!This is equivalent to: + //!this_type().swap(*this); + void reset() + { + this_type().swap(*this); + } + + //!This is equivalent to: + //!this_type(p, a, d).swap(*this); + template + void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) + { + //Check that the pointer passed is of the same type that + //the pointer the allocator defines or it's a raw pointer + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type ParameterPointer; + BOOST_STATIC_ASSERT((ipcdetail::is_same::value) || + (ipcdetail::is_pointer::value)); + this_type(p, a, d).swap(*this); + } + + template + void reset(shared_ptr const & r, const pointer &p) + { + this_type(r, p).swap(*this); + } + + //!Returns a reference to the + //!pointed type + reference operator* () const // never throws + { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); } + + //!Returns the pointer pointing + //!to the owned object + pointer operator-> () const // never throws + { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); } + + //!Returns the pointer pointing + //!to the owned object + pointer get() const // never throws + { return m_pn.to_raw_pointer(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + // implicit conversion to "bool" + void unspecified_bool_type_func() const {} + typedef void (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Not operator. + //!Returns true if this->get() != 0, false otherwise + bool operator! () const // never throws + { return !m_pn.to_raw_pointer(); } + + //!Returns use_count() == 1. + //!unique() might be faster than use_count() + bool unique() const // never throws + { return m_pn.unique(); } + + //!Returns the number of shared_ptr objects, *this included, + //!that share ownership with *this, or an unspecified nonnegative + //!value when *this is empty. + //!use_count() is not necessarily efficient. Use only for + //!debugging and testing purposes, not for production code. + long use_count() const // never throws + { return m_pn.use_count(); } + + //!Exchanges the contents of the two + //!smart pointers. + void swap(shared_ptr & other) // never throws + { m_pn.swap(other.m_pn); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + template + bool _internal_less(shared_ptr const & rhs) const + { return m_pn < rhs.m_pn; } + + const_deleter_pointer get_deleter() const + { return m_pn.get_deleter(); } + +// const_allocator_pointer get_allocator() const +// { return m_pn.get_allocator(); } + + private: + + template friend class shared_ptr; + template friend class weak_ptr; + + ipcdetail::shared_count m_pn; // reference counter + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; // shared_ptr + +template inline +bool operator==(shared_ptr const & a, shared_ptr const & b) +{ return a.get() == b.get(); } + +template inline +bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ return a.get() != b.get(); } + +template inline +bool operator<(shared_ptr const & a, shared_ptr const & b) +{ return a._internal_less(b); } + +template inline +void swap(shared_ptr & a, shared_ptr & b) +{ a.swap(b); } + +template inline +shared_ptr static_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, ipcdetail::static_cast_tag()); } + +template inline +shared_ptr const_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, ipcdetail::const_cast_tag()); } + +template inline +shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, ipcdetail::dynamic_cast_tag()); } + +// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr +template inline +T * to_raw_pointer(shared_ptr const & p) +{ return p.get(); } + +// operator<< +template inline +std::basic_ostream & operator<< + (std::basic_ostream & os, shared_ptr const & p) +{ os << p.get(); return os; } + +//!Returns the type of a shared pointer +//!of type T with the allocator boost::interprocess::allocator allocator +//!and boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_shared_ptr +{ + typedef typename ManagedMemory::template allocator::type void_allocator; + typedef typename ManagedMemory::template deleter::type deleter; + typedef shared_ptr< T, void_allocator, deleter> type; +}; + +//!Returns an instance of a shared pointer constructed +//!with the default allocator and deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +inline typename managed_shared_ptr::type + make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + return typename managed_shared_ptr::type + ( constructed_object + , managed_memory.template get_allocator() + , managed_memory.template get_deleter() + ); +} + +//!Returns an instance of a shared pointer constructed +//!with the default allocator and deleter from a pointer +//!of type T that has been allocated in the passed managed segment. +//!Does not throw, return null shared pointer in error. +template +inline typename managed_shared_ptr::type + make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &) +{ + BOOST_TRY{ + return typename managed_shared_ptr::type + ( constructed_object + , managed_memory.template get_allocator() + , managed_memory.template get_deleter() + ); + } + BOOST_CATCH(...){ + return typename managed_shared_ptr::type(); + } BOOST_CATCH_END +} + + +} // namespace interprocess + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr +template inline +T * to_raw_pointer(boost::interprocess::shared_ptr const & p) +{ return p.get(); } +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp new file mode 100644 index 00000000000..919b91d71b7 --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -0,0 +1,63 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2014. 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_UNIQUE_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +//!\file +//!This header provides utilities to define a unique_ptr that plays nicely with managed segments. + +namespace boost{ +namespace interprocess{ + +//For backwards compatibility +using ::boost::movelib::unique_ptr; + +//!Returns the type of a unique pointer +//!of type T with boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_unique_ptr +{ + typedef boost::movelib::unique_ptr + < T + , typename ManagedMemory::template deleter::type + > type; +}; + +//!Returns an instance of a unique pointer constructed +//!with boost::interproces::deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +inline typename managed_unique_ptr::type + make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + return typename managed_unique_ptr::type + (constructed_object, managed_memory.template get_deleter()); +} + +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp new file mode 100644 index 00000000000..e4873122d8e --- /dev/null +++ b/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -0,0 +1,271 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/weak_ptr.hpp +// +// (C) Copyright Peter Dimov 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006-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_WEAK_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the smart pointer weak_ptr. + +namespace boost{ +namespace interprocess{ + +//!The weak_ptr class template stores a "weak reference" to an object +//!that's already managed by a shared_ptr. To access the object, a weak_ptr +//!can be converted to a shared_ptr using the shared_ptr constructor or the +//!member function lock. When the last shared_ptr to the object goes away +//!and the object is deleted, the attempt to obtain a shared_ptr from the +//!weak_ptr instances that refer to the deleted object will fail: the constructor +//!will throw an exception of type bad_weak_ptr, and weak_ptr::lock will +//!return an empty shared_ptr. +//! +//!Every weak_ptr meets the CopyConstructible and Assignable requirements +//!of the C++ Standard Library, and so can be used in standard library containers. +//!Comparison operators are supplied so that weak_ptr works with the standard +//!library's associative containers. +//! +//!weak_ptr operations never throw exceptions. +//! +//!The class template is parameterized on T, the type of the object pointed to. +template +class weak_ptr +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + typedef typename boost::container:: + allocator_traits::pointer alloc_ptr; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + typedef T element_type; + typedef T value_type; + + //!Effects: Constructs an empty weak_ptr. + //!Postconditions: use_count() == 0. + weak_ptr() + : m_pn() // never throws + {} + // generated copy constructor, assignment, destructor are fine + // + // The "obvious" converting constructor implementation: + // + // template + // weak_ptr(weak_ptr const & r): m_px(r.m_px), m_pn(r.m_pn) // never throws + // { + // } + // + // has a serious problem. + // + // r.m_px may already have been invalidated. The m_px(r.m_px) + // conversion may require access to *r.m_px (virtual inheritance). + // + // It is not possible to avoid spurious access violations since + // in multithreaded programs r.m_px may be invalidated at any point. + + //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, + //!constructs a weak_ptr that shares ownership with r as if by storing a + //!copy of the pointer stored in r. + //! + //!Postconditions: use_count() == r.use_count(). + //! + //!Throws: nothing. + template + weak_ptr(weak_ptr const & r) + : m_pn(r.m_pn) // never throws + { + //Construct a temporary shared_ptr so that nobody + //can destroy the value while constructing this + const shared_ptr &ref = r.lock(); + m_pn.set_pointer(ref.get()); + } + + //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, + //!constructs a weak_ptr that shares ownership with r as if by storing a + //!copy of the pointer stored in r. + //! + //!Postconditions: use_count() == r.use_count(). + //! + //!Throws: nothing. + template + weak_ptr(shared_ptr const & r) + : m_pn(r.m_pn) // never throws + {} + + //!Effects: Equivalent to weak_ptr(r).swap(*this). + //! + //!Throws: nothing. + //! + //!Notes: The implementation is free to meet the effects (and the + //!implied guarantees) via different means, without creating a temporary. + template + weak_ptr & operator=(weak_ptr const & r) // never throws + { + //Construct a temporary shared_ptr so that nobody + //can destroy the value while constructing this + const shared_ptr &ref = r.lock(); + m_pn = r.m_pn; + m_pn.set_pointer(ref.get()); + return *this; + } + + //!Effects: Equivalent to weak_ptr(r).swap(*this). + //! + //!Throws: nothing. + //! + //!Notes: The implementation is free to meet the effects (and the + //!implied guarantees) via different means, without creating a temporary. + template + weak_ptr & operator=(shared_ptr const & r) // never throws + { m_pn = r.m_pn; return *this; } + + //!Returns: expired()? shared_ptr(): shared_ptr(*this). + //! + //!Throws: nothing. + shared_ptr lock() const // never throws + { + // optimization: avoid throw overhead + if(expired()){ + return shared_ptr(); + } + BOOST_TRY{ + return shared_ptr(*this); + } + BOOST_CATCH(bad_weak_ptr const &){ + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. + return shared_ptr(); + } + BOOST_CATCH_END + } + + //!Returns: 0 if *this is empty; otherwise, the number of shared_ptr objects + //!that share ownership with *this. + //! + //!Throws: nothing. + //! + //!Notes: use_count() is not necessarily efficient. Use only for debugging and + //!testing purposes, not for production code. + long use_count() const // never throws + { return m_pn.use_count(); } + + //!Returns: Returns: use_count() == 0. + //! + //!Throws: nothing. + //! + //!Notes: expired() may be faster than use_count(). + bool expired() const // never throws + { return m_pn.use_count() == 0; } + + //!Effects: Equivalent to: + //!weak_ptr().swap(*this). + void reset() // never throws in 1.30+ + { this_type().swap(*this); } + + //!Effects: Exchanges the contents of the two + //!smart pointers. + //! + //!Throws: nothing. + void swap(this_type & other) // never throws + { ::boost::adl_move_swap(m_pn, other.m_pn); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + template + bool _internal_less(weak_ptr const & rhs) const + { return m_pn < rhs.m_pn; } + + template + void _internal_assign(const ipcdetail::shared_count & pn2) + { + + m_pn = pn2; + } + + private: + + template friend class shared_ptr; + template friend class weak_ptr; + + ipcdetail::weak_count m_pn; // reference counter + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; // weak_ptr + +template inline +bool operator<(weak_ptr const & a, weak_ptr const & b) +{ return a._internal_less(b); } + +template inline +void swap(weak_ptr & a, weak_ptr & b) +{ a.swap(b); } + +//!Returns the type of a weak pointer +//!of type T with the allocator boost::interprocess::allocator allocator +//!and boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_weak_ptr +{ + typedef weak_ptr + < T + , typename ManagedMemory::template allocator::type + , typename ManagedMemory::template deleter::type + > type; +}; + +//!Returns an instance of a weak pointer constructed +//!with the default allocator and deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +inline typename managed_weak_ptr::type + make_managed_weak_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + return typename managed_weak_ptr::type + ( constructed_object + , managed_memory.template get_allocator() + , managed_memory.template get_deleter() + ); +} + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/streams/vectorstream.hpp b/extern/boost/boost/interprocess/streams/vectorstream.hpp new file mode 100644 index 00000000000..e4845a01e05 --- /dev/null +++ b/extern/boost/boost/interprocess/streams/vectorstream.hpp @@ -0,0 +1,633 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. +// Changed internal SGI string to a generic, templatized vector. Added efficient +// internal buffer get/set/swap functions, so that we can obtain/establish the +// internal buffer without any reallocation or copy. Kill those temporaries! +/////////////////////////////////////////////////////////////////////////////// +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +//!\file +//!This file defines basic_vectorbuf, basic_ivectorstream, +//!basic_ovectorstream, and basic_vectorstreamclasses. These classes +//!represent streamsbufs and streams whose sources or destinations are +//!STL-like vectors that can be swapped with external vectors to avoid +//!unnecessary allocations/copies. + +#ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP +#define BOOST_INTERPROCESS_VECTORSTREAM_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include // char traits +#include // INT_MAX +#include // ptrdiff_t +#include +#include + +namespace boost { namespace interprocess { + +//!A streambuf class that controls the transmission of elements to and from +//!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. +//!It holds a character vector specified by CharVector template parameter +//!as its formatting buffer. The vector must have contiguous storage, like +//!std::vector, boost::interprocess::vector or boost::interprocess::basic_string +template +class basic_vectorbuf + : public std::basic_streambuf +{ + public: + typedef CharVector vector_type; + typedef typename CharVector::value_type char_type; + typedef typename CharTraits::int_type int_type; + typedef typename CharTraits::pos_type pos_type; + typedef typename CharTraits::off_type off_type; + typedef CharTraits traits_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef std::basic_streambuf base_t; + + basic_vectorbuf(const basic_vectorbuf&); + basic_vectorbuf & operator =(const basic_vectorbuf&); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + explicit basic_vectorbuf(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode) + { this->initialize_pointers(); } + + //!Constructor. Throws if + //!vector_type(const VectorParameter ¶m) throws. + template + explicit basic_vectorbuf(const VectorParameter ¶m, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode), m_vect(param) + { this->initialize_pointers(); } + + public: + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read/write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { + if (this->m_mode & std::ios_base::out){ + //Update high water if necessary + //And resize vector to remove extra size + if (mp_high_water < base_t::pptr()){ + //Restore the vector's size if necessary + mp_high_water = base_t::pptr(); + } + //This does not reallocate + m_vect.resize(std::size_t(mp_high_water - (m_vect.size() ? &m_vect[0] : 0))); + } + //Now swap vector + m_vect.swap(vect); + this->initialize_pointers(); + } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { + if (this->m_mode & std::ios_base::out){ + if (mp_high_water < base_t::pptr()){ + //Restore the vector's size if necessary + mp_high_water = base_t::pptr(); + } + //This shouldn't reallocate + typedef typename vector_type::size_type size_type; + char_type *old_ptr = base_t::pbase(); + size_type high_pos = size_type(mp_high_water-old_ptr); + if(m_vect.size() > high_pos){ + m_vect.resize(high_pos); + //But we must update end write pointer because vector size is now shorter + off_type old_pos = base_t::pptr() - base_t::pbase(); + const_cast(this)->base_t::setp(old_ptr, old_ptr + high_pos); + const_cast(this)->pbump(old_pos); + } + } + return m_vect; + } + + //!Preallocates memory from the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's memory allocation throws. + void reserve(typename vector_type::size_type size) + { + if (this->m_mode & std::ios_base::out && size > m_vect.size()){ + off_type write_pos = base_t::pptr() - base_t::pbase(); + off_type read_pos = base_t::gptr() - base_t::eback(); + //Now update pointer data + m_vect.reserve(size); + this->initialize_pointers(); + this->pbump(write_pos); + if(this->m_mode & std::ios_base::in){ + base_t::setg(base_t::eback(), base_t::eback() + read_pos, base_t::egptr()); + } + } + } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { m_vect.clear(); this->initialize_pointers(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + //Maximizes high watermark to the initial vector size, + //initializes read and write iostream buffers to the capacity + //and resets stream positions + void initialize_pointers() + { + // The initial read position is the beginning of the vector. + if(!(m_mode & std::ios_base::out)){ + if(m_vect.empty()){ + this->setg(0, 0, 0); + } + else{ + this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size()); + } + } + + // The initial write position is the beginning of the vector. + if(m_mode & std::ios_base::out){ + //First get real size + off_type real_size = m_vect.size(); + //Then maximize size for high watermarking + m_vect.resize(m_vect.capacity()); + BOOST_ASSERT(m_vect.size() == m_vect.capacity()); + //Set high watermarking with the expanded size + mp_high_water = m_vect.size() ? (&m_vect[0] + real_size) : 0; + //Now set formatting pointers + if(m_vect.empty()){ + this->setp(0, 0); + if(m_mode & std::ios_base::in) + this->setg(0, 0, 0); + } + else{ + char_type *p = &m_vect[0]; + this->setp(p, p + m_vect.size()); + if(m_mode & std::ios_base::in) + this->setg(p, p, p + real_size); + } + if (m_mode & (std::ios_base::app | std::ios_base::ate)){ + this->pbump(real_size); + } + } + } + + // LWG255-inspired variant of base_t::pbump that takes a streamoff instead of an int. + void pbump(off_type delta) { + if (delta > INT_MAX) { + for (off_type d = delta / INT_MAX; d > 0; d--) + base_t::pbump(INT_MAX); + delta %= INT_MAX; + } + base_t::pbump((int)delta); + } + + protected: + virtual int_type underflow() BOOST_OVERRIDE + { + if (base_t::gptr() == 0) + return CharTraits::eof(); + if(m_mode & std::ios_base::out){ + if (mp_high_water < base_t::pptr()) + mp_high_water = base_t::pptr(); + if (base_t::egptr() < mp_high_water) + base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); + } + if (base_t::gptr() < base_t::egptr()) + return CharTraits::to_int_type(*base_t::gptr()); + return 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())) { + if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { + this->gbump(-1); + return c; + } + else if(m_mode & std::ios_base::out) { + this->gbump(-1); + *this->gptr() = CharTraits::to_char_type(c); + return c; + } + else + return CharTraits::eof(); + } + else { + this->gbump(-1); + return CharTraits::not_eof(c); + } + } + else + return 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())) { + typedef typename vector_type::difference_type dif_t; + //The new output position is the previous one plus one + //because 'overflow' requires putting 'c' on the buffer + dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1; + //Adjust high water if necessary + dif_t hipos = mp_high_water - base_t::pbase(); + if (hipos < new_outpos) + hipos = new_outpos; + //Insert the new data + m_vect.push_back(CharTraits::to_char_type(c)); + m_vect.resize(m_vect.capacity()); + BOOST_ASSERT(m_vect.size() == m_vect.capacity()); + char_type* p = const_cast(&m_vect[0]); + //A reallocation might have happened, update pointers + base_t::setp(p, p + (dif_t)m_vect.size()); + mp_high_water = p + hipos; + if (m_mode & std::ios_base::in) + base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water); + //Update write position to the old position + 1 + this->pbump((off_type)new_outpos); + return c; + } + else // c is EOF, so we don't have to do anything + return CharTraits::not_eof(c); + } + else // Overflow always fails if it's read-only. + return CharTraits::eof(); + } + + 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) BOOST_OVERRIDE + { + //Get seek mode + bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out)); + //Test for logic errors + if(!in & !out) + return pos_type(off_type(-1)); + else if((in && out) && (dir == std::ios_base::cur)) + return pos_type(off_type(-1)); + else if((in && (!(m_mode & std::ios_base::in) || (off != 0 && this->gptr() == 0) )) || + (out && (!(m_mode & std::ios_base::out) || (off != 0 && this->pptr() == 0)))) + return pos_type(off_type(-1)); + + off_type newoff; + //Just calculate the end of the stream. If the stream is read-only + //the limit is the size of the vector. Otherwise, the high water mark + //will mark the real size. + off_type limit; + if(m_mode & std::ios_base::out){ + //Update high water marking because pptr() is going to change and it might + //have been updated since last overflow() + if(mp_high_water < base_t::pptr()) + mp_high_water = base_t::pptr(); + //Update read limits in case high water mark was changed + if(m_mode & std::ios_base::in){ + if (base_t::egptr() < mp_high_water) + base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); + } + limit = static_cast(mp_high_water - base_t::pbase()); + } + else{ + limit = static_cast(m_vect.size()); + } + + switch(dir) { + case std::ios_base::beg: + newoff = 0; + break; + case std::ios_base::end: + newoff = limit; + break; + case std::ios_base::cur: + newoff = in ? static_cast(this->gptr() - this->eback()) + : static_cast(this->pptr() - this->pbase()); + break; + default: + return pos_type(off_type(-1)); + } + + newoff += off; + + if (newoff < 0 || newoff > limit) + return pos_type(-1); + if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit) + return pos_type(-1); + //This can reassign pointers + //if(m_vect.size() != m_vect.capacity()) + //this->initialize_pointers(); + if (in) + base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr()); + if (out){ + base_t::setp(base_t::pbase(), base_t::epptr()); + this->pbump(newoff); + } + return pos_type(newoff); + } + + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE + { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } + + private: + std::ios_base::openmode m_mode; + mutable vector_type m_vect; + mutable char_type* mp_high_water; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +//!A basic_istream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_ivectorstream + : public std::basic_istream + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef basic_vectorbuf vectorbuf_t; + typedef std::basic_ios basic_ios_t; + typedef std::basic_istream base_t; + + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode | std::ios_base::in) + { this->base_t::rdbuf(&get_buf()); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_ivectorstream(const VectorParameter ¶m, + std::ios_base::openmode mode = std::ios_base::in) + : vectorbuf_t(param, mode | std::ios_base::in) + //basic_ios_t() is constructed uninitialized as virtual base + //and initialized inside base_t calling basic_ios::init() + , base_t(&get_buf()) + {} + + public: + //!Returns the address of the stored + //!stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&get_buf()); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { get_buf().swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return get_buf().vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { get_buf().reserve(size); } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { get_buf().clear(); } +}; + +//!A basic_ostream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_ovectorstream + : public std::basic_ostream + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef basic_vectorbuf vectorbuf_t; + typedef std::basic_ios basic_ios_t; + typedef std::basic_ostream base_t; + + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf()const { return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode | std::ios_base::out) + { this->base_t::rdbuf(&get_buf()); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_ovectorstream(const VectorParameter ¶m, + std::ios_base::openmode mode = std::ios_base::out) + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(param, mode | std::ios_base::out) + { this->base_t::rdbuf(&get_buf()); } + + public: + //!Returns the address of the stored + //!stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&get_buf()); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { get_buf().swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return get_buf().vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { get_buf().reserve(size); } +}; + +//!A basic_iostream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_vectorstream + : public std::basic_iostream + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + , private basic_vectorbuf + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef basic_vectorbuf vectorbuf_t; + typedef std::basic_ios basic_ios_t; + typedef std::basic_iostream base_t; + + vectorbuf_t & get_buf() { return *this; } + const vectorbuf_t & get_buf() const{ return *this; } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_vectorstream(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(mode) + { this->base_t::rdbuf(&get_buf()); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base + //(via basic_ios::init() call in base_t's constructor) without the risk of a + //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. + , vectorbuf_t(param, mode) + { this->base_t::rdbuf(&get_buf()); } + + public: + //Returns the address of the stored stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&get_buf()); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read/write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { get_buf().swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return get_buf().vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { get_buf().reserve(size); } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { get_buf().clear(); } +}; + +//Some typedefs to simplify usage +//! +//!typedef basic_vectorbuf > vectorbuf; +//!typedef basic_vectorstream > vectorstream; +//!typedef basic_ivectorstream > ivectorstream; +//!typedef basic_ovectorstream > ovectorstream; +//! +//!typedef basic_vectorbuf > wvectorbuf; +//!typedef basic_vectorstream > wvectorstream; +//!typedef basic_ivectorstream > wivectorstream; +//!typedef basic_ovectorstream > wovectorstream; + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */ diff --git a/extern/boost/boost/interprocess/sync/cv_status.hpp b/extern/boost/boost/interprocess/sync/cv_status.hpp new file mode 100644 index 00000000000..afbcdf6fd75 --- /dev/null +++ b/extern/boost/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 + +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/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp new file mode 100644 index 00000000000..a4cce7ba7ec --- /dev/null +++ b/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp @@ -0,0 +1,389 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CONDITION_ALGORITHM_8A_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// Condition variable algorithm taken from pthreads-win32 discussion. +// +// The algorithm was developed by Alexander Terekhov in colaboration with +// Louis Thomas. +// +// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL +// +// semBlockLock - bin.semaphore +// semBlockQueue - semaphore +// mtxExternal - mutex or CS +// mtxUnblockLock - mutex or CS +// nWaitersGone - int +// nWaitersBlocked - int +// nWaitersToUnblock - int +// +// wait( timeout ) { +// +// [auto: register int result ] // error checking omitted +// [auto: register int nSignalsWasLeft ] +// [auto: register int nWaitersWasGone ] +// +// sem_wait( semBlockLock ); +// nWaitersBlocked++; +// sem_post( semBlockLock ); +// +// unlock( mtxExternal ); +// bTimedOut = sem_wait( semBlockQueue,timeout ); +// +// lock( mtxUnblockLock ); +// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { +// if ( bTimedOut ) { // timeout (or canceled) +// if ( 0 != nWaitersBlocked ) { +// nWaitersBlocked--; +// } +// else { +// nWaitersGone++; // count spurious wakeups. +// } +// } +// if ( 0 == --nWaitersToUnblock ) { +// if ( 0 != nWaitersBlocked ) { +// sem_post( semBlockLock ); // open the gate. +// nSignalsWasLeft = 0; // do not open the gate +// // below again. +// } +// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { +// nWaitersGone = 0; +// } +// } +// } +// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or +// // spurious semaphore :-) +// sem_wait( semBlockLock ); +// nWaitersBlocked -= nWaitersGone; // something is going on here +// // - test of timeouts? :-) +// sem_post( semBlockLock ); +// nWaitersGone = 0; +// } +// unlock( mtxUnblockLock ); +// +// if ( 1 == nSignalsWasLeft ) { +// if ( 0 != nWaitersWasGone ) { +// // sem_adjust( semBlockQueue,-nWaitersWasGone ); +// while ( nWaitersWasGone-- ) { +// sem_wait( semBlockQueue ); // better now than spurious later +// } +// } sem_post( semBlockLock ); // open the gate +// } +// +// lock( mtxExternal ); +// +// return ( bTimedOut ) ? ETIMEOUT : 0; +// } +// +// signal(bAll) { +// +// [auto: register int result ] +// [auto: register int nSignalsToIssue] +// +// lock( mtxUnblockLock ); +// +// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! +// if ( 0 == nWaitersBlocked ) { // NO-OP +// return unlock( mtxUnblockLock ); +// } +// if (bAll) { +// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; +// nWaitersBlocked = 0; +// } +// else { +// nSignalsToIssue = 1; +// nWaitersToUnblock++; +// nWaitersBlocked--; +// } +// } +// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! +// sem_wait( semBlockLock ); // close the gate +// if ( 0 != nWaitersGone ) { +// nWaitersBlocked -= nWaitersGone; +// nWaitersGone = 0; +// } +// if (bAll) { +// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; +// nWaitersBlocked = 0; +// } +// else { +// nSignalsToIssue = nWaitersToUnblock = 1; +// nWaitersBlocked--; +// } +// } +// else { // NO-OP +// return unlock( mtxUnblockLock ); +// } +// +// unlock( mtxUnblockLock ); +// sem_post( semBlockQueue,nSignalsToIssue ); +// return result; +// } +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + +// Required interface for ConditionMembers +// class ConditionMembers +// { +// typedef implementation_defined semaphore_type; +// typedef implementation_defined mutex_type; +// typedef implementation_defined integer_type; +// +// integer_type &get_nwaiters_blocked() +// integer_type &get_nwaiters_gone() +// integer_type &get_nwaiters_to_unblock() +// semaphore_type &get_sem_block_queue() +// semaphore_type &get_sem_block_lock() +// mutex_type &get_mtx_unblock_lock() +// }; +// +// Must be initialized as following +// +// get_nwaiters_blocked() == 0 +// get_nwaiters_gone() == 0 +// get_nwaiters_to_unblock() == 0 +// get_sem_block_queue() == initial count 0 +// get_sem_block_lock() == initial count 1 +// get_mtx_unblock_lock() (unlocked) +// +template +class condition_algorithm_8a +{ + private: + condition_algorithm_8a(); + ~condition_algorithm_8a(); + condition_algorithm_8a(const condition_algorithm_8a &); + condition_algorithm_8a &operator=(const condition_algorithm_8a &); + + typedef typename ConditionMembers::semaphore_type semaphore_type; + typedef typename ConditionMembers::mutex_type mutex_type; + typedef typename ConditionMembers::integer_type integer_type; + + public: + template + static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &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(); + + //Unlock external lock and program for relock + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + + bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_()); + + { + scoped_lock 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 ( (std::numeric_limits::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 + } + } + data.get_sem_block_lock().post(); // open the gate + } + + //lock.lock(); called from unlocker destructor + + return ( bTimedOut ) ? false : true; + } + + static void signal(ConditionMembers &data, bool broadcast) + { + integer_type nsignals_to_issue; + + { + scoped_lock 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()--; + } + } + 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 { // 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); + } + + private: + template + static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_) + { return sem.timed_wait(abs_time); } + + template + static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_) + { sem.wait(); return true; } +}; + +template +class condition_8a_wrapper +{ + //Non-copyable + condition_8a_wrapper(const condition_8a_wrapper &); + condition_8a_wrapper &operator=(const condition_8a_wrapper &); + + ConditionMembers m_data; + typedef condition_algorithm_8a algo_type; + + public: + + condition_8a_wrapper(){} + + //Compiler-generated destructor is OK + //~condition_8a_wrapper(){} + + ConditionMembers & get_members() + { return m_data; } + + const ConditionMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + algo_type::template wait(m_data, lock, 0); + } + + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::template wait(m_data, lock, 0); + } + + template + bool timed_wait(L& lock, const TimePoint &abs_time) + { + if (!lock) + throw lock_exception(); + return algo_type::template wait(m_data, lock, abs_time); + } + + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::template wait(m_data, lock, abs_time)) + return pred(); + } + return true; + } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP diff --git a/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp b/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp new file mode 100644 index 00000000000..0155d90bc50 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp @@ -0,0 +1,191 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_ALGORITHM_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// Condition variable 'any' (able to use any type of external mutex) +// +// The code is based on Howard E. Hinnant's ISO C++ N2406 paper. +// Many thanks to Howard for his support and comments. +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// Required interface for ConditionAnyMembers +// class ConditionAnyMembers +// { +// typedef implementation_defined mutex_type; +// typedef implementation_defined condvar_type; +// +// condvar &get_condvar() +// mutex_type &get_mutex() +// }; +// +// Must be initialized as following +// +// get_condvar() [no threads blocked] +// get_mutex() [unlocked] + +template +class condition_any_algorithm +{ + private: + condition_any_algorithm(); + ~condition_any_algorithm(); + condition_any_algorithm(const condition_any_algorithm &); + condition_any_algorithm &operator=(const condition_any_algorithm &); + + typedef typename ConditionAnyMembers::mutex_type mutex_type; + typedef typename ConditionAnyMembers::condvar_type condvar_type; + + public: + template + static void wait(ConditionAnyMembers& data, Lock& lock) + { + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(data.get_mutex()); + { + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + data.get_condvar().wait(internal_unlock); + } + } + } + + template + static bool timed_wait(ConditionAnyMembers &data, Lock& lock, const TimePoint &abs_time) + { + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(data.get_mutex()); + { + //Unlock external lock and program for relock + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + return data.get_condvar().timed_wait(internal_unlock, abs_time); + } + } + } + + static void signal(ConditionAnyMembers& data, bool broadcast) + { + scoped_lock internal_lock(data.get_mutex()); + if(broadcast){ + data.get_condvar().notify_all(); + } + else{ + data.get_condvar().notify_one(); + } + } +}; + + +template +class condition_any_wrapper +{ + //Non-copyable + condition_any_wrapper(const condition_any_wrapper &); + condition_any_wrapper &operator=(const condition_any_wrapper &); + + ConditionAnyMembers m_data; + typedef ipcdetail::condition_any_algorithm algo_type; + + public: + + condition_any_wrapper(){} + + ~condition_any_wrapper(){} + + ConditionAnyMembers & get_members() + { return m_data; } + + const ConditionAnyMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template + void wait(Lock& lock) + { + if (!lock) + throw lock_exception(); + algo_type::wait(m_data, lock); + } + + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::wait(m_data, lock); + } + + template + bool timed_wait(L& lock, const TimePoint &abs_time) + { + if (!lock) + throw lock_exception(); + return algo_type::timed_wait(m_data, lock, abs_time); + } + + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::timed_wait(m_data, lock, abs_time)) + return pred(); + } + return true; + } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP diff --git a/extern/boost/boost/interprocess/sync/detail/locks.hpp b/extern/boost/boost/interprocess/sync/detail/locks.hpp new file mode 100644 index 00000000000..a2beb8917ce --- /dev/null +++ b/extern/boost/boost/interprocess/sync/detail/locks.hpp @@ -0,0 +1,111 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-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_LOCKS_HPP +#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +class internal_mutex_lock +{ + typedef void (internal_mutex_lock::*unspecified_bool_type)(); + public: + + typedef typename Lock::mutex_type::internal_mutex_type mutex_type; + + + BOOST_INTERPROCESS_FORCEINLINE internal_mutex_lock(Lock &l) + : l_(l) + {} + + BOOST_INTERPROCESS_FORCEINLINE mutex_type* mutex() const + { return l_ ? &l_.mutex()->internal_mutex() : 0; } + + BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock(); } + + BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock(); } + + BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const + { return l_ ? &internal_mutex_lock::lock : 0; } + + private: + Lock &l_; +}; + +template +class lock_inverter +{ + Lock &l_; + public: + BOOST_INTERPROCESS_FORCEINLINE lock_inverter(Lock &l) + : l_(l) + {} + + BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.unlock(); } + + BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.lock(); } +}; + +template +class lock_to_sharable +{ + Lock &l_; + + public: + BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_sharable(Lock &l) + : l_(l) + {} + + 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_to_wait +{ + Lock &l_; + + public: + BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_wait(Lock &l) + : l_(l) + {} + BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.wait(); } + + BOOST_INTERPROCESS_FORCEINLINE bool try_lock() { return l_.try_wait(); } + + template + BOOST_INTERPROCESS_FORCEINLINE bool timed_lock(const TimePoint &abs_time) + { return l_.timed_wait(abs_time); } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP diff --git a/extern/boost/boost/interprocess/sync/file_lock.hpp b/extern/boost/boost/interprocess/sync/file_lock.hpp new file mode 100644 index 00000000000..34adbd53b11 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/file_lock.hpp @@ -0,0 +1,324 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_FILE_LOCK_HPP +#define BOOST_INTERPROCESS_FILE_LOCK_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a class that wraps file locking capabilities. + +namespace boost { +namespace interprocess { + + +//!A file lock, is a mutual exclusion utility similar to a mutex using a +//!file. A file lock has sharable and exclusive locking capabilities and +//!can be used with scoped_lock and sharable_lock classes. +//!A file lock can't guarantee synchronization between threads of the same +//!process so just use file locks to synchronize threads from different processes. +class file_lock +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructs an empty file mapping. + //!Does not throw + file_lock() BOOST_NOEXCEPT + : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) + {} + + //!Opens a file lock. Throws interprocess_exception if the file does not + //!exist or there are no operating system resources. + file_lock(const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Opens a file lock. Throws interprocess_exception if the file does not + //!exist or there are no operating system resources. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_lock(const wchar_t *name); + #endif + + //!Moves the ownership of "moved"'s file mapping object to *this. + //!After the call, "moved" does not represent any file mapping object. + //!Does not throw + file_lock(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT + : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) + { this->swap(moved); } + + //!Moves the ownership of "moved"'s file mapping to *this. + //!After the call, "moved" does not represent any file mapping. + //!Does not throw + file_lock &operator=(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT + { + file_lock tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Closes a file lock. Does not throw. + ~file_lock(); + + //!Swaps two file_locks. + //!Does not throw. + void swap(file_lock &other) BOOST_NOEXCEPT + { + file_handle_t tmp = m_file_hnd; + m_file_hnd = other.m_file_hnd; + other.m_file_hnd = tmp; + } + + //Exclusive locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!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 acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, waits until + //! it can obtain the ownership. + //!Throws: interprocess_exception on error. + //! + //!Note: A program may deadlock if the thread that owns a mutex object calls + //! this function. If the implementation can detect the deadlock, + //! an exception could be thrown. + void lock_sharable(); + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership of the + //! mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive ownership of + //! the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_until(const TimePoint &abs_time) + { return this->timed_lock_sharable(abs_time); } + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_for(const Duration &dur) + { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + file_handle_t m_file_hnd; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline file_lock::file_lock(const char *name) +{ + m_file_hnd = ipcdetail::open_existing_file(name, read_write); + + if(m_file_hnd == ipcdetail::invalid_file()){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline file_lock::file_lock(const wchar_t *name) +{ + m_file_hnd = ipcdetail::open_existing_file(name, read_write); + + if(m_file_hnd == ipcdetail::invalid_file()){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline file_lock::~file_lock() +{ + if(m_file_hnd != ipcdetail::invalid_file()){ + ipcdetail::close_file(m_file_hnd); + m_file_hnd = ipcdetail::invalid_file(); + } +} + +inline void file_lock::lock() +{ + if(!ipcdetail::acquire_file_lock(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline bool file_lock::try_lock() +{ + bool result; + if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +template +inline bool file_lock::timed_lock(const TimePoint &abs_time) +{ return ipcdetail::try_based_timed_lock(*this, abs_time); } + +inline void file_lock::unlock() +{ + if(!ipcdetail::release_file_lock(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline void file_lock::lock_sharable() +{ + if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline bool file_lock::try_lock_sharable() +{ + bool result; + if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +template +inline bool file_lock::timed_lock_sharable(const TimePoint &abs_time) +{ + ipcdetail::lock_to_sharable lsh(*this); + return ipcdetail::try_based_timed_lock(lsh, abs_time); +} + +inline void file_lock::unlock_sharable() +{ + if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_FILE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_condition.hpp b/extern/boost/boost/interprocess/sync/interprocess_condition.hpp new file mode 100644 index 00000000000..7fde9fe2191 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_condition.hpp @@ -0,0 +1,177 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CONDITION_HPP +#define BOOST_INTERPROCESS_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + #include + #define BOOST_INTERPROCESS_CONDITION_USE_POSIX +//Experimental... +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_CONDITION_USE_WINAPI +#else + //spin_condition is used + #include +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { + +class named_condition; + +//!This class is a condition variable that can be placed in shared memory or +//!memory mapped files. +//!Destroys the object of type std::condition_variable_any +//! +//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. +class interprocess_condition +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_condition(const interprocess_condition &); + interprocess_condition &operator=(const interprocess_condition &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Constructs a interprocess_condition. On error throws interprocess_exception. + interprocess_condition() + {} + + //!Destroys *this + //!liberating system resources. + ~interprocess_condition() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one() + { m_condition.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_condition.notify_all(); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + m_condition.wait(internal_lock); + } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + m_condition.wait(internal_lock, pred); + } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_condition.timed_wait(internal_lock, abs_time); + } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { + ipcdetail::internal_mutex_lock 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 + 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 + 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 + 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 + 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_CONDITION_USE_POSIX) + ipcdetail::posix_condition m_condition; + #elif defined(BOOST_INTERPROCESS_CONDITION_USE_WINAPI) + ipcdetail::winapi_condition m_condition; + #else + ipcdetail::spin_condition m_condition; + #endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp b/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp new file mode 100644 index 00000000000..4a1d84a5ac1 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp @@ -0,0 +1,154 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_CONDITION_ANY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#include +#include + +#include +#include +#include +#include +#include +#include + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes process-shared variables interprocess_condition_any class + +namespace boost { +namespace interprocess { + +//!This class is a condition variable that can be placed in shared memory or +//!memory mapped files. +//! +//!The interprocess_condition_any class is a generalization of interprocess_condition. +//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex +//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable +//!requirements (lock()/unlock() member functions). +//! +//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. +class interprocess_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_condition_any(const interprocess_condition_any &); + interprocess_condition_any &operator=(const interprocess_condition_any &); + + class members + { + public: + typedef interprocess_condition condvar_type; + typedef interprocess_mutex mutex_type; + + condvar_type &get_condvar() { return m_cond; } + mutex_type &get_mutex() { return m_mut; } + + private: + condvar_type m_cond; + mutex_type m_mut; + }; + + ipcdetail::condition_any_wrapper m_cond; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Constructs a interprocess_condition_any. On error throws interprocess_exception. + interprocess_condition_any(){} + + //!Destroys *this + //!liberating system resources. + ~interprocess_condition_any(){} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { m_cond.wait(lock, pred); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + 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 + 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 + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } +}; + +} //namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp new file mode 100644 index 00000000000..3819080e2e4 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp @@ -0,0 +1,198 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MUTEX_HPP +#define BOOST_INTERPROCESS_MUTEX_HPP + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + #include + #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 +#else + //spin_mutex is used + #include + namespace boost { + namespace interprocess { + namespace ipcdetail{ + namespace robust_emulation_helpers { + + template + class mutex_traits; + + }}}} +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes a mutex class that can be placed in memory shared by +//!several processes. + +namespace boost { +namespace interprocess { + +class interprocess_condition; + +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_mutex(const interprocess_mutex &); + interprocess_mutex &operator=(const interprocess_mutex &); + friend class interprocess_condition; + + public: + #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; + void take_ownership(){ m_mutex.take_ownership(); } + public: + #endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Constructor. + //!Throws interprocess_exception on error. + interprocess_mutex(); + + //!Destructor. If any process uses the mutex after the destructor is called + //!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 + //! number of times it is locked. + //!Returns: If the thread acquires ownership of the mutex, returns true, if + //! the timeout expires 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. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 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. + void unlock(); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + internal_mutex_type &internal_mutex() + { return m_mutex; } + + const internal_mutex_type &internal_mutex() const + { return m_mutex; } + + private: + internal_mutex_type m_mutex; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess { +} //namespace boost { + + +namespace boost { +namespace interprocess { + +inline interprocess_mutex::interprocess_mutex(){} + +inline interprocess_mutex::~interprocess_mutex(){} + +inline void interprocess_mutex::lock() +{ ipcdetail::timeout_when_locking_aware_lock(m_mutex); } + +inline bool interprocess_mutex::try_lock() +{ return m_mutex.try_lock(); } + +template +inline bool interprocess_mutex::timed_lock(const TimePoint &abs_time) +{ return m_mutex.timed_lock(abs_time); } + +inline void interprocess_mutex::unlock() +{ m_mutex.unlock(); } + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp new file mode 100644 index 00000000000..dc5c5a07463 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -0,0 +1,184 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \ + defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \ + defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES) + #include + #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + //Experimental... + #include + #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI +#else + //spin_recursive_mutex is used + #include + namespace boost { + namespace interprocess { + namespace ipcdetail{ + namespace robust_emulation_helpers { + + template + class mutex_traits; + + }}}} +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows several locking calls by the same +//!process. Allows timed lock tries +class interprocess_recursive_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_recursive_mutex(const interprocess_recursive_mutex &); + interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Constructor. + //!Throws interprocess_exception on error. + interprocess_recursive_mutex(); + + //!Destructor. If any process uses the mutex after the destructor is called + //!the result is undefined. Does not throw. + ~interprocess_recursive_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. The mutex must be unlocked + //! the same number of times it is locked. + //!Throws: interprocess_exception on error. + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + void lock(); + + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!is already locked, returns true when success. The mutex must be unlocked + //!the same number of times it is locked. + //!Throws: interprocess_exception if a severe error is found + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + bool try_lock(); + + //!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before + //!abs_time time, returns false. The mutex must be unlocked + //! the same number of times it is locked. + //!Throws: interprocess_exception if a severe error is found + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 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. + //! If the mutex supports recursive locking, the mutex must be unlocked the + //! same number of times it is locked. + //!Throws: interprocess_exception on error. + void unlock(); + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + #if defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX) + ipcdetail::posix_recursive_mutex mutex; + #elif defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI) + ipcdetail::winapi_recursive_mutex mutex; + #else + void take_ownership(){ mutex.take_ownership(); } + friend class ipcdetail::robust_emulation_helpers::mutex_traits; + ipcdetail::spin_recursive_mutex mutex; + #endif + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess { +} //namespace boost { + +namespace boost { +namespace interprocess { + +inline interprocess_recursive_mutex::interprocess_recursive_mutex(){} + +inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){} + +inline void interprocess_recursive_mutex::lock() +{ ipcdetail::timeout_when_locking_aware_lock(mutex); } + +inline bool interprocess_recursive_mutex::try_lock() +{ return mutex.try_lock(); } + +template +inline bool interprocess_recursive_mutex::timed_lock(const TimePoint &abs_time) +{ return mutex.timed_lock(abs_time); } + +inline void interprocess_recursive_mutex::unlock() +{ mutex.unlock(); } + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp b/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp new file mode 100644 index 00000000000..abb74e8aa48 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp @@ -0,0 +1,143 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_SEMAPHORE_HPP + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \ + defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \ + defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES) + #include + #define BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + //Experimental... + #include + #define BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI +#else + //spin_semaphore is used + #include +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!\file +//!Describes a interprocess_semaphore class for inter-process synchronization + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_semaphore that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_semaphore +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + interprocess_semaphore(const interprocess_semaphore &); + interprocess_semaphore &operator=(const interprocess_semaphore &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Creates a interprocess_semaphore with the given initial count. + //!interprocess_exception if there is an error.*/ + interprocess_semaphore(unsigned int initialCount); + + //!Destroys the interprocess_semaphore. + //!Does not throw + ~interprocess_semaphore(); + + //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting + //!for the interprocess_semaphore, then one of these processes will return successfully from + //!its wait function. If there is an error an interprocess_exception exception is thrown. + void post(); + + //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, + //!then the calling process/thread blocks until it can decrement the counter. + //!If there is an error an interprocess_exception exception is thrown. + void wait(); + + //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero + //!and returns true. If the value is not greater than zero returns false. + //!If there is an error an interprocess_exception exception is thrown. + bool try_wait(); + + //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater + //!than zero and returns true. Otherwise, waits for the interprocess_semaphore + //!to the posted or the timeout expires. If the timeout expires, the + //!function returns false. If the interprocess_semaphore is posted the function + //!returns true. If there is an error throws sem_exception + template + bool timed_wait(const TimePoint &abs_time); + + //!Returns the interprocess_semaphore count +// int get_count() const; + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + #if defined(BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX) + typedef ipcdetail::posix_semaphore internal_sem_t; + #elif defined(BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI) + typedef ipcdetail::winapi_semaphore internal_sem_t; + #else + typedef ipcdetail::spin_semaphore internal_sem_t; + #endif //#if defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) + internal_sem_t m_sem; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess { +} //namespace boost { + +namespace boost { +namespace interprocess { + +inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount) + : m_sem(initialCount) +{} + +inline interprocess_semaphore::~interprocess_semaphore(){} + +inline void interprocess_semaphore::wait() +{ + ipcdetail::lock_to_wait ltw(m_sem); + timeout_when_locking_aware_lock(ltw); +} + +inline bool interprocess_semaphore::try_wait() +{ return m_sem.try_wait(); } + +template +inline bool interprocess_semaphore::timed_wait(const TimePoint &abs_time) +{ return m_sem.timed_wait(abs_time); } + +inline void interprocess_semaphore::post() +{ m_sem.post(); } + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp new file mode 100644 index 00000000000..bee9eedeade --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp @@ -0,0 +1,424 @@ +////////////////////////////////////////////////////////////////////////////// +// Code based on Howard Hinnant's shared_mutex class +// +// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost +// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt) +// +// (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_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +//!\file +//!Describes interprocess_sharable_mutex class + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_sharable_mutex +{ + //Non-copyable + interprocess_sharable_mutex(const interprocess_sharable_mutex &); + interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &); + + friend class interprocess_condition; + public: + + //!Constructs the sharable lock. + //!Throws interprocess_exception on error. + interprocess_sharable_mutex(); + + //!Destroys the sharable lock. + //!Does not throw. + ~interprocess_sharable_mutex(); + + //Exclusive locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!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 acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_sharable(); + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, 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_sharable(); + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise 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. + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_until(const TimePoint &abs_time) + { return this->timed_lock_sharable(abs_time); } + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_for(const Duration &dur) + { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef scoped_lock scoped_lock_t; + + //Pack all the control data in a word to be able + //to use atomic instructions in the future + struct control_word_t + { + unsigned exclusive_in : 1; + unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1; + } m_ctrl; + + interprocess_mutex m_mut; + interprocess_condition m_first_gate; + interprocess_condition m_second_gate; + + private: + //Rollback structures for exceptions or failure return values + struct exclusive_rollback + { + exclusive_rollback(control_word_t &ctrl + ,interprocess_condition &first_gate) + : mp_ctrl(&ctrl), m_first_gate(first_gate) + {} + + void release() + { mp_ctrl = 0; } + + ~exclusive_rollback() + { + if(mp_ctrl){ + mp_ctrl->exclusive_in = 0; + m_first_gate.notify_all(); + } + } + control_word_t *mp_ctrl; + interprocess_condition &m_first_gate; + }; + + template + struct base_constants_t + { + static const unsigned max_readers + = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1)); + }; + typedef base_constants_t<0> constants; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +const unsigned interprocess_sharable_mutex::base_constants_t::max_readers; + +inline interprocess_sharable_mutex::interprocess_sharable_mutex() +{ + this->m_ctrl.exclusive_in = 0; + this->m_ctrl.num_shared = 0; +} + +inline interprocess_sharable_mutex::~interprocess_sharable_mutex() +{} + +inline void interprocess_sharable_mutex::lock() +{ + scoped_lock_t lck(m_mut); + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + this->m_first_gate.wait(lck); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + this->m_second_gate.wait(lck); + } + rollback.release(); +} + +inline bool interprocess_sharable_mutex::try_lock() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive + //or sharable mark return false; + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared){ + return false; + } + this->m_ctrl.exclusive_in = 1; + return true; +} + +template +inline bool interprocess_sharable_mutex::timed_lock + (const TimePoint &abs_time) +{ + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in){ + return false; + } + break; + } + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_shared){ + return false; + } + break; + } + } + rollback.release(); + return true; +} + +inline void interprocess_sharable_mutex::unlock() +{ + scoped_lock_t lck(m_mut); + this->m_ctrl.exclusive_in = 0; + this->m_first_gate.notify_all(); +} + +//Sharable locking + +inline void interprocess_sharable_mutex::lock_sharable() +{ + scoped_lock_t lck(m_mut); + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + this->m_first_gate.wait(lck); + } + + //Increment sharable count + ++this->m_ctrl.num_shared; +} + +inline bool interprocess_sharable_mutex::try_lock_sharable() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //The sharable lock must fail + //if an exclusive lock has been acquired + //or there are too many sharable locks + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +template +inline bool interprocess_sharable_mutex::timed_lock_sharable + (const TimePoint &abs_time) +{ + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while (this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + break; + } + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +inline void interprocess_sharable_mutex::unlock_sharable() +{ + scoped_lock_t lck(m_mut); + //Decrement sharable count + --this->m_ctrl.num_shared; + if (this->m_ctrl.num_shared == 0){ + this->m_second_gate.notify_one(); + } + //Check if there are blocked sharables because of + //there were too many sharables + else if(this->m_ctrl.num_shared == (constants::max_readers-1)){ + this->m_first_gate.notify_all(); + } +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp new file mode 100644 index 00000000000..7b7893a8b3f --- /dev/null +++ b/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -0,0 +1,771 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Code based on Howard Hinnant's upgrade_mutex class +// +// (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_UPGRADABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +//!\file +//!Describes interprocess_upgradable_mutex class + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_upgradable_mutex +{ + //Non-copyable + interprocess_upgradable_mutex(const interprocess_upgradable_mutex &); + interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &); + + friend class interprocess_condition; + public: + + //!Constructs the upgradable lock. + //!Throws interprocess_exception on error. + interprocess_upgradable_mutex(); + + //!Destroys the upgradable lock. + //!Does not throw. + ~interprocess_upgradable_mutex(); + + //Exclusive locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, sharable or upgradable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!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 acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, sharable or upgradable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, sharable or + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_sharable(); + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, 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_sharable(); + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise 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. + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_until(const TimePoint &abs_time) + { return this->timed_lock_sharable(abs_time); } + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_for(const Duration &dur) + { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + //Upgradable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_upgradable(); + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! without waiting. If no other thread has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire upgradable ownership immediately returns true. + //! If it has to wait, 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_upgradable(); + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! waiting if necessary until no other thread has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires upgradable ownership, returns true. Otherwise 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. + template + bool timed_lock_upgradable(const TimePoint &abs_time); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable(); + + //Demotions + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! upgradable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_upgradable(); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_sharable(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock_sharable(); + + //Promotions + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! exclusive ownership. This operation will block until all threads with + //! sharable ownership release their sharable lock. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to + //! acquire exclusive ownership. This operation will fail if there are threads + //! with sharable ownership, but it will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to acquire + //! exclusive ownership, waiting if necessary until abs_time. This operation will + //! fail if there are threads with sharable ownership or timeout reaches, but it + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. */ + template + bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! exclusive ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock(); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! upgradable ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock_upgradable(); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef scoped_lock scoped_lock_t; + + //Pack all the control data in a word to be able + //to use atomic instructions in the future + struct control_word_t + { + unsigned exclusive_in : 1; + unsigned upgradable_in : 1; + unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2; + } m_ctrl; + + interprocess_mutex m_mut; + interprocess_condition m_first_gate; + interprocess_condition m_second_gate; + + private: + //Rollback structures for exceptions or failure return values + struct exclusive_rollback + { + exclusive_rollback(control_word_t &ctrl + ,interprocess_condition &first_gate) + : mp_ctrl(&ctrl), m_first_gate(first_gate) + {} + + void release() + { mp_ctrl = 0; } + + ~exclusive_rollback() + { + if(mp_ctrl){ + mp_ctrl->exclusive_in = 0; + m_first_gate.notify_all(); + } + } + control_word_t *mp_ctrl; + interprocess_condition &m_first_gate; + }; + + struct upgradable_to_exclusive_rollback + { + upgradable_to_exclusive_rollback(control_word_t &ctrl) + : mp_ctrl(&ctrl) + {} + + void release() + { mp_ctrl = 0; } + + ~upgradable_to_exclusive_rollback() + { + if(mp_ctrl){ + //Recover upgradable lock + mp_ctrl->upgradable_in = 1; + ++mp_ctrl->num_upr_shar; + //Execute the second half of exclusive locking + mp_ctrl->exclusive_in = 0; + } + } + control_word_t *mp_ctrl; + }; + + template + struct base_constants_t + { + static const unsigned max_readers + = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); + }; + typedef base_constants_t<0> constants; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +const unsigned interprocess_upgradable_mutex::base_constants_t::max_readers; + +inline interprocess_upgradable_mutex::interprocess_upgradable_mutex() +{ + this->m_ctrl.exclusive_in = 0; + this->m_ctrl.upgradable_in = 0; + this->m_ctrl.num_upr_shar = 0; +} + +inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex() +{} + +inline void interprocess_upgradable_mutex::lock() +{ + scoped_lock_t lck(m_mut); + + //The exclusive lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + this->m_first_gate.wait(lck); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_upr_shar){ + this->m_second_gate.wait(lck); + } + rollback.release(); +} + +inline bool interprocess_upgradable_mutex::try_lock() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive, upgradable + //or sharable mark return false; + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar){ + return false; + } + this->m_ctrl.exclusive_in = 1; + return true; +} + +template +bool interprocess_upgradable_mutex::timed_lock(const TimePoint &abs_time) +{ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The exclusive lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + return false; + } + break; + } + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_upr_shar){ + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; + } + } + rollback.release(); + return true; +} + +inline void interprocess_upgradable_mutex::unlock() +{ + scoped_lock_t lck(m_mut); + this->m_ctrl.exclusive_in = 0; + this->m_first_gate.notify_all(); +} + +//Upgradable locking + +inline void interprocess_upgradable_mutex::lock_upgradable() +{ + scoped_lock_t lck(m_mut); + + //The upgradable lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + this->m_first_gate.wait(lck); + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; +} + +inline bool interprocess_upgradable_mutex::try_lock_upgradable() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //The upgradable lock must fail + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; + return true; +} + +template +bool interprocess_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) +{ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The upgradable lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if((this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers)){ + return false; + } + break; + } + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline void interprocess_upgradable_mutex::unlock_upgradable() +{ + scoped_lock_t lck(m_mut); + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + this->m_first_gate.notify_all(); +} + +//Sharable locking + +inline void interprocess_upgradable_mutex::lock_sharable() +{ + scoped_lock_t lck(m_mut); + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + this->m_first_gate.wait(lck); + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; +} + +inline bool interprocess_upgradable_mutex::try_lock_sharable() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //The sharable lock must fail + //if an exclusive lock has been acquired + //or there are too many sharable locks + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; + return true; +} + +template +inline bool interprocess_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) +{ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while (this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + break; + } + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline void interprocess_upgradable_mutex::unlock_sharable() +{ + scoped_lock_t lck(m_mut); + //Decrement sharable count + --this->m_ctrl.num_upr_shar; + if (this->m_ctrl.num_upr_shar == 0){ + this->m_second_gate.notify_one(); + } + //Check if there are blocked sharables because of + //there were too many sharables + else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){ + this->m_first_gate.notify_all(); + } +} + +//Downgrading + +inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() +{ + scoped_lock_t lck(m_mut); + //Unmark it as exclusive + this->m_ctrl.exclusive_in = 0; + //Mark it as upgradable + this->m_ctrl.upgradable_in = 1; + //The sharable count should be 0 so increment it + this->m_ctrl.num_upr_shar = 1; + //Notify readers that they can enter + m_first_gate.notify_all(); +} + +inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() +{ + scoped_lock_t lck(m_mut); + //Unmark it as exclusive + this->m_ctrl.exclusive_in = 0; + //The sharable count should be 0 so increment it + this->m_ctrl.num_upr_shar = 1; + //Notify readers that they can enter + m_first_gate.notify_all(); +} + +inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() +{ + scoped_lock_t lck(m_mut); + //Unmark it as upgradable (we don't have to decrement count) + this->m_ctrl.upgradable_in = 0; + //Notify readers/upgradable that they can enter + m_first_gate.notify_all(); +} + +//Upgrading + +inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() +{ + scoped_lock_t lck(m_mut); + //Simulate unlock_upgradable() without + //notifying sharables. + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + //Execute the second half of exclusive locking + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + upgradable_to_exclusive_rollback rollback(m_ctrl); + + while (this->m_ctrl.num_upr_shar){ + this->m_second_gate.wait(lck); + } + rollback.release(); +} + +inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() +{ + scoped_lock_t lck(m_mut, try_to_lock); + //Check if there are no readers + if(!lck.owns() + || this->m_ctrl.num_upr_shar != 1){ + return false; + } + //Now unlock upgradable and mark exclusive + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + this->m_ctrl.exclusive_in = 1; + return true; +} + +template +bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) +{ + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; + + //Simulate unlock_upgradable() without + //notifying sharables. + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + //Execute the second half of exclusive locking + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + upgradable_to_exclusive_rollback rollback(m_ctrl); + + while (this->m_ctrl.num_upr_shar){ + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; + } + } + rollback.release(); + return true; +} + +inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive, upgradable + //or sharable mark return false; + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar != 1){ + return false; + } + this->m_ctrl.exclusive_in = 1; + this->m_ctrl.num_upr_shar = 0; + return true; +} + +inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() +{ + scoped_lock_t lck(m_mut, try_to_lock); + + //The upgradable lock must fail + //if an exclusive or upgradable lock has been acquired + if(!lck.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in){ + return false; + } + + //Mark that upgradable lock has been acquired + this->m_ctrl.upgradable_in = 1; + return true; +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/mutex_family.hpp b/extern/boost/boost/interprocess/sync/mutex_family.hpp new file mode 100644 index 00000000000..b136ce4418d --- /dev/null +++ b/extern/boost/boost/interprocess/sync/mutex_family.hpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MUTEX_FAMILY_HPP +#define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +//!\file +//!Describes a shared interprocess_mutex family fit algorithm used to allocate objects in shared memory. + +namespace boost { + +namespace interprocess { + +//!Describes interprocess_mutex family to use with Interprocess framework +//!based on boost::interprocess synchronization objects. +struct mutex_family +{ + typedef boost::interprocess::interprocess_mutex mutex_type; + typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type; +}; + +//!Describes interprocess_mutex family to use with Interprocess frameworks +//!based on null operation synchronization objects. +struct null_mutex_family +{ + typedef boost::interprocess::null_mutex mutex_type; + typedef boost::interprocess::null_mutex recursive_mutex_type; +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP + + diff --git a/extern/boost/boost/interprocess/sync/named_condition.hpp b/extern/boost/boost/interprocess/sync/named_condition.hpp new file mode 100644 index 00000000000..78a9fb90159 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_condition.hpp @@ -0,0 +1,299 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI +#else + #include +#endif + +//!\file +//!Describes a named condition class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class named_condition +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_condition(); + named_condition(const named_condition &); + named_condition &operator=(const named_condition &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + named_condition(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition(open_only_t, ... ) + //!Does not throw + named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_condition(open_only_t, const char *name); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(open_only_t, const wchar_t *name); + + #endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock); + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time); + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred); + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + 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 + 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 + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } + + //!Erases a named condition 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 named condition 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) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + #if defined(BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI) + typedef ipcdetail::winapi_named_condition condition_type; + #else + typedef ipcdetail::shm_named_condition condition_type; + #endif + condition_type m_cond; + + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_condition::~named_condition() +{} + +inline named_condition::named_condition(create_only_t, const char *name, const permissions &perm) + : m_cond(create_only_t(), name, perm) +{} + +inline named_condition::named_condition(open_or_create_t, const char *name, const permissions &perm) + : m_cond(open_or_create_t(), name, perm) +{} + +inline named_condition::named_condition(open_only_t, const char *name) + : m_cond(open_only_t(), name) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_condition::named_condition(create_only_t, const wchar_t *name, const permissions &perm) + : m_cond(create_only_t(), name, perm) +{} + +inline named_condition::named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_cond(open_or_create_t(), name, perm) +{} + +inline named_condition::named_condition(open_only_t, const wchar_t *name) + : m_cond(open_only_t(), name) +{} + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + +inline void named_condition::notify_one() +{ m_cond.notify_one(); } + +inline void named_condition::notify_all() +{ m_cond.notify_all(); } + +template +inline void named_condition::wait(L& lock) +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock); +} + +template +inline void named_condition::wait(L& lock, Pr pred) +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock, pred); +} + +template +inline bool named_condition::timed_wait + (L& lock, const TimePoint &abs_time) +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time); +} + +template +inline bool named_condition::timed_wait + (L& lock, const TimePoint &abs_time, Pr pred) +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time, pred); +} + +inline bool named_condition::remove(const char *name) +{ + return condition_type::remove(name); +} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_condition::remove(const wchar_t *name) +{ + return condition_type::remove(name); +} + +#endif + + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/named_condition_any.hpp new file mode 100644 index 00000000000..2614c46d488 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_condition_any.hpp @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI +#else + #include +#endif + +//!\file +//!Describes a named condition class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_condition_any(); + named_condition_any(const named_condition_any &); + named_condition_any &operator=(const named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + named_condition_any(create_only_t, const char *name, const permissions &perm = permissions()) + : m_cond(create_only_t(), name, perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition_any(open_only_t, ... ) + //!Does not throw + named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions()) + : m_cond(open_or_create_t(), name, perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_condition_any(open_only_t, const char *name) + : m_cond(open_only_t(), name) + {} + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(create_only_t, const wchar_t *name, const permissions &perm = permissions()) + : m_cond(create_only_t(), name, perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition_any(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) + : m_cond(open_or_create_t(), name, perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(open_only_t, const wchar_t *name) + : m_cond(open_only_t(), name) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { return m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { return m_cond.wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + 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 + 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 + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name) + { return condition_any_type::remove(name); } + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named condition 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) + { return condition_any_type::remove(name); } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + #if defined(BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI) + typedef ipcdetail::winapi_named_condition_any condition_any_type; + #else + typedef ipcdetail::shm_named_condition_any condition_any_type; + #endif + condition_any_type m_cond; + + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/named_mutex.hpp b/extern/boost/boost/interprocess/sync/named_mutex.hpp new file mode 100644 index 00000000000..c7415769dae --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_mutex.hpp @@ -0,0 +1,267 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + #include + #define BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI +#else + #include +#endif + +//!\file +//!Describes a named mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +class named_condition; + +//!A mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named_mutex. +class named_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + named_mutex(); + named_mutex(const named_mutex &); + named_mutex &operator=(const named_mutex &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Creates a global mutex with a name. + //!Throws interprocess_exception on error. + named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!named_mutex(open_only_t, ... ) + //!Does not throw + named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global mutex with a name. + //!Throws interprocess_exception on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!named_mutex(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_mutex(); + + //!Unlocks a previously locked + //!mutex. + void unlock(); + + //!Requires: The calling thread does not own the mutex. + //! + //!Locks the mutex, sleeps when the mutex is already locked. + //!Throws interprocess_exception if a severe error is found + //! + //!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. + //! + //!Tries to lock the mutex, returns false when the mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found + //! + //!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. + //! + //!Tries to lock the the mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + //! + //!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 + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Erases a named mutex 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 named mutex 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) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + public: + #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX) + typedef ipcdetail::posix_named_mutex internal_mutex_type; + #elif defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI) + typedef ipcdetail::winapi_named_mutex internal_mutex_type; + #else + typedef ipcdetail::shm_named_mutex internal_mutex_type; + #endif + internal_mutex_type &internal_mutex() + { return m_mut; } + + internal_mutex_type m_mut; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm) + : m_mut(create_only_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_or_create_t, const char *name, const permissions &perm) + : m_mut(open_or_create_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_only_t, const char *name) + : m_mut(open_only_t(), name) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_mutex::named_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_mut(create_only_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mut(open_or_create_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_only_t, const wchar_t *name) + : m_mut(open_only_t(), name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void named_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); } + +inline named_mutex::~named_mutex() +{} + +inline void named_mutex::lock() +{ m_mut.lock(); } + +inline void named_mutex::unlock() +{ m_mut.unlock(); } + +inline bool named_mutex::try_lock() +{ return m_mut.try_lock(); } + +template +inline bool named_mutex::timed_lock(const TimePoint &abs_time) +{ return m_mut.timed_lock(abs_time); } + +inline bool named_mutex::remove(const char *name) +{ return internal_mutex_type::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_mutex::remove(const wchar_t *name) +{ return internal_mutex_type::remove(name); } + +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp new file mode 100644 index 00000000000..e75d0f9d6f3 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp @@ -0,0 +1,245 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI +#else + #include +#endif + +//!\file +//!Describes a named named_recursive_mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!A recursive mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named_recursive_mutex. +class named_recursive_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_recursive_mutex(); + named_recursive_mutex(const named_recursive_mutex &); + named_recursive_mutex &operator=(const named_recursive_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!named_recursive_mutex(open_only_t, ... ) + //!Does not throw + named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_recursive_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!named_recursive_mutex(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_recursive_mutex(); + + //!Unlocks a previously locked + //!named_recursive_mutex. + void unlock(); + + //!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked. + //!Throws interprocess_exception if a severe error is found. + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + void lock(); + + //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found. + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + bool try_lock(); + + //!Tries to lock the named_recursive_mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + //! + //!Note: A program shall not deadlock if the thread that has ownership calls + //! this function. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Erases a named recursive mutex + //!from the system + static bool remove(const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Erases a named recursive mutex + //!from the system + //! + //!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) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + #if defined(BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI) + typedef ipcdetail::winapi_named_recursive_mutex impl_t; + #else + typedef ipcdetail::shm_named_recursive_mutex impl_t; + #endif + impl_t m_mut; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_recursive_mutex::~named_recursive_mutex() +{} + +inline void named_recursive_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); } + +inline named_recursive_mutex::named_recursive_mutex(create_only_t, const char *name, const permissions &perm) + : m_mut (create_only, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm) + : m_mut (open_or_create, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *name) + : m_mut (open_only, name) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_recursive_mutex::named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_mut (create_only, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mut (open_or_create, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_only_t, const wchar_t *name) + : m_mut (open_only, name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void named_recursive_mutex::lock() +{ m_mut.lock(); } + +inline void named_recursive_mutex::unlock() +{ m_mut.unlock(); } + +inline bool named_recursive_mutex::try_lock() +{ return m_mut.try_lock(); } + +template +inline bool named_recursive_mutex::timed_lock(const TimePoint &abs_time) +{ return m_mut.timed_lock(abs_time); } + +inline bool named_recursive_mutex::remove(const char *name) +{ return impl_t::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_recursive_mutex::remove(const wchar_t *name) +{ return impl_t::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/named_semaphore.hpp new file mode 100644 index 00000000000..74d38ba97c2 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_semaphore.hpp @@ -0,0 +1,239 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) +#include +//Experimental... +#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI +#else + #include +#endif + +//!\file +//!Describes a named semaphore class for inter-process synchronization + +namespace boost { +namespace interprocess { + +//!A semaphore with a global name, so it can be found from different +//!processes. Allows several resource sharing patterns and efficient +//!acknowledgment mechanisms. +class named_semaphore +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + named_semaphore(); + named_semaphore(const named_semaphore &); + named_semaphore &operator=(const named_semaphore &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Creates a global semaphore with a name, and an initial count. + //!If the semaphore can't be created throws interprocess_exception + named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens or creates a global semaphore with a name, and an initial count. + //!If the semaphore is created, this call is equivalent to + //!named_semaphore(create_only_t, ...) + //!If the semaphore is already created, this call is equivalent to + //!named_semaphore(open_only_t, ... ) + //!and initialCount is ignored. + named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens a global semaphore with a name if that semaphore is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_semaphore(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global semaphore with a name, and an initial count. + //!If the semaphore can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens or creates a global semaphore with a name, and an initial count. + //!If the semaphore is created, this call is equivalent to + //!named_semaphore(create_only_t, ...) + //!If the semaphore is already created, this call is equivalent to + //!named_semaphore(open_only_t, ... ) + //!and initialCount is ignored. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens a global semaphore with a name if that semaphore is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_semaphore(); + + //!Increments the semaphore count. If there are processes/threads blocked waiting + //!for the semaphore, then one of these processes will return successfully from + //!its wait function. If there is an error an interprocess_exception exception is thrown. + void post(); + + //!Decrements the semaphore. If the semaphore value is not greater than zero, + //!then the calling process/thread blocks until it can decrement the counter. + //!If there is an error an interprocess_exception exception is thrown. + void wait(); + + //!Decrements the semaphore if the semaphore's value is greater than zero + //!and returns true. If the value is not greater than zero returns false. + //!If there is an error an interprocess_exception exception is thrown. + bool try_wait(); + + //!Decrements the semaphore if the semaphore's value is greater + //!than zero and returns true. Otherwise, waits for the semaphore + //!to the posted or the timeout expires. If the timeout expires, the + //!function returns false. If the semaphore is posted the function + //!returns true. If there is an error throws sem_exception + template + bool timed_wait(const TimePoint &abs_time); + + //!Erases a named semaphore 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 named semaphore 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) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) + typedef ipcdetail::posix_named_semaphore impl_t; + #elif defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI) + typedef ipcdetail::winapi_named_semaphore impl_t; + #else + typedef ipcdetail::shm_named_semaphore impl_t; + #endif + impl_t m_sem; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_semaphore::named_semaphore + (create_only_t, const char *name, unsigned int initialCount, const permissions &perm) + : m_sem(create_only, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore + (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm) + : m_sem(open_or_create, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore(open_only_t, const char *name) + : m_sem(open_only, name) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_semaphore::named_semaphore + (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_sem(create_only, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_sem(open_or_create, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore(open_only_t, const wchar_t *name) + : m_sem(open_only, name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_semaphore::~named_semaphore() +{} + +inline void named_semaphore::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_sem); } + +inline void named_semaphore::wait() +{ m_sem.wait(); } + +inline void named_semaphore::post() +{ m_sem.post(); } + +inline bool named_semaphore::try_wait() +{ return m_sem.try_wait(); } + +template +inline bool named_semaphore::timed_wait(const TimePoint &abs_time) +{ return m_sem.timed_wait(abs_time); } + +inline bool named_semaphore::remove(const char *name) +{ return impl_t::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_semaphore::remove(const wchar_t *name) +{ return impl_t::remove(name); } + +#endif + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp b/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp new file mode 100644 index 00000000000..d56e7b9c064 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp @@ -0,0 +1,391 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named sharable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +class named_condition; + +//!A sharable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named sharable mutex. +class named_sharable_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_sharable_mutex(); + named_sharable_mutex(const named_sharable_mutex &); + named_sharable_mutex &operator=(const named_sharable_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global sharable mutex with a name. + //!If the sharable mutex can't be created throws interprocess_exception + named_sharable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global sharable mutex with a name. + //!If the sharable mutex is created, this call is equivalent to + //!named_sharable_mutex(create_only_t, ...) + //!If the sharable mutex is already created, this call is equivalent to + //!named_sharable_mutex(open_only_t, ... ). + named_sharable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global sharable mutex with a name if that sharable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_sharable_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global sharable mutex with a name. + //!If the sharable mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global sharable mutex with a name. + //!If the sharable mutex is created, this call is equivalent to + //!named_sharable_mutex(create_only_t, ...) + //!If the sharable mutex is already created, this call is equivalent to + //!named_sharable_mutex(open_only_t, ... ). + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global sharable mutex with a name if that sharable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_sharable_mutex(); + + //Exclusive locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!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 acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_sharable(); + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, 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_sharable(); + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise 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 + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_until(const TimePoint &abs_time) + { return this->timed_lock_sharable(abs_time); } + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_for(const Duration &dur) + { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + //!Erases a named sharable mutex 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 named sharable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const wchar_t *name); + + #endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_sharable_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_sharable_mutex::~named_sharable_mutex() +{} + +inline named_sharable_mutex::named_sharable_mutex + (create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_sharable_mutex::named_sharable_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif + +inline void named_sharable_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_sharable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_sharable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_sharable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +template +inline bool named_sharable_mutex::timed_lock + (const TimePoint &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_sharable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_sharable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_sharable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +template +inline bool named_sharable_mutex::timed_lock_sharable + (const TimePoint &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline bool named_sharable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_sharable_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp new file mode 100644 index 00000000000..679e961d771 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -0,0 +1,540 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_named_upgradable_mutex_HPP +#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named upgradable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +class named_condition; + +//!A upgradable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named upgradable mutex. +class named_upgradable_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_upgradable_mutex(); + named_upgradable_mutex(const named_upgradable_mutex &); + named_upgradable_mutex &operator=(const named_upgradable_mutex &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global upgradable mutex with a name. + //!If the upgradable mutex can't be created throws interprocess_exception + named_upgradable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global upgradable mutex with a name. + //!If the upgradable mutex is created, this call is equivalent to + //!named_upgradable_mutex(create_only_t, ...) + //!If the upgradable mutex is already created, this call is equivalent to + //!named_upgradable_mutex(open_only_t, ... ). + named_upgradable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global upgradable mutex with a name if that upgradable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_upgradable_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global upgradable mutex with a name. + //!If the upgradable mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global upgradable mutex with a name. + //!If the upgradable mutex is created, this call is equivalent to + //!named_upgradable_mutex(create_only_t, ...) + //!If the upgradable mutex is already created, this call is equivalent to + //!named_upgradable_mutex(open_only_t, ... ). + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global upgradable mutex with a name if that upgradable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_upgradable_mutex(); + + //Exclusive locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, sharable or upgradable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!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 acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, sharable or upgradable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, sharable or + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise 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 + template + bool timed_lock(const TimePoint &abs_time); + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template 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 bool try_lock_for(const Duration &dur) + { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_sharable(); + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, 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_sharable(); + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise 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 + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_until(const TimePoint &abs_time) + { return this->timed_lock_sharable(abs_time); } + + //!Same as `timed_lock_sharable`, but this function is modeled after the + //!standard library interface. + template bool try_lock_shared_for(const Duration &dur) + { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + //Upgradable locking + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!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_upgradable(); + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! without waiting. If no other thread has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire upgradable ownership immediately returns true. + //! If it has to wait, 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_upgradable(); + + //!Requires: The calling thread does not own the mutex. + //! + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! waiting if necessary until no other thread has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires upgradable ownership, returns true. Otherwise 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 + template + bool timed_lock_upgradable(const TimePoint &abs_time); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable(); + + //Demotions + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! upgradable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_upgradable(); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_sharable(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock_sharable(); + + //Promotions + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! exclusive ownership. This operation will block until all threads with + //! sharable ownership release it. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to + //! acquire exclusive ownership. This operation will fail if there are threads + //! with sharable ownership, but it will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to acquire + //! exclusive ownership, waiting if necessary until abs_time. This operation will + //! fail if there are threads with sharable ownership or timeout reaches, but it + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + template + bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! exclusive ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock(); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! upgradable ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock_upgradable(); + + //!Erases a named upgradable mutex 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 named upgradable mutex 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 + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_upgradable_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_upgradable_mutex::~named_upgradable_mutex() +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_upgradable_mutex::named_upgradable_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif + +inline void named_upgradable_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_upgradable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_upgradable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_upgradable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +template +inline bool named_upgradable_mutex::timed_lock(const TimePoint &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_upgradable_mutex::lock_upgradable() +{ this->mutex()->lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_upgradable() +{ this->mutex()->unlock_upgradable(); } + +inline bool named_upgradable_mutex::try_lock_upgradable() +{ return this->mutex()->try_lock_upgradable(); } + +template +inline bool named_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) +{ return this->mutex()->timed_lock_upgradable(abs_time); } + +inline void named_upgradable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_upgradable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_upgradable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +template +inline bool named_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline void named_upgradable_mutex::unlock_and_lock_upgradable() +{ this->mutex()->unlock_and_lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_and_lock_sharable() +{ this->mutex()->unlock_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable() +{ this->mutex()->unlock_upgradable_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock() +{ this->mutex()->unlock_upgradable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock() +{ return this->mutex()->try_unlock_upgradable_and_lock(); } + +template +inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) +{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock() +{ return this->mutex()->try_unlock_sharable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() +{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); } + +inline bool named_upgradable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_upgradable_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP diff --git a/extern/boost/boost/interprocess/sync/null_mutex.hpp b/extern/boost/boost/interprocess/sync/null_mutex.hpp new file mode 100644 index 00000000000..cf12c9e6d8a --- /dev/null +++ b/extern/boost/boost/interprocess/sync/null_mutex.hpp @@ -0,0 +1,178 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NULL_MUTEX_HPP +#define BOOST_INTERPROCESS_NULL_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + + +//!\file +//!Describes null_mutex classes + +namespace boost { +namespace interprocess { + +//!Implements a mutex that simulates a mutex without doing any operation and +//!simulates a successful operation. +class null_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + null_mutex(const null_mutex&); + null_mutex &operator= (const null_mutex&); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Constructor. + //!Empty. + null_mutex() BOOST_NOEXCEPT {} + + //!Destructor. + //!Empty. + ~null_mutex(){} + + //!Simulates a mutex lock() operation. Empty function. + void lock(){} + + //!Simulates a mutex try_lock() operation. + //!Equivalent to "return true;" + bool try_lock() + { return true; } + + //!Simulates a mutex timed_lock() operation. + //!Equivalent to "return true;" + template + bool timed_lock(const TimePoint &) + { return true; } + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template + bool try_lock_until(const TimePoint &) + { return true; } + + //!Same as `timed_lock`, but this function is modeled after the + //!standard library interface. + template + bool try_lock_for(const Duration &) + { return true; } + + //!Simulates a mutex unlock() operation. + //!Empty function. + void unlock(){} + + //!Simulates a mutex lock_sharable() operation. + //!Empty function. + void lock_sharable(){} + + //!Same as `lock_sharable` but with a std-compatible interface + //! + void lock_shared() + { this->lock_sharable(); } + + //!Simulates a mutex try_lock_sharable() operation. + //!Equivalent to "return true;" + bool try_lock_sharable() + { return true; } + + //!Same as `try_lock_sharable` but with a std-compatible interface + //! + bool try_lock_shared() + { return this->try_lock_sharable(); } + + //!Simulates a mutex timed_lock_sharable() operation. + //!Equivalent to "return true;" + template + bool timed_lock_sharable(const TimePoint &) + { return true; } + + //!Simulates a mutex unlock_sharable() operation. + //!Empty function. + void unlock_sharable(){} + + //!Same as `unlock_sharable` but with a std-compatible interface + //! + void unlock_shared() + { this->unlock_sharable(); } + + //!Simulates a mutex lock_upgradable() operation. + //!Empty function. + void lock_upgradable(){} + + //!Simulates a mutex try_lock_upgradable() operation. + //!Equivalent to "return true;" + bool try_lock_upgradable() + { return true; } + + //!Simulates a mutex timed_lock_upgradable() operation. + //!Equivalent to "return true;" + template + bool timed_lock_upgradable(const TimePoint &) + { return true; } + + //!Simulates a mutex unlock_upgradable() operation. + //!Empty function. + void unlock_upgradable(){} + + //!Simulates unlock_and_lock_upgradable(). + //!Empty function. + void unlock_and_lock_upgradable(){} + + //!Simulates unlock_and_lock_sharable(). + //!Empty function. + void unlock_and_lock_sharable(){} + + //!Simulates unlock_upgradable_and_lock_sharable(). + //!Empty function. + void unlock_upgradable_and_lock_sharable(){} + + //Promotions + + //!Simulates unlock_upgradable_and_lock(). + //!Empty function. + void unlock_upgradable_and_lock(){} + + //!Simulates try_unlock_upgradable_and_lock(). + //!Equivalent to "return true;" + bool try_unlock_upgradable_and_lock() + { return true; } + + //!Simulates timed_unlock_upgradable_and_lock(). + //!Equivalent to "return true;" + template + bool timed_unlock_upgradable_and_lock(const TimePoint &) + { return true; } + + //!Simulates try_unlock_sharable_and_lock(). + //!Equivalent to "return true;" + bool try_unlock_sharable_and_lock() + { return true; } + + //!Simulates try_unlock_sharable_and_lock_upgradable(). + //!Equivalent to "return true;" + bool try_unlock_sharable_and_lock_upgradable() + { return true; } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NULL_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/condition.hpp b/extern/boost/boost/interprocess/sync/posix/condition.hpp new file mode 100644 index 00000000000..5b3b7526617 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/condition.hpp @@ -0,0 +1,218 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_CONDITION_HPP +#define BOOST_INTERPROCESS_POSIX_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class posix_condition +{ + //Non-copyable + posix_condition(const posix_condition &); + posix_condition &operator=(const posix_condition &); + + public: + //!Constructs a posix_condition. On error throws interprocess_exception. + posix_condition(); + + //!Destroys *this + //!liberating system resources. + ~posix_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + this->do_wait(*lock.mutex()); + } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + this->do_wait(*lock.mutex()); + } + + //!Releases the lock on the posix_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + 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(ipcdetail::is_pos_infinity(abs_time)){ + this->wait(lock); + return true; + } + return this->do_timed_wait(abs_time, *lock.mutex()); + } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + 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(ipcdetail::is_pos_infinity(abs_time)){ + this->wait(lock, pred); + return true; + } + while (!pred()){ + if (!this->do_timed_wait(abs_time, *lock.mutex())) + return pred(); + } + return true; + } + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) + { return this->timed_wait(lock, abs_time, pred); } + + template + 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 + 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); + + template + bool do_timed_wait(const TimePoint &abs_time, posix_mutex &mut); + + private: + pthread_cond_t m_condition; +}; + +inline posix_condition::posix_condition() +{ + int res; + pthread_condattr_t cond_attr; + res = pthread_condattr_init(&cond_attr); + if(res != 0){ + throw interprocess_exception("pthread_condattr_init failed"); + } + res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + if(res != 0){ + pthread_condattr_destroy(&cond_attr); + throw interprocess_exception(res); + } + res = pthread_cond_init(&m_condition, &cond_attr); + pthread_condattr_destroy(&cond_attr); + if(res != 0){ + throw interprocess_exception(res); + } +} + +inline posix_condition::~posix_condition() +{ + int res = 0; + res = pthread_cond_destroy(&m_condition); + BOOST_ASSERT(res == 0); (void)res; +} + +inline void posix_condition::notify_one() +{ + int res = 0; + res = pthread_cond_signal(&m_condition); + BOOST_ASSERT(res == 0); (void)res; +} + +inline void posix_condition::notify_all() +{ + int res = 0; + res = pthread_cond_broadcast(&m_condition); + BOOST_ASSERT(res == 0); (void)res; +} + +inline void posix_condition::do_wait(posix_mutex &mut) +{ + pthread_mutex_t* pmutex = &mut.m_mut; + int res = 0; + res = pthread_cond_wait(&m_condition, pmutex); + BOOST_ASSERT(res == 0); (void)res; +} + +template +inline bool posix_condition::do_timed_wait + (const TimePoint &abs_time, posix_mutex &mut) +{ + 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); + BOOST_ASSERT(res == 0 || res == ETIMEDOUT); + + return res != ETIMEDOUT; +} + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/mutex.hpp b/extern/boost/boost/interprocess/sync/posix/mutex.hpp new file mode 100644 index 00000000000..8716f79b799 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/mutex.hpp @@ -0,0 +1,188 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP +#define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS +# include +# include +#endif +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class posix_condition; + +class posix_mutex +{ + posix_mutex(const posix_mutex &); + posix_mutex &operator=(const posix_mutex &); + public: + + posix_mutex(); + ~posix_mutex(); + + void lock(); + bool try_lock(); + template bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + void unlock(); + + friend class posix_condition; + + private: + pthread_mutex_t m_mut; +}; + +inline posix_mutex::posix_mutex() +{ + mutexattr_wrapper mut_attr; + mutex_initializer mut(m_mut, mut_attr); + mut.release(); +} + +inline posix_mutex::~posix_mutex() +{ + int res = pthread_mutex_destroy(&m_mut); + BOOST_ASSERT(res == 0);(void)res; +} + +inline void posix_mutex::lock() +{ + 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; +} + +template +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(ipcdetail::is_pos_infinity(abs_time)){ + this->lock(); + return true; + } + 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; + + #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS + + return ipcdetail::try_based_timed_lock(*this, abs_time); + + #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + +inline void posix_mutex::unlock() +{ + int res = pthread_mutex_unlock(&m_mut); + (void)res; + BOOST_ASSERT(res == 0); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp b/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp new file mode 100644 index 00000000000..bdf3ea4dec3 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp @@ -0,0 +1,126 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class named_condition; + +class posix_named_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + posix_named_mutex(); + posix_named_mutex(const posix_named_mutex &); + posix_named_mutex &operator=(const posix_named_mutex &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + posix_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + posix_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + posix_named_mutex(open_only_t, const char *name); + + ~posix_named_mutex(); + + void unlock(); + void lock(); + bool try_lock(); + + template + bool timed_lock(const TimePoint &abs_time); + + template + bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template + bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + static bool remove(const char *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + + posix_named_semaphore m_sem; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm) + : m_sem(create_only, name, 1, perm) +{} + +inline posix_named_mutex::posix_named_mutex(open_or_create_t, const char *name, const permissions &perm) + : m_sem(open_or_create, name, 1, perm) +{} + +inline posix_named_mutex::posix_named_mutex(open_only_t, const char *name) + : m_sem(open_only, name) +{} + +inline void posix_named_mutex::dont_close_on_destruction() +{ interprocess_tester::dont_close_on_destruction(m_sem); } + +inline posix_named_mutex::~posix_named_mutex() +{} + +inline void posix_named_mutex::lock() +{ m_sem.wait(); } + +inline void posix_named_mutex::unlock() +{ m_sem.post(); } + +inline bool posix_named_mutex::try_lock() +{ return m_sem.try_wait(); } + +template +inline bool posix_named_mutex::timed_lock(const TimePoint &abs_time) +{ return m_sem.timed_wait(abs_time); } + +inline bool posix_named_mutex::remove(const char *name) +{ return posix_named_semaphore::remove(name); } + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp new file mode 100644 index 00000000000..410e76f9a4f --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +namespace ipcdetail { + +class posix_named_semaphore +{ + posix_named_semaphore(); + posix_named_semaphore(const posix_named_semaphore&); + posix_named_semaphore &operator= (const posix_named_semaphore &); + + public: + posix_named_semaphore + (create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()) + { semaphore_open(mp_sem, DoCreate, name, initialCount, perm); } + + posix_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()) + { semaphore_open(mp_sem, DoOpenOrCreate, name, initialCount, perm); } + + posix_named_semaphore(open_only_t, const char *name) + { semaphore_open(mp_sem, DoOpen, name); } + + ~posix_named_semaphore() + { + if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED) + semaphore_close(mp_sem); + } + + void post() + { semaphore_post(mp_sem); } + + void wait() + { semaphore_wait(mp_sem); } + + bool try_wait() + { return semaphore_try_wait(mp_sem); } + + template + bool timed_wait(const TimePoint &abs_time) + { return semaphore_timed_wait(mp_sem, abs_time); } + + static bool remove(const char *name) + { return semaphore_unlink(name); } + + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; } + + sem_t *mp_sem; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp b/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp new file mode 100644 index 00000000000..f247d5e5961 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -0,0 +1,176 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_PTHREAD_HELPERS_HPP +#define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + + #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + + //!Makes pthread_mutexattr_t cleanup easy when using exceptions + struct mutexattr_wrapper + { + //!Constructor + mutexattr_wrapper(bool recursive = false) + { + 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 ) + #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES + || pthread_mutexattr_setrobust(&m_attr, PTHREAD_MUTEX_ROBUST) != 0 + #endif + ) + throw interprocess_exception("pthread_mutexattr_xxxx failed"); + } + + //!Destructor + ~mutexattr_wrapper() { pthread_mutexattr_destroy(&m_attr); } + + //!This allows using mutexattr_wrapper as pthread_mutexattr_t + operator pthread_mutexattr_t&() { return m_attr; } + + pthread_mutexattr_t m_attr; + }; + + //!Makes pthread_condattr_t cleanup easy when using exceptions + struct condattr_wrapper + { + //!Constructor + condattr_wrapper() + { + if(pthread_condattr_init(&m_attr)!=0 || + pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) + throw interprocess_exception("pthread_condattr_xxxx failed"); + } + + //!Destructor + ~condattr_wrapper() { pthread_condattr_destroy(&m_attr); } + + //!This allows using condattr_wrapper as pthread_condattr_t + operator pthread_condattr_t&(){ return m_attr; } + + pthread_condattr_t m_attr; + }; + + //!Makes initialized pthread_mutex_t cleanup easy when using exceptions + class mutex_initializer + { + public: + //!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex + mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr) + : mp_mut(&mut) + { + if(pthread_mutex_init(mp_mut, &mut_attr) != 0) + throw interprocess_exception("pthread_mutex_init failed"); + } + + ~mutex_initializer() { if(mp_mut) pthread_mutex_destroy(mp_mut); } + + void release() {mp_mut = 0; } + + private: + pthread_mutex_t *mp_mut; + }; + + //!Makes initialized pthread_cond_t cleanup easy when using exceptions + class condition_initializer + { + public: + condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) + : mp_cond(&cond) + { + if(pthread_cond_init(mp_cond, &cond_attr)!= 0) + throw interprocess_exception("pthread_cond_init failed"); + } + + ~condition_initializer() { if(mp_cond) pthread_cond_destroy(mp_cond); } + + void release() { mp_cond = 0; } + + private: + pthread_cond_t *mp_cond; + }; + + #endif // #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + + #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + + //!Makes pthread_barrierattr_t cleanup easy when using exceptions + struct barrierattr_wrapper + { + //!Constructor + barrierattr_wrapper() + { + if(pthread_barrierattr_init(&m_attr)!=0 || + pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) + throw interprocess_exception("pthread_barrierattr_xxx failed"); + } + + //!Destructor + ~barrierattr_wrapper() { pthread_barrierattr_destroy(&m_attr); } + + //!This allows using mutexattr_wrapper as pthread_barrierattr_t + operator pthread_barrierattr_t&() { return m_attr; } + + pthread_barrierattr_t m_attr; + }; + + //!Makes initialized pthread_barrier_t cleanup easy when using exceptions + class barrier_initializer + { + public: + //!Constructor. Takes barrier attributes to initialize the barrier + barrier_initializer(pthread_barrier_t &mut, + pthread_barrierattr_t &mut_attr, + unsigned int count) + : mp_barrier(&mut) + { + if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0) + throw interprocess_exception("pthread_barrier_init failed"); + } + + ~barrier_initializer() { if(mp_barrier) pthread_barrier_destroy(mp_barrier); } + + void release() {mp_barrier = 0; } + + private: + pthread_barrier_t *mp_barrier; + }; + + #endif //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + +}//namespace ipcdetail + +}//namespace interprocess + +}//namespace boost + +#include + +#endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp new file mode 100644 index 00000000000..20e654e3ddc --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp @@ -0,0 +1,175 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS +# include +# include +#endif +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class posix_recursive_mutex +{ + posix_recursive_mutex(const posix_recursive_mutex &); + posix_recursive_mutex &operator=(const posix_recursive_mutex &); + public: + + posix_recursive_mutex(); + ~posix_recursive_mutex(); + + void lock(); + bool try_lock(); + template bool timed_lock(const TimePoint &abs_time); + void unlock(); + + private: + pthread_mutex_t m_mut; +}; + +inline posix_recursive_mutex::posix_recursive_mutex() +{ + mutexattr_wrapper mut_attr(true); + mutex_initializer mut(m_mut, mut_attr); + mut.release(); +} + +inline posix_recursive_mutex::~posix_recursive_mutex() +{ + int res = pthread_mutex_destroy(&m_mut); + BOOST_ASSERT(res == 0);(void)res; +} + +inline void posix_recursive_mutex::lock() +{ + 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_recursive_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); +} + +template +inline bool posix_recursive_mutex::timed_lock(const TimePoint &abs_time) +{ + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + //Posix does not support infinity absolute time so handle it here + if(ipcdetail::is_pos_infinity(abs_time)){ + this->lock(); + return true; + } + + 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; + + #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS + + return ipcdetail::try_based_timed_lock(*this, abs_time); + + #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + +inline void posix_recursive_mutex::unlock() +{ + int res = 0; + res = pthread_mutex_unlock(&m_mut); + BOOST_ASSERT(res == 0); (void)res; +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/semaphore.hpp b/extern/boost/boost/interprocess/sync/posix/semaphore.hpp new file mode 100644 index 00000000000..bf64d430da7 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/semaphore.hpp @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class posix_semaphore +{ + posix_semaphore(); + posix_semaphore(const posix_semaphore&); + posix_semaphore &operator= (const posix_semaphore &); + + public: + posix_semaphore(unsigned int initialCount) + { semaphore_init(&m_sem, initialCount); } + + ~posix_semaphore() + { semaphore_destroy(&m_sem); } + + void post() + { semaphore_post(&m_sem); } + + void wait() + { semaphore_wait(&m_sem); } + + bool try_wait() + { return semaphore_try_wait(&m_sem); } + + template + bool timed_wait(const TimePoint &abs_time) + { return semaphore_timed_wait(&m_sem, abs_time); } + + private: + sem_t m_sem; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp new file mode 100644 index 00000000000..c77397ae775 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -0,0 +1,254 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SEMAPHORE_WRAPPER_HPP +#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include //O_CREAT, O_*... +#include //close +#include //std::string +#include //sem_* family, SEM_VALUE_MAX +#include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, +#include + +#ifdef SEM_FAILED +#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(SEM_FAILED)) +#else +#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(-1)) +#endif + +#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS +#include +#else +#include +#include +#include +#endif + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES + +inline bool semaphore_open + (sem_t *&handle, create_enum_t type, const char *origname, + unsigned int count = 0, const permissions &perm = permissions()) +{ + std::string name; + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + add_leading_slash(origname, name); + #else + create_shared_dir_cleaning_old_and_get_filepath(origname, name); + #endif + + //Create new mapping + int oflag = 0; + switch(type){ + case DoOpen: + { + //No addition + handle = ::sem_open(name.c_str(), oflag); + } + break; + case DoOpenOrCreate: + case DoCreate: + { + while(1){ + oflag = (O_CREAT | O_EXCL); + handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count); + if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){ + //We can't change semaphore permissions! + //::fchmod(handle, perm.get_permissions()); + break; + } + else if(errno == EEXIST && type == DoOpenOrCreate){ + oflag = 0; + if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED + || (errno != ENOENT) ){ + break; + } + } + else{ + break; + } + } + } + break; + default: + { + error_info err(other_error); + throw interprocess_exception(err); + } + } + + //Check for error + if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){ + throw interprocess_exception(error_info(errno)); + } + + return true; +} + +inline void semaphore_close(sem_t *handle) +{ + int ret = sem_close(handle); + if(ret != 0){ + BOOST_ASSERT(0); + } +} + +inline bool semaphore_unlink(const char *semname) +{ + BOOST_TRY{ + std::string sem_str; + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + add_leading_slash(semname, sem_str); + #else + shared_filepath(semname, sem_str); + #endif + return 0 == sem_unlink(sem_str.c_str()); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END +} + +#endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES + +#ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES + +inline void semaphore_init(sem_t *handle, unsigned int initialCount) +{ + int ret = sem_init(handle, 1, initialCount); + //According to SUSV3 version 2003 edition, the return value of a successful + //sem_init call is not defined, but -1 is returned on failure. + //In the future, a successful call might be required to return 0. + if(ret == -1){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +inline void semaphore_destroy(sem_t *handle) +{ + int ret = sem_destroy(handle); + if(ret != 0){ + BOOST_ASSERT(0); + } +} + +#endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES + +inline void semaphore_post(sem_t *handle) +{ + int ret = sem_post(handle); + if(ret != 0){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +inline void semaphore_wait(sem_t *handle) +{ + int ret = sem_wait(handle); + if(ret != 0){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +inline bool semaphore_try_wait(sem_t *handle) +{ + int res = sem_trywait(handle); + if(res == 0) + return true; + if(system_error_code() == EAGAIN){ + return false; + } + error_info err = system_error_code(); + throw interprocess_exception(err); +} + +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS + +struct semaphore_wrapper_try_wrapper +{ + explicit semaphore_wrapper_try_wrapper(sem_t *handle) + : m_handle(handle) + {} + + void wait() + { semaphore_wait(m_handle); } + + bool try_wait() + { return semaphore_try_wait(m_handle); } + + private: + sem_t *m_handle; +}; + +#endif + +template +inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time) +{ + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + //Posix does not support infinity absolute time so handle it here + if(ipcdetail::is_pos_infinity(abs_time)){ + semaphore_wait(handle); + return true; + } + + timespec tspec = timepoint_to_timespec(abs_time); + for (;;){ + int res = sem_timedwait(handle, &tspec); + if(res == 0) + return true; + if (res > 0){ + //buggy glibc, copy the returned error code to errno + errno = res; + } + if(system_error_code() == ETIMEDOUT){ + return false; + } + error_info err = system_error_code(); + throw interprocess_exception(err); + } + return false; + #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + + semaphore_wrapper_try_wrapper swtw(handle); + ipcdetail::lock_to_wait lw(swtw); + return ipcdetail::try_based_timed_lock(lw, abs_time); + + #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp b/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp new file mode 100644 index 00000000000..6f5d795cc2d --- /dev/null +++ b/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp @@ -0,0 +1,91 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { + +namespace interprocess { + +namespace ipcdetail { + +template +inline timespec timepoint_to_timespec ( const TimePoint &tm + , typename enable_if_ptime::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(duration.total_seconds()); + ts.tv_nsec = static_cast(duration.total_nanoseconds() % 1000000000); + return ts; +} + +inline timespec timepoint_to_timespec (const ustime &tm) +{ + timespec ts; + const boost::uint64_t micros = tm.get_microsecs(); + ts.tv_sec = static_cast(micros /1000000u); + ts.tv_nsec = static_cast((micros%1000000u)*1000u); + return ts; +} + +template +inline timespec timepoint_to_timespec ( const TimePoint &tm + , typename enable_if_time_point::type * = 0) +{ + typedef typename TimePoint::duration duration_t; + duration_t d(tm.time_since_epoch()); + + timespec ts; + const typename duration_t::rep cnt = d.count(); + + BOOST_IF_CONSTEXPR(duration_t::period::num == 1 && duration_t::period::den == 1000000000) + { + + ts.tv_sec = static_cast(cnt /duration_t::period::den); + ts.tv_nsec = static_cast(cnt%duration_t::period::den); + } + else + { + const double factor = double(duration_t::period::num)/double(duration_t::period::den); + const double res = double(cnt)*factor; + ts.tv_sec = static_cast(res); + ts.tv_nsec = static_cast(1000000000.0*(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/extern/boost/boost/interprocess/sync/sharable_lock.hpp b/extern/boost/boost/interprocess/sync/sharable_lock.hpp new file mode 100644 index 00000000000..7bdcd97b76d --- /dev/null +++ b/extern/boost/boost/interprocess/sync/sharable_lock.hpp @@ -0,0 +1,351 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// This interface is inspired by Howard Hinnant's lock proposal. +// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP +#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the upgradable_lock class that serves to acquire the upgradable +//!lock of a mutex. + +namespace boost { +namespace interprocess { + + +//!sharable_lock is meant to carry out the tasks for sharable-locking +//!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking +//!(recursive or not) for the Mutex. The Mutex need not supply all of this +//!functionality. If the client of sharable_lock does not use functionality which +//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among +//!sharable_locks, and a single upgradable_lock. sharable_lock does not support +//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock, +//!upgradable_lock and scoped_lock via transfer_lock syntax.*/ +template +class sharable_lock +{ + public: + typedef SharableMutex mutex_type; + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef sharable_lock this_type; + explicit sharable_lock(scoped_lock&); + typedef bool this_type::*unspecified_bool_type; + BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Effects: Default constructs a sharable_lock. + //!Postconditions: owns() == false and mutex() == 0. + sharable_lock() BOOST_NOEXCEPT + : mp_mutex(0), m_locked(false) + {} + + //!Effects: m.lock_sharable(). + //!Postconditions: owns() == true and mutex() == &m. + //!Notes: The constructor will take sharable-ownership of the mutex. If + //! another thread already owns the mutex with exclusive ownership + //! (scoped_lock), this thread will block until the mutex is released. + //! If another thread owns the mutex with sharable or upgradable ownership, + //! then no blocking will occur. Whether or not this constructor handles + //! recursive locking depends upon the mutex. + explicit sharable_lock(mutex_type& m) + : mp_mutex(&m), m_locked(false) + { mp_mutex->lock_sharable(); m_locked = true; } + + //!Postconditions: owns() == false, and mutex() == &m. + //!Notes: The constructor will not take ownership of the mutex. There is no effect + //! required on the referenced mutex. + sharable_lock(mutex_type& m, defer_lock_type) + : mp_mutex(&m), m_locked(false) + {} + + //!Postconditions: owns() == true, and mutex() == &m. + //!Notes: The constructor will suppose that the mutex is already sharable + //! locked. There is no effect required on the referenced mutex. + sharable_lock(mutex_type& m, accept_ownership_type) + : mp_mutex(&m), m_locked(true) + {} + + //!Effects: m.try_lock_sharable() + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.try_lock_sharable() executed within the constructor. + //!Notes: The constructor will take sharable-ownership of the mutex if it + //! can do so without waiting. Whether or not this constructor handles + //! recursive locking depends upon the mutex. If the mutex_type does not + //! support try_lock_sharable, this constructor will fail at compile + //! time if instantiated, but otherwise have no effect. + sharable_lock(mutex_type& m, try_to_lock_type) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->try_lock_sharable(); } + + //!Effects: m.timed_lock_sharable(abs_time) + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.timed_lock_sharable() executed within the constructor. + //!Notes: The constructor will take sharable-ownership of the mutex if it + //! can do so within the time specified. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support timed_lock_sharable, this constructor will fail at + //! compile time if instantiated, but otherwise have no effect. + template + sharable_lock(mutex_type& m, const TimePoint& abs_time) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->timed_lock_sharable(abs_time); } + + //!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns() + //! before the construction. upgr.owns() == false after the construction. + //!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this + //! sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then + //! neither will this sharable_lock. Only a moved sharable_lock's will match this + //! signature. An non-moved sharable_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. + sharable_lock(BOOST_RV_REF(sharable_lock) upgr) BOOST_NOEXCEPT + : mp_mutex(0), m_locked(upgr.owns()) + { mp_mutex = upgr.release(); } + + //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the + //! referenced mutex. + //!Postconditions: mutex() == the value upgr.mutex() had before the construction. + //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction. + //! upgr.owns() == false after the construction. + //!Notes: If upgr is locked, this constructor will lock this sharable_lock while + //! unlocking upgr. Only a moved sharable_lock's will match this + //! signature. An non-moved upgradable_lock can be moved with the expression: + //! "boost::move(lock);".*/ + template + sharable_lock(BOOST_RV_REF(upgradable_lock) upgr + , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr; + if(u_lock.owns()){ + u_lock.mutex()->unlock_upgradable_and_lock_sharable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + + //!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the + //! referenced mutex. + //!Postconditions: mutex() == the value scop.mutex() had before the construction. + //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the + //! construction, scop.owns() == false. + //!Notes: If scop is locked, this constructor will transfer the exclusive ownership + //! to a sharable-ownership of this sharable_lock. + //! Only a moved scoped_lock's will match this + //! signature. An non-moved scoped_lock can be moved with the expression: + //! "boost::move(lock);". + template + sharable_lock(BOOST_RV_REF(scoped_lock) scop + , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) + : mp_mutex(0), m_locked(false) + { + scoped_lock &e_lock = scop; + if(e_lock.owns()){ + e_lock.mutex()->unlock_and_lock_sharable(); + m_locked = true; + } + mp_mutex = e_lock.release(); + } + + //!Effects: if (owns()) mp_mutex->unlock_sharable(). + //!Notes: The destructor behavior ensures that the mutex lock is not leaked. + ~sharable_lock() + { + BOOST_TRY{ + if(m_locked && mp_mutex) mp_mutex->unlock_sharable(); + } + BOOST_CATCH(...){} BOOST_CATCH_END + } + + //!Effects: If owns() before the call, then unlock_sharable() is called on mutex(). + //! *this gets the state of upgr and upgr gets set to a default constructed state. + //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex + //! before the assignment. In this case, this will own the mutex after the assignment + //! (and upgr will not), but the mutex's lock count will be decremented by one. + sharable_lock &operator=(BOOST_RV_REF(sharable_lock) upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.owns(); + mp_mutex = upgr.release(); + return *this; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls lock_sharable() on the referenced mutex. + //!Postconditions: owns() == true. + //!Notes: The sharable_lock changes from a state of not owning the + //! mutex, to owning the mutex, blocking if necessary. + void lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + mp_mutex->lock_sharable(); + m_locked = true; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls try_lock_sharable() on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->try_lock_sharable(). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if blocking was not required. If the + //! mutex_type does not support try_lock_sharable(), this function will + //! fail at compile time if instantiated, but otherwise have no effect. + bool try_lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_sharable(); + return m_locked; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls timed_lock_sharable(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_sharable(elps_time). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time interval. If the mutex_type does not support + //! timed_lock_sharable(), this function will fail at compile time if + //! instantiated, but otherwise have no effect. + template + bool timed_lock(const TimePoint& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->timed_lock_sharable(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_sharable(elps_time). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time interval. If the mutex_type does not support + //! timed_lock_sharable(), this function will fail at compile time if + //! instantiated, but otherwise have no effect. + //! + //!Note: Similar to timed_lock, but with a std-like interface + template + bool try_lock_until(const TimePoint& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_shared_until(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_sharable(elps_time). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time interval. If the mutex_type does not support + //! timed_lock_sharable(), this function will fail at compile time if + //! instantiated, but otherwise have no effect. + //! + //!Note: Similar to timed_lock, but with a std-like interface + template + bool try_lock_for(const Duration& dur) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_shared_for(dur); + return m_locked; + } + + //!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception. + //! Calls unlock_sharable() on the referenced mutex. + //!Postconditions: owns() == false. + //!Notes: The sharable_lock changes from a state of owning the mutex, to + //! not owning the mutex. + void unlock() + { + if(!mp_mutex || !m_locked) + throw lock_exception(); + mp_mutex->unlock_sharable(); + m_locked = false; + } + + //!Effects: Returns true if this scoped_lock has + //!acquired the referenced mutex. + bool owns() const BOOST_NOEXCEPT + { return m_locked && mp_mutex; } + + //!Conversion to bool. + //!Returns owns(). + 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 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() BOOST_NOEXCEPT + { + mutex_type *mut = mp_mutex; + mp_mutex = 0; + m_locked = false; + return mut; + } + + //!Effects: Swaps state with moved lock. + //!Throws: Nothing. + void swap(sharable_lock &other) BOOST_NOEXCEPT + { + (simple_swap)(mp_mutex, other.mp_mutex); + (simple_swap)(m_locked, other.m_locked); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + mutex_type *mp_mutex; + bool m_locked; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_condition.hpp b/extern/boost/boost/interprocess/sync/shm/named_condition.hpp new file mode 100644 index 00000000000..c9e7550cf38 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_condition.hpp @@ -0,0 +1,348 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SHM_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + #include + #include + #include +#else + #include +#endif + + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +class interprocess_tester; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class shm_named_condition +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + shm_named_condition(); + shm_named_condition(const shm_named_condition &); + shm_named_condition &operator=(const shm_named_condition &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + shm_named_condition(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition(open_only_t, ... ) + //!Does not throw + shm_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_condition(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock); + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred); + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time); + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred); + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + 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 + 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 + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } + + //!Erases a named condition 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 named condition 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) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + class internal_condition_members + { + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; + + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } + + private: + mutex_type m_mtx; + condvar_type m_cond; + }; + + typedef ipcdetail::condition_any_wrapper internal_condition; + #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + typedef interprocess_condition internal_condition; + #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + + internal_condition &internal_cond() + { return *static_cast(m_shmem.get_user_address()); } + + friend class boost::interprocess::ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + + template friend class boost::interprocess::ipcdetail::named_creation_functor; + typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_condition::~shm_named_condition() +{} + +inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_condition::shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void shm_named_condition::dont_close_on_destruction() +{ interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void shm_named_condition::notify_one() +{ this->internal_cond().notify_one(); } + +inline void shm_named_condition::notify_all() +{ this->internal_cond().notify_all(); } + +template +inline void shm_named_condition::wait(L& lock) +{ this->internal_cond().wait(lock); } + +template +inline void shm_named_condition::wait(L& lock, Pr pred) +{ this->internal_cond().wait(lock, pred); } + +template +inline bool shm_named_condition::timed_wait + (L& lock, const TimePoint &abs_time) +{ return this->internal_cond().timed_wait(lock, abs_time); } + +template +inline bool shm_named_condition::timed_wait + (L& lock, const TimePoint &abs_time, Pr pred) +{ return this->internal_cond().timed_wait(lock, abs_time, pred); } + +inline bool shm_named_condition::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_condition::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp new file mode 100644 index 00000000000..31f621313ba --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp @@ -0,0 +1,226 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SHM_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +class interprocess_tester; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class shm_named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + shm_named_condition_any(); + shm_named_condition_any(const shm_named_condition_any &); + shm_named_condition_any &operator=(const shm_named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + template + shm_named_condition_any(create_only_t, const CharT *name, const permissions &perm = permissions()) + : m_shmem (create_only_t() + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition_any(open_only_t, ... ) + //!Does not throw + template + shm_named_condition_any(open_or_create_t, const CharT *name, const permissions &perm = permissions()) + : m_shmem (open_or_create_t() + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + template + shm_named_condition_any(open_only_t, const CharT *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) + {} + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { this->internal_cond().notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { this->internal_cond().notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { this->internal_cond().wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { this->internal_cond().wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!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 + bool timed_wait(L& lock, const TimePoint &abs_time) + { return this->internal_cond().timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { return this->internal_cond().timed_wait(lock, abs_time, pred); } + + //!Same as `timed_wait`, but this function is modeled after the + //!standard library interface. + template + 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 + 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 + 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 + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + template + static bool remove(const CharT *name) + { return shared_memory_object::remove(name); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + class internal_condition_members + { + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; + + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } + + private: + mutex_type m_mtx; + condvar_type m_cond; + }; + + typedef ipcdetail::condition_any_wrapper internal_condition; + + internal_condition &internal_cond() + { return *static_cast(m_shmem.get_user_address()); } + + friend class boost::interprocess::ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { interprocess_tester::dont_close_on_destruction(m_shmem); } + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + + template friend class boost::interprocess::ipcdetail::named_creation_functor; + typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp b/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp new file mode 100644 index 00000000000..137a1a8ea7d --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-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_SYNC_NAMED_CREATION_FUNCTOR_HPP +#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +struct named_creation_functor_no_arg{}; + +template +class named_creation_functor +{ + typedef named_creation_functor_no_arg no_arg_t; + public: + named_creation_functor(create_enum_t type, Arg arg = Arg()) + : m_creation_type(type), m_arg(arg){} + + template + void construct(void *address, typename enable_if_c::value>::type * = 0) const + { ::new(address, boost_container_new_t())T; } + + template + void construct(void *address, typename enable_if_c::value>::type * = 0) const + { ::new(address, boost_container_new_t())T(m_arg); } + + bool operator()(void *address, std::size_t, bool created) const + { + switch(m_creation_type){ + case DoOpen: + return true; + break; + case DoCreate: + case DoOpenOrCreate: + if(created){ + construct(address); + } + return true; + break; + + default: + return false; + break; + } + } + + static std::size_t get_min_size() + { return sizeof(T); } + + private: + create_enum_t m_creation_type; + Arg m_arg; +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#endif //BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp new file mode 100644 index 00000000000..123f26ace2d --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp @@ -0,0 +1,259 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SHM_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//!\file +//!Describes a named mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class named_condition; + +//!A mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named mutex. +class shm_named_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + shm_named_mutex(); + shm_named_mutex(const shm_named_mutex &); + shm_named_mutex &operator=(const shm_named_mutex &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Creates a global interprocess_mutex with a name. + //!Throws interprocess_exception on error. + shm_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!shm_named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!shm_named_mutex(open_only_t, ... ) + //!Does not throw + shm_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global interprocess_mutex with a name. + //!Throws interprocess_exception on error. + shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!shm_named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!shm_named_mutex(open_only_t, ... ) + //!Does not throw + shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_mutex(); + + //!Unlocks a previously locked + //!interprocess_mutex. + void unlock(); + + //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked. + //!Throws interprocess_exception if a severe error is found + void lock(); + + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found + bool try_lock(); + + //!Tries to lock the interprocess_mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + template + bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + //!Erases a named mutex 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 named mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const wchar_t *name); + + #endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + typedef interprocess_mutex internal_mutex_type; + interprocess_mutex &internal_mutex() + { return *static_cast(m_shmem.get_user_address()); } + + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void shm_named_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline shm_named_mutex::~shm_named_mutex() +{} + +inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only_t() + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create_t() + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_mutex::shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only_t() + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create_t() + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_only_t, const wchar_t *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void shm_named_mutex::lock() +{ this->internal_mutex().lock(); } + +inline void shm_named_mutex::unlock() +{ this->internal_mutex().unlock(); } + +inline bool shm_named_mutex::try_lock() +{ return this->internal_mutex().try_lock(); } + +template +inline bool shm_named_mutex::timed_lock(const TimePoint &abs_time) +{ return this->internal_mutex().timed_lock(abs_time); } + +inline bool shm_named_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp new file mode 100644 index 00000000000..437588ea2b8 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -0,0 +1,249 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SHM_NAMED_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named shm_named_recursive_mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +class interprocess_tester; +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +class shm_named_recursive_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + shm_named_recursive_mutex(); + shm_named_recursive_mutex(const shm_named_recursive_mutex &); + shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!shm_named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!shm_named_recursive_mutex(open_only_t, ... ) + //!Does not throw + shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_recursive_mutex(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!shm_named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!shm_named_recursive_mutex(open_only_t, ... ) + //!Does not throw + shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_recursive_mutex(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_recursive_mutex(); + + //!Unlocks a previously locked + //!shm_named_recursive_mutex. + void unlock(); + + //!Locks shm_named_recursive_mutex, sleeps when shm_named_recursive_mutex is already locked. + //!Throws interprocess_exception if a severe error is found. + void lock(); + + //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found. + bool try_lock(); + + //!Tries to lock the shm_named_recursive_mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + template + bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + //!Erases a named recursive mutex + //!from the system + static bool remove(const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named recursive mutex + //!from the system + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + + interprocess_recursive_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline shm_named_recursive_mutex::~shm_named_recursive_mutex() +{} + +inline void shm_named_recursive_mutex::dont_close_on_destruction() +{ interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only_t() + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create_t() + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const char *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only_t() + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create_t() + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const wchar_t *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void shm_named_recursive_mutex::lock() +{ this->mutex()->lock(); } + +inline void shm_named_recursive_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool shm_named_recursive_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +template +inline bool shm_named_recursive_mutex::timed_lock(const TimePoint &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline bool shm_named_recursive_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_recursive_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp new file mode 100644 index 00000000000..9977888bd89 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp @@ -0,0 +1,198 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (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_SHM_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class shm_named_semaphore +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + shm_named_semaphore(); + shm_named_semaphore(const shm_named_semaphore &); + shm_named_semaphore &operator=(const shm_named_semaphore &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_only_t, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + shm_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + ~shm_named_semaphore(); + + void post(); + void wait(); + bool try_wait(); + template bool timed_wait(const TimePoint &abs_time); + + static bool remove(const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + static bool remove(const wchar_t *name); + + #endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + + interprocess_semaphore *semaphore() const + { return static_cast(m_shmem.get_user_address()); } + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline shm_named_semaphore::~shm_named_semaphore() +{} + +inline void shm_named_semaphore::dont_close_on_destruction() +{ interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline shm_named_semaphore::shm_named_semaphore + (create_only_t, const char *name, unsigned int initialCount, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen, 0)) +{} + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_semaphore::shm_named_semaphore + (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen, 0)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline void shm_named_semaphore::post() +{ semaphore()->post(); } + +inline void shm_named_semaphore::wait() +{ semaphore()->wait(); } + +inline bool shm_named_semaphore::try_wait() +{ return semaphore()->try_wait(); } + +template +inline bool shm_named_semaphore::timed_wait(const TimePoint &abs_time) +{ return semaphore()->timed_wait(abs_time); } + +inline bool shm_named_semaphore::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_semaphore::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp new file mode 100644 index 00000000000..af21f983ba1 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp @@ -0,0 +1,360 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NAMED_UPGRADABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named upgradable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) +namespace ipcdetail{ class interprocess_tester; } +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +class named_condition; + +//!A upgradable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named upgradable mutex. +class named_upgradable_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable + named_upgradable_mutex(); + named_upgradable_mutex(const named_upgradable_mutex &); + named_upgradable_mutex &operator=(const named_upgradable_mutex &); + friend class named_condition; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Creates a global upgradable mutex with a name. + //!If the upgradable mutex can't be created throws interprocess_exception + named_upgradable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!If the upgradable mutex is created, this call is equivalent to + //!named_upgradable_mutex(create_only_t, ...) + //!If the upgradable mutex is already created, this call is equivalent to + //!named_upgradable_mutex(open_only_t, ... ). + named_upgradable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + //!Opens a global upgradable mutex with a name if that upgradable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_upgradable_mutex(open_only_t, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_upgradable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, sharable or upgradable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, sharable or upgradable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, sharable or + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + template + bool timed_lock(const TimePoint &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + template + bool timed_lock_sharable(const TimePoint &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //Upgradable locking + + //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! without waiting. If no other thread has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire upgradable ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! waiting if necessary until no other thread has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + template + bool timed_lock_upgradable(const TimePoint &abs_time); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable(); + + //Demotions + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! upgradable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_upgradable(); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_sharable(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock_sharable(); + + //Promotions + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! exclusive ownership. This operation will block until all threads with + //! sharable ownership release it. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to + //! acquire exclusive ownership. This operation will fail if there are threads + //! with sharable ownership, but it will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to acquire + //! exclusive ownership, waiting if necessary until abs_time. This operation will + //! fail if there are threads with sharable ownership or timeout reaches, but it + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + template + bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! exclusive ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock(); + + bool try_unlock_sharable_and_lock_upgradable(); + + //!Erases a named upgradable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_upgradable_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; + open_create_impl_t m_shmem; + typedef ipcdetail::named_creation_functor construct_func_t; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_upgradable_mutex::~named_upgradable_mutex() +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only_t() + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create_t() + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_only_t, const char *name) + : m_shmem (open_only_t() + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +inline void named_upgradable_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_upgradable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_upgradable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_upgradable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +template +inline bool named_upgradable_mutex::timed_lock(const TimePoint &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_upgradable_mutex::lock_upgradable() +{ this->mutex()->lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_upgradable() +{ this->mutex()->unlock_upgradable(); } + +inline bool named_upgradable_mutex::try_lock_upgradable() +{ return this->mutex()->try_lock_upgradable(); } + +template +inline bool named_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) +{ return this->mutex()->timed_lock_upgradable(abs_time); } + +inline void named_upgradable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_upgradable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_upgradable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +template +inline bool named_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline void named_upgradable_mutex::unlock_and_lock_upgradable() +{ this->mutex()->unlock_and_lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_and_lock_sharable() +{ this->mutex()->unlock_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable() +{ this->mutex()->unlock_upgradable_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock() +{ this->mutex()->unlock_upgradable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock() +{ return this->mutex()->try_unlock_upgradable_and_lock(); } + +template +inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) +{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock() +{ return this->mutex()->try_unlock_sharable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() +{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); } + +inline bool named_upgradable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/condition.hpp b/extern/boost/boost/interprocess/sync/spin/condition.hpp new file mode 100644 index 00000000000..5eead3e8296 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/spin/condition.hpp @@ -0,0 +1,299 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SPIN_CONDITION_HPP +#define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class spin_condition +{ + spin_condition(const spin_condition &); + spin_condition &operator=(const spin_condition &); + + public: + 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() + { this->notify(NOTIFY_ONE); } + + void notify_all() + { this->notify(NOTIFY_ALL); } + + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + this->do_timed_wait_impl(ustime(0u), *lock.mutex()); + } + + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + this->do_timed_wait_impl(ustime(0u), *lock.mutex()); + } + + template + 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(is_pos_infinity(abs_time)){ + this->wait(lock); + return true; + } + return this->do_timed_wait_impl(abs_time, *lock.mutex()); + } + + template + 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(is_pos_infinity(abs_time)){ + this->wait(lock, pred); + return true; + } + while (!pred()){ + if (!this->do_timed_wait_impl(abs_time, *lock.mutex())) + return pred(); + } + return true; + } + + template + 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 + bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) + { return this->timed_wait(lock, abs_time, pred); } + + template + cv_status wait_for(L& lock, const Duration &dur) + { return this->wait_until(lock, duration_to_ustime(dur)); } + + template + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, duration_to_ustime(dur), pred); } + + private: + + template + bool do_timed_wait_impl(const TimePoint &abs_time, InterprocessMutex &mut) + { + typedef boost::interprocess::scoped_lock 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_(), 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(&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 + spin_wait swait; + while(atomic_read32(&m_command) == SLEEP){ + swait.yield(); + + //Check for timeout + if(TimeoutEnabled){ + typedef typename microsec_clock::time_point time_point; + time_point now = get_now(bool_()); + + 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(TimeoutEnabled && timed_out){ + //Decrement wait count + atomic_dec32(const_cast(&m_num_waiters)); + unlock_enter_mut = true; + break; + } + else{ + boost::uint32_t result = atomic_cas32 + (const_cast(&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(&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(&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(&m_command), SLEEP, NOTIFY_ALL); + } + break; + } + } + } + + //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; + } + + template + static typename microsec_clock::time_point get_now(bool_) + { return microsec_clock::universal_time(); } + + template + static typename microsec_clock::time_point get_now(bool_) + { return typename microsec_clock::time_point(); } + + template + static void get_lock(bool_, Mutex &m, Lock &lck, const TimePoint &abs_time) + { + Lock dummy(m, abs_time); + lck = boost::move(dummy); + } + + template + static void get_lock(bool_, Mutex &m, Lock &lck, const TimePoint &) + { + Lock dummy(m); + lck = boost::move(dummy); + } + + void 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; + } + + //Notify that all threads should execute wait logic + spin_wait swait; + while(SLEEP != atomic_cas32(const_cast(&m_command), command, SLEEP)){ + swait.yield(); + } + //The enter mutex will rest locked until the last waiting thread unlocks it + } + + 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 +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp b/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp new file mode 100644 index 00000000000..0e7216aa704 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp @@ -0,0 +1,53 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost { +namespace interprocess { + +inline barrier::barrier(unsigned int count) + : m_threshold(count), m_count(count), m_generation(0) +{ + if (count == 0) + throw std::invalid_argument("count cannot be zero."); +} + +inline barrier::~barrier(){} + +inline bool barrier::wait() +{ + scoped_lock lock(m_mutex); + unsigned int gen = m_generation; + + if (--m_count == 0){ + m_generation++; + m_count = m_threshold; + m_cond.notify_all(); + return true; + } + + while (gen == m_generation){ + m_cond.wait(lock); + } + return false; +} + +} //namespace interprocess { +} //namespace boost { diff --git a/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp new file mode 100644 index 00000000000..a2a85577957 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp @@ -0,0 +1,185 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class spin_recursive_mutex +{ + spin_recursive_mutex(const spin_recursive_mutex &); + spin_recursive_mutex &operator=(const spin_recursive_mutex &); + public: + + spin_recursive_mutex(); + ~spin_recursive_mutex(); + + void lock(); + bool try_lock(); + template + bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + void unlock(); + void take_ownership(); + private: + spin_mutex m_mutex; + unsigned int m_nLockCount; + volatile ipcdetail::OS_systemwide_thread_id_t m_nOwner; + volatile boost::uint32_t m_s; +}; + +inline spin_recursive_mutex::spin_recursive_mutex() + : m_nLockCount(0), m_nOwner(ipcdetail::get_invalid_systemwide_thread_id()){} + +inline spin_recursive_mutex::~spin_recursive_mutex(){} + +inline void spin_recursive_mutex::lock() +{ + typedef ipcdetail::OS_systemwide_thread_id_t handle_t; + const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); + handle_t old_id; + ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); + if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)){ + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); + } + ++m_nLockCount; + } + else{ + m_mutex.lock(); + ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); + m_nLockCount = 1; + } +} + +inline bool spin_recursive_mutex::try_lock() +{ + typedef ipcdetail::OS_systemwide_thread_id_t handle_t; + handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); + handle_t old_id; + ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); + if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); + } + ++m_nLockCount; + return true; + } + if(m_mutex.try_lock()){ + ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); + m_nLockCount = 1; + return true; + } + return false; +} + +template +inline bool spin_recursive_mutex::timed_lock(const TimePoint &abs_time) +{ + typedef ipcdetail::OS_systemwide_thread_id_t handle_t; + const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); + handle_t old_id; + ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); + if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); + } + ++m_nLockCount; + return true; + } + //m_mutex supports abs_time so no need to check it + if(m_mutex.timed_lock(abs_time)){ + ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); + m_nLockCount = 1; + return true; + } + return false; +} + +inline void spin_recursive_mutex::unlock() +{ + typedef ipcdetail::OS_systemwide_thread_id_t handle_t; + handle_t old_id; + ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); + const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); + (void)old_id; + (void)thr_id; + BOOST_ASSERT(ipcdetail::equal_systemwide_thread_id(thr_id, old_id)); + --m_nLockCount; + if(!m_nLockCount){ + const handle_t new_id(ipcdetail::get_invalid_systemwide_thread_id()); + ipcdetail::systemwide_thread_id_copy(new_id, m_nOwner); + m_mutex.unlock(); + } +} + +inline void spin_recursive_mutex::take_ownership() +{ + typedef ipcdetail::OS_systemwide_thread_id_t handle_t; + this->m_nLockCount = 1; + const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); + ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/semaphore.hpp b/extern/boost/boost/interprocess/sync/spin/semaphore.hpp new file mode 100644 index 00000000000..cd3c8662057 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/spin/semaphore.hpp @@ -0,0 +1,94 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_SPIN_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class spin_semaphore +{ + spin_semaphore(const spin_semaphore &); + spin_semaphore &operator=(const spin_semaphore &); + + public: + spin_semaphore(unsigned int initialCount); + ~spin_semaphore(); + + void post(); + void wait(); + bool try_wait(); + template bool timed_wait(const TimePoint &abs_time); + +// int get_count() const; + private: + volatile boost::uint32_t m_count; +}; + + +inline spin_semaphore::~spin_semaphore() +{} + +inline spin_semaphore::spin_semaphore(unsigned int initialCount) +{ ipcdetail::atomic_write32(&this->m_count, boost::uint32_t(initialCount)); } + +inline void spin_semaphore::post() +{ + ipcdetail::atomic_inc32(&m_count); +} + +inline void spin_semaphore::wait() +{ + ipcdetail::lock_to_wait lw(*this); + return ipcdetail::try_based_lock(lw); +} + +inline bool spin_semaphore::try_wait() +{ + return ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0)); +} + +template +inline bool spin_semaphore::timed_wait(const TimePoint &abs_time) +{ + ipcdetail::lock_to_wait lw(*this); + return ipcdetail::try_based_timed_lock(lw, abs_time); +} + +//inline int spin_semaphore::get_count() const +//{ + //return (int)ipcdetail::atomic_read32(&m_count); +//} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/upgradable_lock.hpp b/extern/boost/boost/interprocess/sync/upgradable_lock.hpp new file mode 100644 index 00000000000..787cf16e1ff --- /dev/null +++ b/extern/boost/boost/interprocess/sync/upgradable_lock.hpp @@ -0,0 +1,314 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +// +// This interface is inspired by Howard Hinnant's lock proposal. +// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP +#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +//!\file +//!Describes the upgradable_lock class that serves to acquire the upgradable +//!lock of a mutex. + +namespace boost { +namespace interprocess { + +//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking, +//!try-read-locking and timed-read-locking (recursive or not) for the Mutex. +//!Additionally the upgradable_lock can transfer ownership to a scoped_lock +//!using transfer_lock syntax. The Mutex need not supply all of the functionality. +//!If the client of upgradable_lock does not use functionality which the +//!Mutex does not supply, no harm is done. Mutex ownership can be shared among +//!read_locks, and a single upgradable_lock. upgradable_lock does not support +//!copy semantics. However upgradable_lock supports ownership transfer from +//!a upgradable_locks or scoped_locks via transfer_lock syntax. +template +class upgradable_lock +{ + public: + typedef UpgradableMutex mutex_type; + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + typedef upgradable_lock this_type; + explicit upgradable_lock(scoped_lock&); + typedef bool this_type::*unspecified_bool_type; + BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + + //!Effects: Default constructs a upgradable_lock. + //!Postconditions: owns() == false and mutex() == 0. + upgradable_lock() BOOST_NOEXCEPT + : mp_mutex(0), m_locked(false) + {} + + explicit upgradable_lock(mutex_type& m) + : mp_mutex(&m), m_locked(false) + { mp_mutex->lock_upgradable(); m_locked = true; } + + //!Postconditions: owns() == false, and mutex() == &m. + //!Notes: The constructor will not take ownership of the mutex. There is no effect + //! required on the referenced mutex. + upgradable_lock(mutex_type& m, defer_lock_type) + : mp_mutex(&m), m_locked(false) + {} + + //!Postconditions: owns() == true, and mutex() == &m. + //!Notes: The constructor will suppose that the mutex is already upgradable + //! locked. There is no effect required on the referenced mutex. + upgradable_lock(mutex_type& m, accept_ownership_type) + : mp_mutex(&m), m_locked(true) + {} + + //!Effects: m.try_lock_upgradable(). + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.try_lock_upgradable() executed within the constructor. + //!Notes: The constructor will take upgradable-ownership of the mutex + //! if it can do so without waiting. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support try_lock_upgradable, this constructor will fail at + //! compile time if instantiated, but otherwise have no effect. + upgradable_lock(mutex_type& m, try_to_lock_type) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->try_lock_upgradable(); } + + //!Effects: m.timed_lock_upgradable(abs_time) + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.timed_lock_upgradable() executed within the constructor. + //!Notes: The constructor will take upgradable-ownership of the mutex if it + //! can do so within the time specified. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support timed_lock_upgradable, this constructor will fail + //! at compile time if instantiated, but otherwise have no effect. + template + upgradable_lock(mutex_type& m, const TimePoint& abs_time) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->timed_lock_upgradable(abs_time); } + + //!Effects: No effects on the underlying mutex. + //!Postconditions: mutex() == the value upgr.mutex() had before the + //! construction. upgr.mutex() == 0. owns() == upgr.owns() before the + //! construction. upgr.owns() == false. + //!Notes: If upgr is locked, this constructor will lock this upgradable_lock + //! while unlocking upgr. If upgr is unlocked, then this upgradable_lock will + //! be unlocked as well. Only a moved upgradable_lock's will match this + //! signature. An non-moved upgradable_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. + upgradable_lock(BOOST_RV_REF(upgradable_lock) upgr) BOOST_NOEXCEPT + : mp_mutex(0), m_locked(upgr.owns()) + { mp_mutex = upgr.release(); } + + //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). + //!Postconditions: mutex() == the value scop.mutex() had before the construction. + //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the + //! construction, scop.owns() == false. + //!Notes: If scop is locked, this constructor will transfer the exclusive-ownership + //! to an upgradable-ownership of this upgradable_lock. + //! Only a moved sharable_lock's will match this + //! signature. An non-moved sharable_lock can be moved with the + //! expression: "boost::move(lock);". + template + upgradable_lock(BOOST_RV_REF(scoped_lock) scop + , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) + : mp_mutex(0), m_locked(false) + { + scoped_lock &u_lock = scop; + if(u_lock.owns()){ + u_lock.mutex()->unlock_and_lock_upgradable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + + //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable() + //! on the referenced mutex. + //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex() + //! obtains the value from shar.release() and owns() is set to true. + //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is + //! unaffected and this upgradable_lock construction has the same + //! effects as a default construction. + //! c)Else shar.owns() is false. mutex() obtains the value from shar.release() + //! and owns() is set to false. + //!Notes: This construction will not block. It will try to obtain mutex + //! ownership from shar immediately, while changing the lock type from a + //! "read lock" to an "upgradable lock". If the "read lock" isn't held + //! in the first place, the mutex merely changes type to an unlocked + //! "upgradable lock". If the "read lock" is held, then mutex transfer + //! occurs only if it can do so in a non-blocking manner. + template + upgradable_lock( BOOST_RV_REF(sharable_lock) shar, try_to_lock_type + , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) + : mp_mutex(0), m_locked(false) + { + sharable_lock &s_lock = shar; + if(s_lock.owns()){ + if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){ + mp_mutex = s_lock.release(); + } + } + else{ + s_lock.release(); + } + } + + //!Effects: if (owns()) m_->unlock_upgradable(). + //!Notes: The destructor behavior ensures that the mutex lock is not leaked. + ~upgradable_lock() + { + BOOST_TRY{ + if(m_locked && mp_mutex) mp_mutex->unlock_upgradable(); + } + BOOST_CATCH(...){} BOOST_CATCH_END + } + + //!Effects: If owns(), then unlock_upgradable() is called on mutex(). + //! *this gets the state of upgr and upgr gets set to a default constructed state. + //!Notes: With a recursive mutex it is possible that both this and upgr own the + //! mutex before the assignment. In this case, this will own the mutex + //! after the assignment (and upgr will not), but the mutex's upgradable lock + //! count will be decremented by one. + upgradable_lock &operator=(BOOST_RV_REF(upgradable_lock) upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.owns(); + mp_mutex = upgr.release(); + return *this; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls lock_upgradable() on the referenced mutex. + //!Postconditions: owns() == true. + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, blocking if necessary. + void lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + mp_mutex->lock_upgradable(); + m_locked = true; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls try_lock_upgradable() on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->try_lock_upgradable(). + //!Notes: The upgradable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if blocking was not required. If the + //! mutex_type does not support try_lock_upgradable(), this function will + //! fail at compile time if instantiated, but otherwise have no effect. + bool try_lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_upgradable(); + return m_locked; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_upgradable(abs_time). + //!Notes: The upgradable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time. If the mutex_type does not support + //! timed_lock_upgradable(abs_time), this function will fail at compile + //! time if instantiated, but otherwise have no effect. + template + bool timed_lock(const TimePoint& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->timed_lock_upgradable(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or if not locked, throws a lock_exception() + //! exception. Calls unlock_upgradable() on the referenced mutex. + //!Postconditions: owns() == false. + //!Notes: The upgradable_lock changes from a state of owning the mutex, + //! to not owning the mutex. + void unlock() + { + if(!mp_mutex || !m_locked) + throw lock_exception(); + mp_mutex->unlock_upgradable(); + m_locked = false; + } + + //!Effects: Returns true if this scoped_lock has acquired the + //!referenced mutex. + bool owns() const BOOST_NOEXCEPT + { return m_locked && mp_mutex; } + + //!Conversion to bool. + //!Returns owns(). + 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 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() BOOST_NOEXCEPT + { + mutex_type *mut = mp_mutex; + mp_mutex = 0; + m_locked = false; + return mut; + } + + //!Effects: Swaps state with moved lock. + //!Throws: Nothing. + void swap(upgradable_lock &other) BOOST_NOEXCEPT + { + (simple_swap)(mp_mutex, other.mp_mutex); + (simple_swap)(m_locked, other.m_locked); + } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + mutex_type *mp_mutex; + bool m_locked; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/condition.hpp b/extern/boost/boost/interprocess/sync/windows/condition.hpp new file mode 100644 index 00000000000..fca3f1f8dc8 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/condition.hpp @@ -0,0 +1,147 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_WINDOWS_CONDITION_HPP +#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_condition +{ + winapi_condition(const winapi_condition &); + winapi_condition &operator=(const winapi_condition &); + + public: + winapi_condition() + : m_condition_data() + {} + + ~winapi_condition() + { + //Notify all waiting threads + //to allow POSIX semantics on condition destruction + this->notify_all(); + } + + void notify_one() + { m_condition_data.notify_one(); } + + void notify_all() + { m_condition_data.notify_all(); } + + template + void wait(L& lock) + { m_condition_data.wait(lock); } + + template + void wait(L& lock, Pr pred) + { m_condition_data.wait(lock, pred); } + + + template + bool timed_wait(L& lock, const TimePoint &abs_time) + { return m_condition_data.timed_wait(lock, abs_time); } + + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { return m_condition_data.timed_wait(lock, abs_time, pred); } + + template + 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 + bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) + { return this->timed_wait(lock, abs_time, pred); } + + template + cv_status wait_for(L& lock, const Duration &dur) + { return this->wait_until(lock, duration_to_ustime(dur)); } + + template + 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 unsigned int integer_type; + typedef winapi_semaphore semaphore_type; + typedef winapi_mutex mutex_type; + + condition_data() + : m_nwaiters_blocked(0) + , m_nwaiters_gone(0) + , m_nwaiters_to_unblock(0) + , m_sem_block_queue(0) + , m_sem_block_lock(1) + , m_mtx_unblock_lock() + {} + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return 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 m_condition_data; +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/mutex.hpp b/extern/boost/boost/interprocess/sync/windows/mutex.hpp new file mode 100644 index 00000000000..ce168f89b60 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/mutex.hpp @@ -0,0 +1,126 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_WINDOWS_MUTEX_HPP +#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_mutex +{ + winapi_mutex(const winapi_mutex &); + winapi_mutex &operator=(const winapi_mutex &); + public: + + winapi_mutex(); + ~winapi_mutex(); + + void lock(); + bool try_lock(); + template bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + void unlock(); + void take_ownership(){}; + + private: + const sync_id id_; +}; + +inline winapi_mutex::winapi_mutex() + : id_() +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //Create mutex with the initial count + bool 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 winapi_mutex::~winapi_mutex() +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + handles.destroy_handle(this->id_, this); +} + +inline void winapi_mutex::lock(void) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); + mut.lock(); +} + +inline bool winapi_mutex::try_lock(void) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); + return mut.try_lock(); +} + +template +inline bool winapi_mutex::timed_lock(const TimePoint &abs_time) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); + return mut.timed_lock(abs_time); +} + +inline void winapi_mutex::unlock(void) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); + return mut.unlock(); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_condition.hpp b/extern/boost/boost/interprocess/sync/windows/named_condition.hpp new file mode 100644 index 00000000000..2f9354c44e1 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_condition.hpp @@ -0,0 +1,40 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +typedef winapi_named_condition_any winapi_named_condition; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp new file mode 100644 index 00000000000..f13a5f944f4 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp @@ -0,0 +1,337 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +struct named_cond_callbacks_str; + +template<> +struct named_cond_callbacks_str +{ + static const char* ipc_cond() + { return "Global\\bipc.cond."; } + + static const char* bq() + { return "_bq"; } + + static const char* bl() + { return "_bl"; } + + static const char* ul() + { return "_ul"; } +}; + +template<> +struct named_cond_callbacks_str +{ + static const wchar_t* ipc_cond() + { return L"Global\\bipc.cond."; } + + static const wchar_t* bq() + { return L"_bq"; } + + static const wchar_t* bl() + { return L"_bl"; } + + static const wchar_t* ul() + { return L"_ul"; } +}; + +class winapi_named_condition_any +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + winapi_named_condition_any(); + winapi_named_condition_any(const winapi_named_condition_any &); + winapi_named_condition_any &operator=(const winapi_named_condition_any &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + winapi_named_condition_any + (create_only_t, const char *name, const permissions &perm = permissions()) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); + } + + winapi_named_condition_any + (open_or_create_t, const char *name, const permissions &perm = permissions()) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); + } + + winapi_named_condition_any(open_only_t, const char *name) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); + } + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + winapi_named_condition_any + (create_only_t, const wchar_t *name, const permissions &perm = permissions()) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); + } + + winapi_named_condition_any + (open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); + } + + winapi_named_condition_any(open_only_t, const wchar_t *name) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); + } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + ~winapi_named_condition_any() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.close(callbacks); + } + + void notify_one() + { m_condition_data.notify_one(); } + + void notify_all() + { m_condition_data.notify_all(); } + + template + bool timed_wait(L& lock, const TimePoint &abs_time) + { return m_condition_data.timed_wait(lock, abs_time); } + + template + bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) + { return m_condition_data.timed_wait(lock, abs_time, pred); } + + template + void wait(L& lock) + { m_condition_data.wait(lock); } + + template + void wait(L& lock, Pr pred) + { m_condition_data.wait(lock, pred); } + + template + 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 + bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) + { return this->timed_wait(lock, abs_time, pred); } + + template + cv_status wait_for(L& lock, const Duration &dur) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); } + + template + bool wait_for(L& lock, const Duration &dur, Pr pred) + { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } + + static bool remove(const char *name) + { return windows_named_sync::remove(name); } + + static bool remove(const wchar_t *name) + { return windows_named_sync::remove(name); } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + void dont_close_on_destruction() + {} + + friend class interprocess_tester; + + struct condition_data + { + typedef boost::int32_t integer_type; + typedef winapi_semaphore_wrapper semaphore_type; + typedef winapi_mutex_wrapper mutex_type; + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + integer_type m_nwaiters_blocked; + integer_type m_nwaiters_gone; + integer_type m_nwaiters_to_unblock; + winapi_semaphore_wrapper m_sem_block_queue; + winapi_semaphore_wrapper m_sem_block_lock; + winapi_mutex_wrapper m_mtx_unblock_lock; + }; + + + class named_cond_callbacks : public windows_named_sync_interface + { + typedef __int64 sem_count_t; + mutable sem_count_t sem_counts [2]; + + public: + named_cond_callbacks(condition_data &cond_data) + : m_condition_data(cond_data) + {} + + virtual std::size_t get_data_size() const BOOST_OVERRIDE + { return sizeof(sem_counts); } + + virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE + { + sem_counts[0] = m_condition_data.m_sem_block_queue.value(); + sem_counts[1] = m_condition_data.m_sem_block_lock.value(); + return &sem_counts; + } + + virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE + { + sem_counts[0] = 0; + sem_counts[1] = 1; + return &sem_counts; + } + + virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE + { return &sem_counts; } + + virtual bool open(create_enum_t op, const char *id_name) BOOST_OVERRIDE + { return this->open_impl(op, id_name); } + + virtual bool open(create_enum_t op, const wchar_t *id_name) BOOST_OVERRIDE + { return this->open_impl(op, id_name); } + + virtual void close() BOOST_OVERRIDE + { + m_condition_data.m_sem_block_queue.close(); + m_condition_data.m_sem_block_lock.close(); + m_condition_data.m_mtx_unblock_lock.close(); + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + } + + virtual ~named_cond_callbacks() BOOST_OVERRIDE + {} + + private: + + template + bool open_impl(create_enum_t, const CharT *id_name) + { + typedef named_cond_callbacks_str str_t; + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + + //Now open semaphores and mutex. + //Use local variables + swap to guarantee consistent + //initialization and cleanup in case any opening fails + permissions perm; + perm.set_unrestricted(); + std::basic_string aux_str = str_t::ipc_cond(); + aux_str += id_name; + std::size_t pos = aux_str.size(); + + //sem_block_queue + aux_str += str_t::bq(); + winapi_semaphore_wrapper sem_block_queue; + bool created; + if(!sem_block_queue.open_or_create + (aux_str.c_str(), static_cast(sem_counts[0]), winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //sem_block_lock + aux_str += str_t::bl(); + winapi_semaphore_wrapper sem_block_lock; + if(!sem_block_lock.open_or_create + (aux_str.c_str(), static_cast(sem_counts[1]), winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //mtx_unblock_lock + aux_str += str_t::ul(); + winapi_mutex_wrapper mtx_unblock_lock; + if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) + return false; + + //All ok, commit data + m_condition_data.m_sem_block_queue.swap(sem_block_queue); + m_condition_data.m_sem_block_lock.swap(sem_block_lock); + m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); + return true; + } + + condition_data &m_condition_data; + }; + + windows_named_sync m_named_sync; + ipcdetail::condition_8a_wrapper m_condition_data; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp new file mode 100644 index 00000000000..029eb61d5f3 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp @@ -0,0 +1,232 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class winapi_named_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + winapi_named_mutex(); + winapi_named_mutex(const winapi_named_mutex &); + winapi_named_mutex &operator=(const winapi_named_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + winapi_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); + + winapi_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); + + winapi_named_mutex(open_only_t, const char *name); + + winapi_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + winapi_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + winapi_named_mutex(open_only_t, const wchar_t *name); + + ~winapi_named_mutex(); + + void unlock(); + void lock(); + bool try_lock(); + template bool timed_lock(const TimePoint &abs_time); + + template bool try_lock_until(const TimePoint &abs_time) + { return this->timed_lock(abs_time); } + + template bool try_lock_for(const Duration &dur) + { return this->timed_lock(duration_to_ustime(dur)); } + + static bool remove(const char *name); + + static bool remove(const wchar_t *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_mutex_wrapper m_mtx_wrapper; + windows_named_sync m_named_sync; + + class named_mut_callbacks : public windows_named_sync_interface + { + public: + named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper) + : m_mtx_wrapper(mtx_wrapper) + {} + + virtual std::size_t get_data_size() const BOOST_OVERRIDE + { return 0u; } + + virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE + { return 0; } + + virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE + { return 0; } + + virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE + { return 0; } + + virtual bool open(create_enum_t, const char *id_name) BOOST_OVERRIDE + { + std::string aux_str = "Global\\bipc.mut."; + aux_str += id_name; + // + permissions mut_perm; + mut_perm.set_unrestricted(); + return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); + } + + virtual bool open(create_enum_t, const wchar_t *id_name) BOOST_OVERRIDE + { + std::wstring aux_str = L"Global\\bipc.mut."; + aux_str += id_name; + // + permissions mut_perm; + mut_perm.set_unrestricted(); + return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); + } + + virtual void close() BOOST_OVERRIDE + { + m_mtx_wrapper.close(); + } + + virtual ~named_mut_callbacks() BOOST_OVERRIDE + {} + + private: + winapi_mutex_wrapper& m_mtx_wrapper; + }; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline winapi_named_mutex::~winapi_named_mutex() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.close(callbacks); +} + +inline void winapi_named_mutex::dont_close_on_destruction() +{} + +inline winapi_named_mutex::winapi_named_mutex + (create_only_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline winapi_named_mutex::winapi_named_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline winapi_named_mutex::winapi_named_mutex(open_only_t, const char *name) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline winapi_named_mutex::winapi_named_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline winapi_named_mutex::winapi_named_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline winapi_named_mutex::winapi_named_mutex(open_only_t, const wchar_t *name) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void winapi_named_mutex::unlock() +{ + m_mtx_wrapper.unlock(); +} + +inline void winapi_named_mutex::lock() +{ + m_mtx_wrapper.lock(); +} + +inline bool winapi_named_mutex::try_lock() +{ + return m_mtx_wrapper.try_lock(); +} + +template +inline bool winapi_named_mutex::timed_lock(const TimePoint &abs_time) +{ + return m_mtx_wrapper.timed_lock(abs_time); +} + +inline bool winapi_named_mutex::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +inline bool winapi_named_mutex::remove(const wchar_t *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP \ No newline at end of file diff --git a/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp new file mode 100644 index 00000000000..3d564b5341f --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp @@ -0,0 +1,74 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + +class winapi_named_recursive_mutex + //Windows mutexes based on CreateMutex are already recursive... + : public winapi_named_mutex +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + winapi_named_recursive_mutex(); + winapi_named_recursive_mutex(const winapi_named_mutex &); + winapi_named_recursive_mutex &operator=(const winapi_named_mutex &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + winapi_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()) + : winapi_named_mutex(create_only_t(), name, perm) + {} + + winapi_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()) + : winapi_named_mutex(open_or_create_t(), name, perm) + {} + + winapi_named_recursive_mutex(open_only_t, const char *name) + : winapi_named_mutex(open_only_t(), name) + {} + + winapi_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()) + : winapi_named_mutex(create_only_t(), name, perm) + {} + + winapi_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) + : winapi_named_mutex(open_or_create_t(), name, perm) + {} + + winapi_named_recursive_mutex(open_only_t, const wchar_t *name) + : winapi_named_mutex(open_only_t(), name) + {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp new file mode 100644 index 00000000000..bd3cff37a6e --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp @@ -0,0 +1,230 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + + + +class winapi_named_semaphore +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + winapi_named_semaphore(); + winapi_named_semaphore(const winapi_named_semaphore &); + winapi_named_semaphore &operator=(const winapi_named_semaphore &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + winapi_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + winapi_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); + + winapi_named_semaphore(open_only_t, const char *name); + + winapi_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + winapi_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + winapi_named_semaphore(open_only_t, const wchar_t *name); + + ~winapi_named_semaphore(); + + void post(); + void wait(); + bool try_wait(); + template bool timed_wait(const TimePoint &abs_time); + + static bool remove(const char *name); + static bool remove(const wchar_t *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + friend class interprocess_tester; + void dont_close_on_destruction(); + winapi_semaphore_wrapper m_sem_wrapper; + windows_named_sync m_named_sync; + + class named_sem_callbacks : public windows_named_sync_interface + { + public: + typedef __int64 sem_count_t; + named_sem_callbacks(winapi_semaphore_wrapper &sem_wrapper, sem_count_t sem_cnt) + : m_sem_wrapper(sem_wrapper), m_sem_count(sem_cnt) + {} + + virtual std::size_t get_data_size() const BOOST_OVERRIDE + { return sizeof(sem_count_t); } + + virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE + { return &m_sem_count; } + + virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE + { return &m_sem_count; } + + virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE + { return &m_sem_count; } + + virtual bool open(create_enum_t, const char *id_name) BOOST_OVERRIDE + { + std::string aux_str = "Global\\bipc.sem."; + aux_str += id_name; + // + permissions sem_perm; + sem_perm.set_unrestricted(); + bool created; + return m_sem_wrapper.open_or_create + ( aux_str.c_str(), static_cast(m_sem_count) + , winapi_semaphore_wrapper::MaxCount, sem_perm, created); + } + + virtual bool open(create_enum_t, const wchar_t *id_name) BOOST_OVERRIDE + { + std::wstring aux_str = L"Global\\bipc.sem."; + aux_str += id_name; + // + permissions sem_perm; + sem_perm.set_unrestricted(); + bool created; + return m_sem_wrapper.open_or_create + ( aux_str.c_str(), static_cast(m_sem_count) + , winapi_semaphore_wrapper::MaxCount, sem_perm, created); + } + + virtual void close() BOOST_OVERRIDE + { + m_sem_wrapper.close(); + } + + virtual ~named_sem_callbacks() BOOST_OVERRIDE + {} + + private: + winapi_semaphore_wrapper& m_sem_wrapper; + sem_count_t m_sem_count; + }; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline winapi_named_semaphore::~winapi_named_semaphore() +{ + named_sem_callbacks callbacks(m_sem_wrapper, m_sem_wrapper.value()); + m_named_sync.close(callbacks); +} + +inline void winapi_named_semaphore::dont_close_on_destruction() +{} + +inline winapi_named_semaphore::winapi_named_semaphore + (create_only_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline winapi_named_semaphore::winapi_named_semaphore + (open_or_create_t, const char *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline winapi_named_semaphore::winapi_named_semaphore(open_only_t, const char *name) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, 0); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline winapi_named_semaphore::winapi_named_semaphore + (create_only_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline winapi_named_semaphore::winapi_named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline winapi_named_semaphore::winapi_named_semaphore(open_only_t, const wchar_t *name) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, 0); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + +inline void winapi_named_semaphore::post() +{ + m_sem_wrapper.post(); +} + +inline void winapi_named_semaphore::wait() +{ + m_sem_wrapper.wait(); +} + +inline bool winapi_named_semaphore::try_wait() +{ + return m_sem_wrapper.try_wait(); +} + +template +inline bool winapi_named_semaphore::timed_wait(const TimePoint &abs_time) +{ + return m_sem_wrapper.timed_wait(abs_time); +} + +inline bool winapi_named_semaphore::remove(const char *name) +{ + return windows_named_sync::remove(name); +} + +inline bool winapi_named_semaphore::remove(const wchar_t *name) +{ + return windows_named_sync::remove(name); +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_sync.hpp b/extern/boost/boost/interprocess/sync/windows/named_sync.hpp new file mode 100644 index 00000000000..28f498c6f73 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/named_sync.hpp @@ -0,0 +1,237 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_SYNC_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_sync_interface +{ + public: + virtual std::size_t get_data_size() const = 0; + virtual const void *buffer_with_final_data_to_file() = 0; + virtual const void *buffer_with_init_data_to_file() = 0; + virtual void *buffer_to_store_init_data_from_file() = 0; + virtual bool open(create_enum_t creation_type, const char *id_name) = 0; + virtual bool open(create_enum_t creation_type, const wchar_t *id_name) = 0; + virtual void close() = 0; + virtual ~windows_named_sync_interface() = 0; +}; + +inline windows_named_sync_interface::~windows_named_sync_interface() +{} + +class windows_named_sync +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //Non-copyable + windows_named_sync(const windows_named_sync &); + windows_named_sync &operator=(const windows_named_sync &); + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + windows_named_sync(); + template + void open_or_create(create_enum_t creation_type, const CharT *name, const permissions &perm, windows_named_sync_interface &sync_interface); + void close(windows_named_sync_interface &sync_interface); + + static bool remove(const char *name); + static bool remove(const wchar_t *name); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + void *m_file_hnd; + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +inline windows_named_sync::windows_named_sync() + : m_file_hnd(winapi::invalid_handle_value) +{} + +inline void windows_named_sync::close(windows_named_sync_interface &sync_interface) +{ + const std::size_t buflen = sync_interface.get_data_size(); + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){ + if(winapi::set_file_pointer(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ + const void *buf = sync_interface.buffer_with_final_data_to_file(); + + unsigned long written_or_read = 0; + if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){ + //... + } + } + } + sync_interface.close(); + //close_handle unlocks the lock + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } +} + +template +inline void windows_named_sync::open_or_create + ( create_enum_t creation_type + , const CharT *name + , const permissions &perm + , windows_named_sync_interface &sync_interface) +{ + std::basic_string aux_str(name); + m_file_hnd = winapi::invalid_handle_value; + //Use a file to emulate POSIX lifetime semantics. After this logic + //we'll obtain the ID of the native handle to open in aux_str + { + create_shared_dir_cleaning_old_and_get_filepath(name, aux_str); + //Create a file with required permissions. + m_file_hnd = winapi::create_file + ( aux_str.c_str() + , winapi::generic_read | winapi::generic_write + , creation_type == DoOpen ? winapi::open_existing : + (creation_type == DoCreate ? winapi::create_new : winapi::open_always) + , 0 + , (winapi::interprocess_security_attributes*)perm.get_permissions()); + + //Obtain OS error in case something has failed + error_info err; + bool success = false; + if(m_file_hnd != winapi::invalid_handle_value){ + //Now lock the file + const std::size_t buflen = sync_interface.get_data_size(); + typedef __int64 unique_id_type; + const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen; + winapi::interprocess_overlapped overlapped; + if(winapi::lock_file_ex + (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){ + __int64 filesize = 0; + //Obtain the unique id to open the native semaphore. + //If file size was created + if(winapi::get_file_size(m_file_hnd, filesize)){ + unsigned long written_or_read = 0; + unique_id_type unique_id_val; + if(static_cast(filesize) != sizeof_file_info){ + winapi::set_end_of_file(m_file_hnd); + winapi::query_performance_counter(&unique_id_val); + const void *buf = sync_interface.buffer_with_init_data_to_file(); + //Write unique ID in file. This ID will be used to calculate the semaphore name + if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + winapi::get_file_size(m_file_hnd, filesize); + BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info); + } + else{ + void *buf = sync_interface.buffer_to_store_init_data_from_file(); + if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && + written_or_read == sizeof(unique_id_val) && + winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) && + written_or_read == buflen ){ + success = true; + } + } + if(success){ + //Now create a global semaphore name based on the unique id + CharT unique_id_name[sizeof(unique_id_val)*2+1]; + std::size_t name_suffix_length = sizeof(unique_id_name); + bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length); + success = sync_interface.open(creation_type, unique_id_name); + } + } + + //Obtain OS error in case something has failed + if(!success) + err = system_error_code(); + + //If this fails we have no possible rollback so don't check the return + if(!winapi::unlock_file_ex(m_file_hnd, 0, 1, 0, &overlapped)){ + err = system_error_code(); + } + } + else{ + //Obtain OS error in case something has failed + err = system_error_code(); + } + } + else{ + err = system_error_code(); + } + + if(!success){ + if(m_file_hnd != winapi::invalid_handle_value){ + winapi::close_handle(m_file_hnd); + m_file_hnd = winapi::invalid_handle_value; + } + //Throw as something went wrong + throw interprocess_exception(err); + } + } +} + +inline bool windows_named_sync::remove(const char *name) +{ + BOOST_TRY{ + //Make sure a temporary path is created for shared memory + std::string semfile; + ipcdetail::shared_filepath(name, semfile); + return winapi::unlink_file(semfile.c_str()); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END +} + +inline bool windows_named_sync::remove(const wchar_t *name) +{ + BOOST_TRY{ + //Make sure a temporary path is created for shared memory + std::wstring semfile; + ipcdetail::shared_filepath(name, semfile); + return winapi::unlink_file(semfile.c_str()); + } + BOOST_CATCH(...){ + return false; + } BOOST_CATCH_END +} + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp new file mode 100644 index 00000000000..900904d809f --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_WINDOWS_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//Windows mutex is already recursive +class winapi_recursive_mutex + : public winapi_mutex +{ + winapi_recursive_mutex(const winapi_recursive_mutex &); + winapi_recursive_mutex &operator=(const winapi_recursive_mutex &); + public: + winapi_recursive_mutex() : winapi_mutex() {} +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/semaphore.hpp b/extern/boost/boost/interprocess/sync/windows/semaphore.hpp new file mode 100644 index 00000000000..888ab71a0c2 --- /dev/null +++ b/extern/boost/boost/interprocess/sync/windows/semaphore.hpp @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_WINDOWS_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class winapi_semaphore +{ + winapi_semaphore(const winapi_semaphore &); + winapi_semaphore &operator=(const winapi_semaphore &); + public: + + winapi_semaphore(unsigned int initialCount); + ~winapi_semaphore(); + + void post(unsigned int release_count = 1); + void wait(); + bool try_wait(); + template bool timed_wait(const TimePoint &abs_time); + + private: + const sync_id id_; + const unsigned initial_count_; +}; + +inline winapi_semaphore::winapi_semaphore(unsigned int initialCount) + : id_(), initial_count_(initialCount) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //Force smeaphore creation with the initial count + bool 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 winapi_semaphore::~winapi_semaphore() +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + handles.destroy_handle(this->id_, this); +} + +inline void winapi_semaphore::wait() +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); + sem.wait(); +} + +inline bool winapi_semaphore::try_wait() +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); + return sem.try_wait(); +} + +template +inline bool winapi_semaphore::timed_wait(const TimePoint &abs_time) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + //This can throw + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); + return sem.timed_wait(abs_time); +} + +inline void winapi_semaphore::post(unsigned release_count) +{ + sync_handles &handles = + windows_intermodule_singleton::get(); + winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); + sem.post(static_cast(release_count)); +} + + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/windows_shared_memory.hpp b/extern/boost/boost/interprocess/windows_shared_memory.hpp new file mode 100644 index 00000000000..eb4bdf926cf --- /dev/null +++ b/extern/boost/boost/interprocess/windows_shared_memory.hpp @@ -0,0 +1,277 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_WINDOWS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_WINDOWS) +#error "This header can only be used in Windows operating systems" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//!\file +//!Describes a class representing a native windows shared memory. + +namespace boost { +namespace interprocess { + +//!A class that wraps the native Windows shared memory +//!that is implemented as a file mapping of the paging file. +//!Unlike shared_memory_object, windows_shared_memory has +//!no kernel persistence and the shared memory is destroyed +//!when all processes destroy all their windows_shared_memory +//!objects and mapped regions for the same shared memory +//!or the processes end/crash. +//! +//!Warning: Windows native shared memory and interprocess portable +//!shared memory (boost::interprocess::shared_memory_object) +//!can't communicate between them. +class windows_shared_memory +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable and non-assignable + BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Default constructor. + //!Represents an empty windows_shared_memory. + windows_shared_memory() BOOST_NOEXCEPT; + + //!Creates a new native shared memory with name "name" and at least size "size", + //!with the access mode "mode". + //!If the file previously exists, throws an error. + windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } + + //!Tries to create a shared memory object with name "name" and at least size "size", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, 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. + windows_shared_memory(open_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } + + //!Creates a new native shared memory with name "name" and at least size "size", + //!with the access mode "mode". + //!If the file previously exists, throws an error. + windows_shared_memory(create_only_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } + + //!Tries to create a shared memory object with name "name" and at least size "size", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + windows_shared_memory(open_or_create_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, 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. + windows_shared_memory(open_only_t, const wchar_t *name, mode_t mode) + { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } + + //!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 + windows_shared_memory(BOOST_RV_REF(windows_shared_memory) moved) BOOST_NOEXCEPT + : m_handle(0) + { this->swap(moved); } + + //!Moves the ownership of "moved"'s shared memory to *this. + //!After the call, "moved" does not represent any shared memory. + //!Does not throw + windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved) BOOST_NOEXCEPT + { + windows_shared_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps to shared_memory_objects. Does not throw + void swap(windows_shared_memory &other) BOOST_NOEXCEPT; + + //!Destroys *this. All mapped regions are still valid after + //!destruction. When all mapped regions and windows_shared_memory + //!objects referring the shared memory are destroyed, the + //!operating system will destroy the shared memory. + ~windows_shared_memory(); + + //!Returns the name of the shared memory. + const char *get_name() const BOOST_NOEXCEPT; + + //!Returns access mode + mode_t get_mode() const BOOST_NOEXCEPT; + + //!Returns the mapping handle. Never throws + mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; + + //!Returns the size of the windows shared memory. It will be a 4K rounded + //!size of the "size" passed in the constructor. + offset_t get_size() const BOOST_NOEXCEPT; + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + + //!Closes a previously opened file mapping. Never throws. + template + bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm = permissions()); + + void * m_handle; + mode_t m_mode; + char_wchar_holder m_name; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline windows_shared_memory::windows_shared_memory() BOOST_NOEXCEPT + : m_handle(0) +{} + +inline windows_shared_memory::~windows_shared_memory() +{ this->priv_close(); } + +inline const char *windows_shared_memory::get_name() const BOOST_NOEXCEPT +{ return m_name.getn(); } + +inline void windows_shared_memory::swap(windows_shared_memory &other) BOOST_NOEXCEPT +{ + (simple_swap)(m_handle, other.m_handle); + (simple_swap)(m_mode, other.m_mode); + m_name.swap(other.m_name); +} + +inline mapping_handle_t windows_shared_memory::get_mapping_handle() const BOOST_NOEXCEPT +{ mapping_handle_t mhnd = { m_handle, true}; return mhnd; } + +inline mode_t windows_shared_memory::get_mode() const BOOST_NOEXCEPT +{ return m_mode; } + +inline offset_t windows_shared_memory::get_size() const BOOST_NOEXCEPT +{ + offset_t size; //This shall never fail + return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0; +} + +template +inline bool windows_shared_memory::priv_open_or_create + (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm) +{ + if (filename){ + m_name = filename; + } + else{ + m_name = ""; + } + + unsigned long protection = 0; + unsigned long map_access = 0; + + switch(mode) + { + //"protection" is for "create_file_mapping" + //"map_access" is for "open_file_mapping" + //Add section query (strange that read or access does not grant it...) + //to obtain the size of the mapping. copy_on_write is equal to section_query. + case read_only: + protection |= winapi::page_readonly; + map_access |= winapi::file_map_read | winapi::section_query; + break; + case read_write: + protection |= winapi::page_readwrite; + map_access |= winapi::file_map_write | winapi::section_query; + break; + case copy_on_write: + protection |= winapi::page_writecopy; + map_access |= winapi::file_map_copy; + break; + default: + { + error_info err(mode_error); + throw interprocess_exception(err); + } + break; + } + + switch(type){ + case ipcdetail::DoOpen: + m_handle = winapi::open_file_mapping(map_access, filename); + break; + case ipcdetail::DoCreate: + case ipcdetail::DoOpenOrCreate: + { + m_handle = winapi::create_file_mapping + ( winapi::invalid_handle_value, protection, size, filename + , (winapi::interprocess_security_attributes*)perm.get_permissions()); + } + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + if(!m_handle || (type == ipcdetail::DoCreate && winapi::get_last_error() == winapi::error_already_exists)){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + + m_mode = mode; + return true; +} + +inline void windows_shared_memory::priv_close() +{ + if(m_handle){ + winapi::close_handle(m_handle); + m_handle = 0; + } +} + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/xsi_key.hpp b/extern/boost/boost/interprocess/xsi_key.hpp new file mode 100644 index 00000000000..2dbfa66fc5a --- /dev/null +++ b/extern/boost/boost/interprocess/xsi_key.hpp @@ -0,0 +1,101 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. 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_XSI_KEY_HPP +#define BOOST_INTERPROCESS_XSI_KEY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a class representing a xsi key type. + +namespace boost { +namespace interprocess { + +//!A class that wraps XSI (System V) key_t type. +//!This type calculates key_t from path and id using ftok, +//!sets key to a specified value, +//!or sets key to IPC_PRIVATE using the default constructor. +class xsi_key +{ + public: + + //!Default constructor. + //!Represents a private xsi_key. + xsi_key() + : m_key(IPC_PRIVATE) + {} + + //!Creates a new XSI key using a specified value. Constructor is explicit to avoid ambiguity with shmid. + explicit xsi_key(key_t key) + : m_key(key) + {} + + //!Creates a new XSI shared memory with a key obtained from a call to ftok (with path + //!"path" and id "id"), of size "size" and permissions "perm". + //!If the shared memory previously exists, throws an error. + xsi_key(const char *path, boost::uint8_t id) + { + key_t key; + if(path){ + key = ::ftok(path, id); + if(((key_t)-1) == key){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + else{ + key = IPC_PRIVATE; + } + m_key = key; + } + + //!Returns the internal key_t value + key_t get_key() const + { return m_key; } + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + key_t m_key; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_XSI_KEY_HPP diff --git a/extern/boost/boost/interprocess/xsi_shared_memory.hpp b/extern/boost/boost/interprocess/xsi_shared_memory.hpp new file mode 100644 index 00000000000..9479f0d0acc --- /dev/null +++ b/extern/boost/boost/interprocess/xsi_shared_memory.hpp @@ -0,0 +1,215 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-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_XSI_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +// move +#include +// other boost +#include +// std +#include +// OS +#include + + +//!\file +//!Describes a class representing a native xsi shared memory. + +namespace boost { +namespace interprocess { + +//!A class that wraps XSI (System V) shared memory. +//!Unlike shared_memory_object, xsi_shared_memory needs a valid +//!xsi_key to identify a shared memory object. +//! +//!Warning: XSI shared memory and interprocess portable +//!shared memory (boost::interprocess::shared_memory_object) +//!can't communicate between them. +class xsi_shared_memory +{ + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //Non-copyable and non-assignable + BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + public: + //!Default constructor. + //!Represents an empty xsi_shared_memory. + xsi_shared_memory() BOOST_NOEXCEPT; + + //!Initializes *this with a shmid previously obtained (possibly from another process) + //!This lower-level initializer allows shared memory mapping without having a key. + xsi_shared_memory(open_only_t, int shmid) + : m_shmid (shmid) + {} + + //!Creates a new XSI shared memory from 'key', with size "size" and permissions "perm". + //!If the shared memory previously exists, throws an error. + xsi_shared_memory(create_only_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, key, perm, size); } + + //!Opens an existing shared memory with identifier 'key' or creates a new XSI shared memory from + //!identifier 'key', with size "size" and permissions "perm". + xsi_shared_memory(open_or_create_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, key, perm, size); } + + //!Tries to open a XSI shared memory with identifier 'key' + //!If the shared memory does not previously exist, it throws an error. + xsi_shared_memory(open_only_t, const xsi_key &key) + { this->priv_open_or_create(ipcdetail::DoOpen, key, permissions(), 0); } + + //!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 + xsi_shared_memory(BOOST_RV_REF(xsi_shared_memory) moved) BOOST_NOEXCEPT + : m_shmid(-1) + { this->swap(moved); } + + //!Moves the ownership of "moved"'s shared memory to *this. + //!After the call, "moved" does not represent any shared memory. + //!Does not throw + xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved) BOOST_NOEXCEPT + { + xsi_shared_memory tmp(boost::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps two xsi_shared_memorys. Does not throw + void swap(xsi_shared_memory &other) BOOST_NOEXCEPT; + + //!Destroys *this. The shared memory won't be destroyed, just + //!this connection to it. Use remove() to destroy the shared memory. + ~xsi_shared_memory(); + + //!Returns the shared memory ID that + //!identifies the shared memory + int get_shmid() const BOOST_NOEXCEPT; + + //!Returns the mapping handle. + //!Never throws + mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; + + //!Erases the XSI shared memory object identified by shmid + //!from the system. + //!Returns false on error. Never throws + static bool remove(int shmid); + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + private: + + //!Closes a previously opened file mapping. Never throws. + bool priv_open_or_create( ipcdetail::create_enum_t type + , const xsi_key &key + , const permissions& perm + , std::size_t size); + int m_shmid; + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED +}; + +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline xsi_shared_memory::xsi_shared_memory() BOOST_NOEXCEPT + : m_shmid(-1) +{} + +inline xsi_shared_memory::~xsi_shared_memory() +{} + +inline int xsi_shared_memory::get_shmid() const BOOST_NOEXCEPT +{ return m_shmid; } + +inline void xsi_shared_memory::swap(xsi_shared_memory &other) BOOST_NOEXCEPT +{ + (simple_swap)(m_shmid, other.m_shmid); +} + +inline mapping_handle_t xsi_shared_memory::get_mapping_handle() const BOOST_NOEXCEPT +{ mapping_handle_t mhnd = { m_shmid, true}; return mhnd; } + +inline bool xsi_shared_memory::priv_open_or_create + (ipcdetail::create_enum_t type, const xsi_key &key, const permissions& permissions, std::size_t size) +{ + int perm = (int)permissions.get_permissions(); + perm &= 0x01FF; + int shmflg = perm; + + switch(type){ + case ipcdetail::DoOpen: + shmflg |= 0; + break; + case ipcdetail::DoCreate: + shmflg |= IPC_CREAT | IPC_EXCL; + break; + case ipcdetail::DoOpenOrCreate: + shmflg |= IPC_CREAT; + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + int ret = ::shmget(key.get_key(), size, shmflg); + int shmid = ret; + if((type == ipcdetail::DoOpen) && (-1 != ret)){ + //Now get the size + ::shmid_ds xsi_ds; + ret = ::shmctl(ret, IPC_STAT, &xsi_ds); + size = xsi_ds.shm_segsz; + } + if(-1 == ret){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + + m_shmid = shmid; + return true; +} + +inline bool xsi_shared_memory::remove(int shmid) +{ return -1 != ::shmctl(shmid, IPC_RMID, 0); } + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP From 3241a456bd4966c371b790ca8b6554628388eed5 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Wed, 9 Jul 2025 10:59:20 -0300 Subject: [PATCH 2/7] Fix #8639 - Concurrency problem in remote profiler communication mechanism. --- src/jrd/ProfilerManager.cpp | 191 +++++++++++++++++++++++------------- 1 file changed, 124 insertions(+), 67 deletions(-) diff --git a/src/jrd/ProfilerManager.cpp b/src/jrd/ProfilerManager.cpp index 0897ad355e3..5fee8aabff0 100644 --- a/src/jrd/ProfilerManager.cpp +++ b/src/jrd/ProfilerManager.cpp @@ -35,6 +35,9 @@ #include "../jrd/tra_proto.h" #include +#include +#include +#include "boost/interprocess/sync/interprocess_mutex.hpp" #ifdef WIN_NT #include @@ -100,11 +103,13 @@ namespace event_t clientEvent; USHORT bufferSize; std::atomic tag; + unsigned seq; + boost::interprocess::interprocess_mutex bufferMutex; char userName[USERNAME_LENGTH + 1]; // \0 if has PROFILE_ANY_ATTACHMENT alignas(FB_ALIGNMENT) UCHAR buffer[4096]; }; - static const USHORT VERSION = 2; + static const USHORT VERSION = 3; public: ProfilerIpc(thread_db* tdbb, MemoryPool& pool, AttNumber aAttachmentId, bool server = false); @@ -179,7 +184,7 @@ class Jrd::ProfilerListener final listener->watcherThread(); } - void processCommand(thread_db* tdbb); + void processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std::vector& buffer); private: Attachment* const attachment; @@ -736,6 +741,8 @@ ProfilerIpc::ProfilerIpc(thread_db* tdbb, MemoryPool& pool, AttNumber aAttachmen { Guard guard(this); + header->seq = 0; + if (sharedMemory->eventInit(&header->serverEvent) != FB_SUCCESS) (Arg::Gds(isc_random) << "ProfilerIpc eventInit(serverEvent) failed").raise(); } @@ -817,18 +824,17 @@ void ProfilerIpc::internalSendAndReceive(thread_db* tdbb, Tag tag, } }); - const SLONG value = sharedMemory->eventClear(&header->clientEvent); + const SLONG clientEventCounter = sharedMemory->eventClear(&header->clientEvent); + + std::unique_lock bufferMutexLock(header->bufferMutex); - const Tag oldTag = header->tag.exchange(tag); - switch (oldTag) + switch (header->tag) { case Tag::NOP: - header->tag = oldTag; (Arg::Gds(isc_random) << "Remote attachment failed to start listener thread").raise(); break; case Tag::SERVER_EXITED: - header->tag = oldTag; (Arg::Gds(isc_random) << "Cannot start remote profile session - attachment exited").raise(); break; @@ -846,41 +852,49 @@ void ProfilerIpc::internalSendAndReceive(thread_db* tdbb, Tag tag, fb_assert(inSize <= sizeof(header->buffer)); memcpy(header->buffer, in, inSize); + header->tag = tag; + const auto seq = ++header->seq; + + bufferMutexLock.unlock(); + if (sharedMemory->eventPost(&header->serverEvent) != FB_SUCCESS) (Arg::Gds(isc_random) << "Cannot start remote profile session - attachment exited").raise(); + const SLONG TIMEOUT = 500 * 1000; // 0.5 sec + const int serverPID = header->serverEvent.event_pid; + + while (true) { - const SLONG TIMEOUT = 500 * 1000; // 0.5 sec + { // scope + EngineCheckout cout(tdbb, FB_FUNCTION); - const int serverPID = header->serverEvent.event_pid; - while (true) - { + if (sharedMemory->eventWait(&header->clientEvent, clientEventCounter, TIMEOUT) == FB_SUCCESS) + break; + + if (serverPID != getpid() && !ISC_check_process_existence(serverPID)) { - EngineCheckout cout(tdbb, FB_FUNCTION); - if (sharedMemory->eventWait(&header->clientEvent, value, TIMEOUT) == FB_SUCCESS) - break; + // Server process was died or exited + fb_assert((header->tag == tag) || header->tag == Tag::SERVER_EXITED); - if (serverPID != getpid() && !ISC_check_process_existence(serverPID)) + if (header->tag == tag) { - // Server process was died or exited - fb_assert((header->tag == tag) || header->tag == Tag::SERVER_EXITED); - - if (header->tag == tag) + header->tag = Tag::SERVER_EXITED; + if (header->serverEvent.event_pid) { - header->tag = Tag::SERVER_EXITED; - if (header->serverEvent.event_pid) - { - sharedMemory->eventFini(&header->serverEvent); - header->serverEvent.event_pid = 0; - } + sharedMemory->eventFini(&header->serverEvent); + header->serverEvent.event_pid = 0; } - break; } + + break; } - JRD_reschedule(tdbb, true); } + + JRD_reschedule(tdbb, true); } + bufferMutexLock.lock(); + switch (header->tag) { case Tag::SERVER_EXITED: @@ -977,7 +991,7 @@ void ProfilerListener::watcherThread() { while (!exiting) { - const SLONG value = sharedMemory->eventClear(&header->serverEvent); + const SLONG serverEventCounter = sharedMemory->eventClear(&header->serverEvent); if (startup) { @@ -986,6 +1000,10 @@ void ProfilerListener::watcherThread() } else { + ProfilerIpc::Tag tag; + unsigned seq; + std::vector buffer; + fb_assert(header->tag >= ProfilerIpc::Tag::FIRST_CLIENT_OP); try @@ -993,11 +1011,28 @@ void ProfilerListener::watcherThread() FbLocalStatus statusVector; EngineContextHolder tdbb(&statusVector, attachment->getInterface(), FB_FUNCTION); - processCommand(tdbb); - header->tag = ProfilerIpc::Tag::RESPONSE; + { // scope + std::unique_lock bufferMutexLock(header->bufferMutex); + + if (header->userName[0] && attachment->getUserName() != header->userName) + status_exception::raise(Arg::Gds(isc_miss_prvlg) << "PROFILE_ANY_ATTACHMENT"); + + fb_assert(header->tag >= ProfilerIpc::Tag::FIRST_CLIENT_OP); + + tag = header->tag; + seq = header->seq; + buffer.resize(header->bufferSize); + memcpy(buffer.data(), header->buffer, header->bufferSize); + } + + processCommand(tdbb, tag, buffer); + + tag = ProfilerIpc::Tag::RESPONSE; } catch (const status_exception& e) { + tag = ProfilerIpc::Tag::EXCEPTION; + //// TODO: Serialize status vector instead of formated message. const ISC_STATUS* status = e.value(); @@ -1012,20 +1047,34 @@ void ProfilerListener::watcherThread() errorMsg += temp; } - header->bufferSize = MIN(errorMsg.length(), sizeof(header->buffer) - 1); - strncpy((char*) header->buffer, errorMsg.c_str(), sizeof(header->buffer)); - header->buffer[header->bufferSize] = '\0'; - - header->tag = ProfilerIpc::Tag::EXCEPTION; + header->bufferSize = MIN(errorMsg.length(), sizeof(header->buffer)); + memcpy(header->buffer, errorMsg.c_str(), header->bufferSize); } - sharedMemory->eventPost(&header->clientEvent); + fb_assert(buffer.size() <= sizeof(header->buffer)); + + { // scope + std::unique_lock bufferMutexLock(header->bufferMutex, std::try_to_lock); + + // Otherwise a client lost interest in the response. + if (bufferMutexLock.owns_lock() && header->seq == seq) + { + if (header->seq == seq) + { + header->tag = tag; + header->bufferSize = buffer.size(); + memcpy(header->buffer, buffer.data(), buffer.size()); + + sharedMemory->eventPost(&header->clientEvent); + } + } + } } if (exiting) break; - sharedMemory->eventWait(&header->serverEvent, value, 0); + sharedMemory->eventWait(&header->serverEvent, serverEventCounter, 0); } } catch (const Exception& ex) @@ -1033,11 +1082,16 @@ void ProfilerListener::watcherThread() iscLogException("Error in profiler watcher thread\n", ex); } - const ProfilerIpc::Tag oldTag = header->tag.exchange(ProfilerIpc::Tag::SERVER_EXITED); - if (oldTag >= ProfilerIpc::Tag::FIRST_CLIENT_OP) - { - fb_assert(header->clientEvent.event_pid); - sharedMemory->eventPost(&header->clientEvent); + { // scope + std::unique_lock bufferMutexLock(header->bufferMutex); + + if (header->tag >= ProfilerIpc::Tag::FIRST_CLIENT_OP) + { + fb_assert(header->clientEvent.event_pid); + sharedMemory->eventPost(&header->clientEvent); + } + + header->tag = ProfilerIpc::Tag::SERVER_EXITED; } try @@ -1051,70 +1105,75 @@ void ProfilerListener::watcherThread() } } -void ProfilerListener::processCommand(thread_db* tdbb) +void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std::vector& buffer) { - const auto header = ipc->sharedMemory->getHeader(); const auto profilerManager = attachment->getProfilerManager(tdbb); - if (header->userName[0] && attachment->getUserName() != header->userName) - status_exception::raise(Arg::Gds(isc_miss_prvlg) << "PROFILE_ANY_ATTACHMENT"); - using Tag = ProfilerIpc::Tag; - switch (header->tag) + switch (tag) { case Tag::CANCEL_SESSION: + fb_assert(buffer.empty()); profilerManager->cancelSession(); - header->bufferSize = 0; + buffer.resize(0); break; case Tag::DISCARD: + fb_assert(buffer.empty()); profilerManager->discard(); - header->bufferSize = 0; + buffer.resize(0); break; case Tag::FINISH_SESSION: { - const auto in = reinterpret_cast(header->buffer); - fb_assert(sizeof(*in) == header->bufferSize); + const auto in = reinterpret_cast(buffer.data()); + fb_assert(sizeof(*in) == buffer.size()); + profilerManager->finishSession(tdbb, in->flush); - header->bufferSize = 0; + + buffer.resize(0); break; } case Tag::FLUSH: + fb_assert(buffer.empty()); profilerManager->flush(); - header->bufferSize = 0; + buffer.resize(0); break; case Tag::PAUSE_SESSION: { - const auto in = reinterpret_cast(header->buffer); - fb_assert(sizeof(*in) == header->bufferSize); + const auto in = reinterpret_cast(buffer.data()); + fb_assert(sizeof(*in) == buffer.size()); + profilerManager->pauseSession(in->flush); - header->bufferSize = 0; + + buffer.resize(0); break; } case Tag::RESUME_SESSION: + fb_assert(buffer.empty()); profilerManager->resumeSession(); - header->bufferSize = 0; + buffer.resize(0); break; case Tag::SET_FLUSH_INTERVAL: { - const auto in = reinterpret_cast(header->buffer); - fb_assert(sizeof(*in) == header->bufferSize); + const auto in = reinterpret_cast(buffer.data()); + fb_assert(sizeof(*in) == buffer.size()); profilerManager->setFlushInterval(in->flushInterval); - header->bufferSize = 0; + + buffer.resize(0); break; } case Tag::START_SESSION: { - const auto in = reinterpret_cast(header->buffer); - fb_assert(sizeof(*in) == header->bufferSize); + const auto in = reinterpret_cast(buffer.data()); + fb_assert(sizeof(*in) == buffer.size()); const string description(in->description.str, in->descriptionNull ? 0 : in->description.length); @@ -1125,14 +1184,12 @@ void ProfilerListener::processCommand(thread_db* tdbb) const string pluginOptions(in->pluginOptions.str, in->pluginOptionsNull ? 0 : in->pluginOptions.length); - const auto out = reinterpret_cast(header->buffer); - static_assert(sizeof(*out) <= sizeof(header->buffer), "Buffer size too small"); - header->bufferSize = sizeof(*out); + const auto out = reinterpret_cast(buffer.data()); + buffer.resize(sizeof(*out)); out->sessionIdNull = FB_FALSE; out->sessionId = profilerManager->startSession(tdbb, flushInterval, pluginName, description, pluginOptions); - break; } From 743d2302ff7a459e983679fcf34ca0e53bb5740b Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 10 Jul 2025 07:58:20 -0300 Subject: [PATCH 3/7] Remove old Spinlock implementation. --- src/common/classes/locks.cpp | 9 +---- src/common/classes/locks.h | 65 +----------------------------------- 2 files changed, 2 insertions(+), 72 deletions(-) diff --git a/src/common/classes/locks.cpp b/src/common/classes/locks.cpp index 1f4f482d0d6..a66a6ca621c 100644 --- a/src/common/classes/locks.cpp +++ b/src/common/classes/locks.cpp @@ -38,14 +38,7 @@ namespace Firebird { -#if defined(WIN_NT) - -void Spinlock::init() -{ - SetCriticalSectionSpinCount(&spinlock, 4000); -} - -#else //posix mutex +#if !defined(WIN_NT) pthread_mutexattr_t Mutex::attr; diff --git a/src/common/classes/locks.h b/src/common/classes/locks.h index cda84ae1e4a..2c44ca01df3 100644 --- a/src/common/classes/locks.h +++ b/src/common/classes/locks.h @@ -50,8 +50,7 @@ class Exception; // Needed for catch #ifdef WIN_NT -// Generic process-local mutex and spinlock. The latter -// is used to manage memory heaps in a threaded environment. +// Generic process-local mutex. // Windows version of the class @@ -151,23 +150,6 @@ class Mutex : public Reasons Mutex& operator=(const Mutex&); }; -class Spinlock : public Mutex -{ -private: - void init(); - -public: - Spinlock() - { - init(); - } - - explicit Spinlock(MemoryPool&) - { - init(); - } -}; - #else //WIN_NT // Pthreads version of the class @@ -272,51 +254,6 @@ friend class Condition; Mutex& operator=(const Mutex&); }; -#ifdef NOT_USED_OR_REPLACED // we do not use spinlocks currently -class Spinlock -{ -private: - pthread_spinlock_t spinlock; -public: - Spinlock() - { - if (pthread_spin_init(&spinlock, false)) - system_call_failed::raise("pthread_spin_init"); - } - - explicit Spinlock(MemoryPool&) - { - if (pthread_spin_init(&spinlock, false)) - system_call_failed::raise("pthread_spin_init"); - } - - ~Spinlock() - { - if (pthread_spin_destroy(&spinlock)) - system_call_failed::raise("pthread_spin_destroy"); - } - - void enter() - { - if (pthread_spin_lock(&spinlock)) - system_call_failed::raise("pthread_spin_lock"); - } - - void leave() - { - if (pthread_spin_unlock(&spinlock)) - system_call_failed::raise("pthread_spin_unlock"); - } - -private: - // Forbid copying - Spinlock(const Spinlock&); - Spinlock& operator=(const Spinlock&); -}; -#else -typedef Mutex Spinlock; -#endif - #endif //WIN_NT From b14e18950706b5196f86e906f804dab0652d41ee Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 10 Jul 2025 08:09:18 -0300 Subject: [PATCH 4/7] Add new Spinlock class. --- src/common/classes/Spinlock.h | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/common/classes/Spinlock.h diff --git a/src/common/classes/Spinlock.h b/src/common/classes/Spinlock.h new file mode 100644 index 00000000000..132214c00d9 --- /dev/null +++ b/src/common/classes/Spinlock.h @@ -0,0 +1,73 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2025 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef CLASSES_SPINLOCK_H +#define CLASSES_SPINLOCK_H + +#include +#include + +namespace Firebird { + + +// Spinlock implementation that can be used in shared memory. +// Based in example found in https://en.cppreference.com/w/cpp/atomic/atomic_flag.html +// Compatible with std::lock_guard, std::scoped_lock and std::unique_lock. +class SpinLock +{ + std::atomic_flag atomicFlag = ATOMIC_FLAG_INIT; + +public: + void lock() noexcept + { + while (atomicFlag.test_and_set(std::memory_order_acquire)) + { +#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L + // Since C++20, locks can be acquired only after notification in the unlock, + // avoiding any unnecessary spinning. + // Note that even though wait guarantees it returns only after the value has + // changed, the lock is acquired after the next condition check. + atomicFlag.wait(true, std::memory_order_relaxed); +#else + std::this_thread::yield(); +#endif + } + } + + bool try_lock() noexcept + { + return !atomicFlag.test_and_set(std::memory_order_acquire); + } + + void unlock() noexcept + { + atomicFlag.clear(std::memory_order_release); +#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L + atomicFlag.notify_one(); +#endif + } +}; + + +} // namespace Firebird + +#endif // CLASSES_SPINLOCK_H From 3fb235d07ec992f2169e65a5a67bb48c76330c9b Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 10 Jul 2025 08:09:57 -0300 Subject: [PATCH 5/7] Replace boost::interprocess::interprocess_mutex by Spinlock. --- src/jrd/ProfilerManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jrd/ProfilerManager.cpp b/src/jrd/ProfilerManager.cpp index 5fee8aabff0..2a00d89f575 100644 --- a/src/jrd/ProfilerManager.cpp +++ b/src/jrd/ProfilerManager.cpp @@ -33,11 +33,11 @@ #include "../jrd/met_proto.h" #include "../jrd/pag_proto.h" #include "../jrd/tra_proto.h" +#include "../common/classes/Spinlock.h" #include #include #include -#include "boost/interprocess/sync/interprocess_mutex.hpp" #ifdef WIN_NT #include @@ -103,8 +103,8 @@ namespace event_t clientEvent; USHORT bufferSize; std::atomic tag; - unsigned seq; - boost::interprocess::interprocess_mutex bufferMutex; + std::atomic_uint seq; + SpinLock bufferMutex; char userName[USERNAME_LENGTH + 1]; // \0 if has PROFILE_ANY_ATTACHMENT alignas(FB_ALIGNMENT) UCHAR buffer[4096]; }; From 523e7272815c7dca5a92f78a069a804694d7a920 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 10 Jul 2025 08:16:03 -0300 Subject: [PATCH 6/7] Replace vector by UCharBuffer. --- src/jrd/ProfilerManager.cpp | 42 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/jrd/ProfilerManager.cpp b/src/jrd/ProfilerManager.cpp index 2a00d89f575..7b5c6eb1b72 100644 --- a/src/jrd/ProfilerManager.cpp +++ b/src/jrd/ProfilerManager.cpp @@ -37,7 +37,6 @@ #include #include -#include #ifdef WIN_NT #include @@ -184,7 +183,7 @@ class Jrd::ProfilerListener final listener->watcherThread(); } - void processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std::vector& buffer); + void processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, UCharBuffer& buffer); private: Attachment* const attachment; @@ -1002,7 +1001,7 @@ void ProfilerListener::watcherThread() { ProfilerIpc::Tag tag; unsigned seq; - std::vector buffer; + UCharBuffer buffer; fb_assert(header->tag >= ProfilerIpc::Tag::FIRST_CLIENT_OP); @@ -1021,8 +1020,7 @@ void ProfilerListener::watcherThread() tag = header->tag; seq = header->seq; - buffer.resize(header->bufferSize); - memcpy(buffer.data(), header->buffer, header->bufferSize); + memcpy(buffer.getBuffer(header->bufferSize, false), header->buffer, header->bufferSize); } processCommand(tdbb, tag, buffer); @@ -1051,7 +1049,7 @@ void ProfilerListener::watcherThread() memcpy(header->buffer, errorMsg.c_str(), header->bufferSize); } - fb_assert(buffer.size() <= sizeof(header->buffer)); + fb_assert(buffer.getCount() <= sizeof(header->buffer)); { // scope std::unique_lock bufferMutexLock(header->bufferMutex, std::try_to_lock); @@ -1062,8 +1060,8 @@ void ProfilerListener::watcherThread() if (header->seq == seq) { header->tag = tag; - header->bufferSize = buffer.size(); - memcpy(header->buffer, buffer.data(), buffer.size()); + header->bufferSize = buffer.getCount(); + memcpy(header->buffer, buffer.begin(), buffer.getCount()); sharedMemory->eventPost(&header->clientEvent); } @@ -1105,7 +1103,7 @@ void ProfilerListener::watcherThread() } } -void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std::vector& buffer) +void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, UCharBuffer& buffer) { const auto profilerManager = attachment->getProfilerManager(tdbb); @@ -1114,21 +1112,21 @@ void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std switch (tag) { case Tag::CANCEL_SESSION: - fb_assert(buffer.empty()); + fb_assert(buffer.isEmpty()); profilerManager->cancelSession(); buffer.resize(0); break; case Tag::DISCARD: - fb_assert(buffer.empty()); + fb_assert(buffer.isEmpty()); profilerManager->discard(); buffer.resize(0); break; case Tag::FINISH_SESSION: { - const auto in = reinterpret_cast(buffer.data()); - fb_assert(sizeof(*in) == buffer.size()); + const auto in = reinterpret_cast(buffer.begin()); + fb_assert(sizeof(*in) == buffer.getCount()); profilerManager->finishSession(tdbb, in->flush); @@ -1137,15 +1135,15 @@ void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std } case Tag::FLUSH: - fb_assert(buffer.empty()); + fb_assert(buffer.isEmpty()); profilerManager->flush(); buffer.resize(0); break; case Tag::PAUSE_SESSION: { - const auto in = reinterpret_cast(buffer.data()); - fb_assert(sizeof(*in) == buffer.size()); + const auto in = reinterpret_cast(buffer.begin()); + fb_assert(sizeof(*in) == buffer.getCount()); profilerManager->pauseSession(in->flush); @@ -1154,15 +1152,15 @@ void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std } case Tag::RESUME_SESSION: - fb_assert(buffer.empty()); + fb_assert(buffer.isEmpty()); profilerManager->resumeSession(); buffer.resize(0); break; case Tag::SET_FLUSH_INTERVAL: { - const auto in = reinterpret_cast(buffer.data()); - fb_assert(sizeof(*in) == buffer.size()); + const auto in = reinterpret_cast(buffer.begin()); + fb_assert(sizeof(*in) == buffer.getCount()); profilerManager->setFlushInterval(in->flushInterval); @@ -1172,8 +1170,8 @@ void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std case Tag::START_SESSION: { - const auto in = reinterpret_cast(buffer.data()); - fb_assert(sizeof(*in) == buffer.size()); + const auto in = reinterpret_cast(buffer.begin()); + fb_assert(sizeof(*in) == buffer.getCount()); const string description(in->description.str, in->descriptionNull ? 0 : in->description.length); @@ -1184,7 +1182,7 @@ void ProfilerListener::processCommand(thread_db* tdbb, ProfilerIpc::Tag tag, std const string pluginOptions(in->pluginOptions.str, in->pluginOptionsNull ? 0 : in->pluginOptions.length); - const auto out = reinterpret_cast(buffer.data()); + const auto out = reinterpret_cast(buffer.begin()); buffer.resize(sizeof(*out)); out->sessionIdNull = FB_FALSE; From 52af692e825d8d193d3f7472194756f1ca008c90 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 10 Jul 2025 08:22:15 -0300 Subject: [PATCH 7/7] Revert "Add boost/interprocess." This reverts commit 62ad26ff8327909580b94afba1b669dbd9d31cd4. --- .../interprocess/allocators/adaptive_pool.hpp | 470 ------ .../interprocess/allocators/allocator.hpp | 294 ---- .../allocators/cached_adaptive_pool.hpp | 357 ----- .../allocators/cached_node_allocator.hpp | 328 ---- .../allocators/detail/adaptive_node_pool.hpp | 115 -- .../allocators/detail/allocator_common.hpp | 857 ----------- .../allocators/detail/node_pool.hpp | 111 -- .../allocators/detail/node_tools.hpp | 54 - .../allocators/node_allocator.hpp | 454 ------ .../allocators/private_adaptive_pool.hpp | 470 ------ .../allocators/private_node_allocator.hpp | 447 ------ .../interprocess/anonymous_shared_memory.hpp | 125 -- .../containers/allocation_type.hpp | 44 - .../containers/containers_fwd.hpp | 44 - .../boost/interprocess/containers/deque.hpp | 37 - .../interprocess/containers/flat_map.hpp | 37 - .../interprocess/containers/flat_set.hpp | 37 - .../boost/interprocess/containers/list.hpp | 37 - .../boost/interprocess/containers/map.hpp | 37 - .../boost/interprocess/containers/pair.hpp | 37 - .../boost/interprocess/containers/set.hpp | 37 - .../boost/interprocess/containers/slist.hpp | 36 - .../interprocess/containers/stable_vector.hpp | 36 - .../boost/interprocess/containers/string.hpp | 37 - .../boost/interprocess/containers/vector.hpp | 37 - .../interprocess/containers/version_type.hpp | 37 - .../boost/interprocess/detail/cast_tags.hpp | 31 - .../detail/file_locking_helpers.hpp | 302 ---- .../interprocess/detail/file_wrapper.hpp | 233 --- .../detail/in_place_interface.hpp | 77 - .../detail/intermodule_singleton.hpp | 53 - .../detail/interprocess_tester.hpp | 39 - .../detail/managed_global_memory.hpp | 119 -- .../detail/managed_memory_impl.hpp | 775 ---------- .../detail/managed_open_or_create_impl.hpp | 574 ------- .../interprocess/detail/math_functions.hpp | 118 -- .../boost/boost/interprocess/detail/move.hpp | 36 - .../boost/interprocess/detail/named_proxy.hpp | 284 ---- .../boost/interprocess/detail/nothrow.hpp | 42 - .../interprocess/detail/pointer_type.hpp | 78 - .../detail/portable_intermodule_singleton.hpp | 361 ----- .../interprocess/detail/robust_emulation.hpp | 387 ----- .../detail/segment_manager_helper.hpp | 503 ------ .../detail/transform_iterator.hpp | 44 - .../detail/variadic_templates_tools.hpp | 35 - .../detail/xsi_shared_memory_file_wrapper.hpp | 88 -- .../boost/boost/interprocess/file_mapping.hpp | 250 --- .../interprocess/indexes/flat_map_index.hpp | 93 -- .../boost/interprocess/indexes/iset_index.hpp | 158 -- .../indexes/iunordered_set_index.hpp | 390 ----- .../boost/interprocess/indexes/map_index.hpp | 109 -- .../boost/interprocess/indexes/null_index.hpp | 76 - .../boost/interprocess/ipc/message_queue.hpp | 1131 -------------- .../interprocess/managed_external_buffer.hpp | 143 -- .../interprocess/managed_heap_memory.hpp | 172 --- .../interprocess/managed_mapped_file.hpp | 370 ----- .../interprocess/managed_shared_memory.hpp | 388 ----- .../managed_windows_shared_memory.hpp | 288 ---- .../managed_xsi_shared_memory.hpp | 251 --- .../mem_algo/detail/mem_algo_common.hpp | 599 -------- .../mem_algo/detail/simple_seq_fit_impl.hpp | 1107 -------------- .../interprocess/mem_algo/rbtree_best_fit.hpp | 1359 ----------------- .../interprocess/mem_algo/simple_seq_fit.hpp | 62 - .../boost/boost/interprocess/offset_ptr.hpp | 776 ---------- .../boost/interprocess/segment_manager.hpp | 1357 ---------------- .../boost/interprocess/smart_ptr/deleter.hpp | 68 - .../smart_ptr/detail/bad_weak_ptr.hpp | 48 - .../smart_ptr/detail/shared_count.hpp | 347 ----- .../smart_ptr/detail/sp_counted_base.hpp | 26 - .../detail/sp_counted_base_atomic.hpp | 94 -- .../smart_ptr/detail/sp_counted_impl.hpp | 164 -- .../smart_ptr/enable_shared_from_this.hpp | 87 -- .../interprocess/smart_ptr/intrusive_ptr.hpp | 333 ---- .../interprocess/smart_ptr/scoped_ptr.hpp | 176 --- .../interprocess/smart_ptr/shared_ptr.hpp | 430 ------ .../interprocess/smart_ptr/unique_ptr.hpp | 63 - .../boost/interprocess/smart_ptr/weak_ptr.hpp | 271 ---- .../interprocess/streams/vectorstream.hpp | 633 -------- .../boost/interprocess/sync/cv_status.hpp | 29 - .../sync/detail/condition_algorithm_8a.hpp | 389 ----- .../sync/detail/condition_any_algorithm.hpp | 191 --- .../boost/interprocess/sync/detail/locks.hpp | 111 -- .../boost/interprocess/sync/file_lock.hpp | 324 ---- .../sync/interprocess_condition.hpp | 177 --- .../sync/interprocess_condition_any.hpp | 154 -- .../interprocess/sync/interprocess_mutex.hpp | 198 --- .../sync/interprocess_recursive_mutex.hpp | 184 --- .../sync/interprocess_semaphore.hpp | 143 -- .../sync/interprocess_sharable_mutex.hpp | 424 ----- .../sync/interprocess_upgradable_mutex.hpp | 771 ---------- .../boost/interprocess/sync/mutex_family.hpp | 60 - .../interprocess/sync/named_condition.hpp | 299 ---- .../interprocess/sync/named_condition_any.hpp | 230 --- .../boost/interprocess/sync/named_mutex.hpp | 267 ---- .../sync/named_recursive_mutex.hpp | 245 --- .../interprocess/sync/named_semaphore.hpp | 239 --- .../sync/named_sharable_mutex.hpp | 391 ----- .../sync/named_upgradable_mutex.hpp | 540 ------- .../boost/interprocess/sync/null_mutex.hpp | 178 --- .../interprocess/sync/posix/condition.hpp | 218 --- .../boost/interprocess/sync/posix/mutex.hpp | 188 --- .../interprocess/sync/posix/named_mutex.hpp | 126 -- .../sync/posix/named_semaphore.hpp | 89 -- .../sync/posix/pthread_helpers.hpp | 176 --- .../sync/posix/recursive_mutex.hpp | 175 --- .../interprocess/sync/posix/semaphore.hpp | 67 - .../sync/posix/semaphore_wrapper.hpp | 254 --- .../sync/posix/timepoint_to_timespec.hpp | 91 -- .../boost/interprocess/sync/sharable_lock.hpp | 351 ----- .../interprocess/sync/shm/named_condition.hpp | 348 ----- .../sync/shm/named_condition_any.hpp | 226 --- .../sync/shm/named_creation_functor.hpp | 81 - .../interprocess/sync/shm/named_mutex.hpp | 259 ---- .../sync/shm/named_recursive_mutex.hpp | 249 --- .../interprocess/sync/shm/named_semaphore.hpp | 198 --- .../sync/shm/named_upgradable_mutex.hpp | 360 ----- .../interprocess/sync/spin/condition.hpp | 299 ---- .../sync/spin/interprocess_barrier.hpp | 53 - .../sync/spin/recursive_mutex.hpp | 185 --- .../interprocess/sync/spin/semaphore.hpp | 94 -- .../interprocess/sync/upgradable_lock.hpp | 314 ---- .../interprocess/sync/windows/condition.hpp | 147 -- .../boost/interprocess/sync/windows/mutex.hpp | 126 -- .../sync/windows/named_condition.hpp | 40 - .../sync/windows/named_condition_any.hpp | 337 ---- .../interprocess/sync/windows/named_mutex.hpp | 232 --- .../sync/windows/named_recursive_mutex.hpp | 74 - .../sync/windows/named_semaphore.hpp | 230 --- .../interprocess/sync/windows/named_sync.hpp | 237 --- .../sync/windows/recursive_mutex.hpp | 47 - .../interprocess/sync/windows/semaphore.hpp | 119 -- .../interprocess/windows_shared_memory.hpp | 277 ---- extern/boost/boost/interprocess/xsi_key.hpp | 101 -- .../boost/interprocess/xsi_shared_memory.hpp | 215 --- 134 files changed, 32737 deletions(-) delete mode 100644 extern/boost/boost/interprocess/allocators/adaptive_pool.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/allocator.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/detail/node_pool.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/detail/node_tools.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/node_allocator.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp delete mode 100644 extern/boost/boost/interprocess/allocators/private_node_allocator.hpp delete mode 100644 extern/boost/boost/interprocess/anonymous_shared_memory.hpp delete mode 100644 extern/boost/boost/interprocess/containers/allocation_type.hpp delete mode 100644 extern/boost/boost/interprocess/containers/containers_fwd.hpp delete mode 100644 extern/boost/boost/interprocess/containers/deque.hpp delete mode 100644 extern/boost/boost/interprocess/containers/flat_map.hpp delete mode 100644 extern/boost/boost/interprocess/containers/flat_set.hpp delete mode 100644 extern/boost/boost/interprocess/containers/list.hpp delete mode 100644 extern/boost/boost/interprocess/containers/map.hpp delete mode 100644 extern/boost/boost/interprocess/containers/pair.hpp delete mode 100644 extern/boost/boost/interprocess/containers/set.hpp delete mode 100644 extern/boost/boost/interprocess/containers/slist.hpp delete mode 100644 extern/boost/boost/interprocess/containers/stable_vector.hpp delete mode 100644 extern/boost/boost/interprocess/containers/string.hpp delete mode 100644 extern/boost/boost/interprocess/containers/vector.hpp delete mode 100644 extern/boost/boost/interprocess/containers/version_type.hpp delete mode 100644 extern/boost/boost/interprocess/detail/cast_tags.hpp delete mode 100644 extern/boost/boost/interprocess/detail/file_locking_helpers.hpp delete mode 100644 extern/boost/boost/interprocess/detail/file_wrapper.hpp delete mode 100644 extern/boost/boost/interprocess/detail/in_place_interface.hpp delete mode 100644 extern/boost/boost/interprocess/detail/intermodule_singleton.hpp delete mode 100644 extern/boost/boost/interprocess/detail/interprocess_tester.hpp delete mode 100644 extern/boost/boost/interprocess/detail/managed_global_memory.hpp delete mode 100644 extern/boost/boost/interprocess/detail/managed_memory_impl.hpp delete mode 100644 extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp delete mode 100644 extern/boost/boost/interprocess/detail/math_functions.hpp delete mode 100644 extern/boost/boost/interprocess/detail/move.hpp delete mode 100644 extern/boost/boost/interprocess/detail/named_proxy.hpp delete mode 100644 extern/boost/boost/interprocess/detail/nothrow.hpp delete mode 100644 extern/boost/boost/interprocess/detail/pointer_type.hpp delete mode 100644 extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp delete mode 100644 extern/boost/boost/interprocess/detail/robust_emulation.hpp delete mode 100644 extern/boost/boost/interprocess/detail/segment_manager_helper.hpp delete mode 100644 extern/boost/boost/interprocess/detail/transform_iterator.hpp delete mode 100644 extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp delete mode 100644 extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp delete mode 100644 extern/boost/boost/interprocess/file_mapping.hpp delete mode 100644 extern/boost/boost/interprocess/indexes/flat_map_index.hpp delete mode 100644 extern/boost/boost/interprocess/indexes/iset_index.hpp delete mode 100644 extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp delete mode 100644 extern/boost/boost/interprocess/indexes/map_index.hpp delete mode 100644 extern/boost/boost/interprocess/indexes/null_index.hpp delete mode 100644 extern/boost/boost/interprocess/ipc/message_queue.hpp delete mode 100644 extern/boost/boost/interprocess/managed_external_buffer.hpp delete mode 100644 extern/boost/boost/interprocess/managed_heap_memory.hpp delete mode 100644 extern/boost/boost/interprocess/managed_mapped_file.hpp delete mode 100644 extern/boost/boost/interprocess/managed_shared_memory.hpp delete mode 100644 extern/boost/boost/interprocess/managed_windows_shared_memory.hpp delete mode 100644 extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp delete mode 100644 extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp delete mode 100644 extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp delete mode 100644 extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp delete mode 100644 extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp delete mode 100644 extern/boost/boost/interprocess/offset_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/segment_manager.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/deleter.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp delete mode 100644 extern/boost/boost/interprocess/streams/vectorstream.hpp delete mode 100644 extern/boost/boost/interprocess/sync/cv_status.hpp delete mode 100644 extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp delete mode 100644 extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp delete mode 100644 extern/boost/boost/interprocess/sync/detail/locks.hpp delete mode 100644 extern/boost/boost/interprocess/sync/file_lock.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/mutex_family.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_condition_any.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/null_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/named_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp delete mode 100644 extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp delete mode 100644 extern/boost/boost/interprocess/sync/sharable_lock.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/spin/condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp delete mode 100644 extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/spin/semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/upgradable_lock.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_condition.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/named_sync.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp delete mode 100644 extern/boost/boost/interprocess/sync/windows/semaphore.hpp delete mode 100644 extern/boost/boost/interprocess/windows_shared_memory.hpp delete mode 100644 extern/boost/boost/interprocess/xsi_key.hpp delete mode 100644 extern/boost/boost/interprocess/xsi_shared_memory.hpp diff --git a/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp deleted file mode 100644 index 83b9e8d6dce..00000000000 --- a/extern/boost/boost/interprocess/allocators/adaptive_pool.hpp +++ /dev/null @@ -1,470 +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_ADAPTIVE_POOL_HPP -#define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes adaptive_pool pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail{ - -template < unsigned int Version - , class T - , class SegmentManager - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class adaptive_pool_base - : public node_pool_allocation_impl - < adaptive_pool_base - < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> - , Version - , T - , SegmentManager - > -{ - public: - typedef typename SegmentManager::void_pointer void_pointer; - typedef SegmentManager segment_manager; - typedef adaptive_pool_base - self_t; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - template - struct node_pool - { - typedef ipcdetail::shared_adaptive_node_pool - < SegmentManager, sizeof_value::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type; - - static type *get(void *p) - { return static_cast(p); } - }; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - BOOST_STATIC_ASSERT((Version <=2)); - - public: - //------- - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - typedef boost::interprocess::version_type version; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - //!Obtains adaptive_pool_base from - //!adaptive_pool_base - template - struct rebind - { - typedef adaptive_pool_base other; - }; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - //!Not assignable from related adaptive_pool_base - template - adaptive_pool_base& operator= - (const adaptive_pool_base&); - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - adaptive_pool_base(segment_manager *segment_mngr) - : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(segment_mngr)) { } - - //!Copy constructor from other adaptive_pool_base. Increments the reference - //!count of the associated node pool. Never throws - adaptive_pool_base(const adaptive_pool_base &other) - : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); - } - - //!Assignment from other adaptive_pool_base - adaptive_pool_base& operator=(const adaptive_pool_base &other) - { - adaptive_pool_base c(other); - boost::adl_move_swap(*this, c); - return *this; - } - - //!Copy constructor from related adaptive_pool_base. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - adaptive_pool_base - (const adaptive_pool_base &other) - : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(other.get_segment_manager())) { } - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~adaptive_pool_base() - { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } - - //!Returns a pointer to the node pool. - //!Never throws - void* get_node_pool() const - { return ipcdetail::to_raw_pointer(mp_node_pool); } - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const - { return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); } - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2) - { boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - void_pointer mp_node_pool; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Equality test for same type -//!of adaptive_pool_base -template inline -bool operator==(const adaptive_pool_base &alloc1, - const adaptive_pool_base &alloc2) - { return alloc1.get_node_pool() == alloc2.get_node_pool(); } - -//!Inequality test for same type -//!of adaptive_pool_base -template inline -bool operator!=(const adaptive_pool_base &alloc1, - const adaptive_pool_base &alloc2) - { return alloc1.get_node_pool() != alloc2.get_node_pool(); } - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - , std::size_t MaxFreeBlocks = 2 - , unsigned char OverheadPercent = 5 - > -class adaptive_pool_v1 - : public adaptive_pool_base - < 1 - , T - , SegmentManager - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > -{ - public: - typedef ipcdetail::adaptive_pool_base - < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; - - template - struct rebind - { - typedef adaptive_pool_v1 other; - }; - - adaptive_pool_v1(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - adaptive_pool_v1 - (const adaptive_pool_v1 &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail{ - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!An STL node allocator that uses a segment manager as memory -//!source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -//! -//!This node allocator shares a segregated storage between all instances -//!of adaptive_pool with equal sizeof(T) placed in the same segment -//!group. NodesPerBlock is the number of nodes allocated at once when the allocator -//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks -//!that the adaptive node pool will hold. The rest of the totally free blocks will be -//!deallocated with the segment manager. -//! -//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: -//!(memory usable for nodes / total memory allocated from the segment manager) -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class adaptive_pool - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::adaptive_pool_base - < 2 - , T - , SegmentManager - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef ipcdetail::adaptive_pool_base - < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; - public: - typedef boost::interprocess::version_type version; - - template - struct rebind - { - typedef adaptive_pool other; - }; - - adaptive_pool(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - adaptive_pool - (const adaptive_pool &other) - : base_t(other) - {} - - #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - //!Obtains adaptive_pool from - //!adaptive_pool - template - struct rebind - { - typedef adaptive_pool other; - }; - - private: - //!Not assignable from - //!related adaptive_pool - template - adaptive_pool& operator= - (const adaptive_pool&); - - //!Not assignable from - //!other adaptive_pool - //adaptive_pool& operator=(const adaptive_pool&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - adaptive_pool(segment_manager *segment_mngr); - - //!Copy constructor from other adaptive_pool. Increments the reference - //!count of the associated node pool. Never throws - adaptive_pool(const adaptive_pool &other); - - //!Copy constructor from related adaptive_pool. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - adaptive_pool - (const adaptive_pool &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~adaptive_pool(); - - //!Returns a pointer to the node pool. - //!Never throws - void* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; -/* - //!Copy construct an object. - //!Throws if T's copy constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); -*/ - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain); - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of adaptive_pool -template inline -bool operator==(const adaptive_pool &alloc1, - const adaptive_pool &alloc2); - -//!Inequality test for same type -//!of adaptive_pool -template inline -bool operator!=(const adaptive_pool &alloc1, - const adaptive_pool &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP - diff --git a/extern/boost/boost/interprocess/allocators/allocator.hpp b/extern/boost/boost/interprocess/allocators/allocator.hpp deleted file mode 100644 index 127df774f54..00000000000 --- a/extern/boost/boost/interprocess/allocators/allocator.hpp +++ /dev/null @@ -1,294 +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_ALLOCATOR_HPP -#define BOOST_INTERPROCESS_ALLOCATOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -//!\file -//!Describes an allocator that allocates portions of fixed size -//!memory buffer (shared memory, mapped file...) - -namespace boost { -namespace interprocess { - - -//!An STL compatible allocator that uses a segment manager as -//!memory source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -template -class allocator -{ - public: - //Segment manager - typedef SegmentManager segment_manager; - typedef typename SegmentManager::void_pointer void_pointer; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - //Self type - typedef allocator self_t; - - //Pointer to void - typedef typename segment_manager::void_pointer aux_pointer_t; - - //Typedef to const void pointer - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type cvoid_ptr; - - //Pointer to the allocator - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type alloc_ptr_t; - - //Not assignable from related allocator - template - allocator& operator=(const allocator&); - - //Not assignable from other allocator - allocator& operator=(const allocator&); - - //Pointer to the allocator - alloc_ptr_t mp_mngr; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef T value_type; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - typedef boost::interprocess::version_type version; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Experimental. Don't use. - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Obtains an allocator that allocates - //!objects of type T2 - template - struct rebind - { - typedef allocator other; - }; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const - { return ipcdetail::to_raw_pointer(mp_mngr); } - - //!Constructor from the segment manager. - //!Never throws - allocator(segment_manager *segment_mngr) - : mp_mngr(segment_mngr) { } - - //!Constructor from other allocator. - //!Never throws - allocator(const allocator &other) - : mp_mngr(other.get_segment_manager()){ } - - //!Constructor from related allocator. - //!Never throws - template - allocator(const allocator &other) - : mp_mngr(other.get_segment_manager()){} - - //!Allocates memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_ptr hint = 0) - { - (void)hint; - if(size_overflows(count)){ - throw bad_alloc(); - } - return pointer(static_cast(mp_mngr->allocate(count*sizeof(T)))); - } - - //!Deallocates memory previously allocated. - //!Never throws - void deallocate(const pointer &ptr, size_type) - { mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); } - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const - { return mp_mngr->get_size()/sizeof(T); } - - //!Swap segment manager. Does not throw. If each allocator is placed in - //!different memory segments, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2) - { boost::adl_move_swap(alloc1.mp_mngr, alloc2.mp_mngr); } - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const - { - return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T); - } - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) - { - value_type *reuse_raw = ipcdetail::to_raw_pointer(reuse); - pointer const p = mp_mngr->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse_raw); - reuse = reuse_raw; - return p; - } - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) - { - if(size_overflows(elem_size)){ - throw bad_alloc(); - } - mp_mngr->allocate_many(elem_size*sizeof(T), num_elements, chain); - } - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) - { - mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T), chain); - } - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain) - { mp_mngr->deallocate_many(chain); } - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one() - { return this->allocate(1); } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain) - { this->allocate_many(1, num_elements, chain); } - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p) - { return this->deallocate(p, 1); } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain) - { this->deallocate_many(chain); } - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const - { return pointer(boost::addressof(value)); } - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const - { return const_pointer(boost::addressof(value)); } -}; - -//!Equality test for same type -//!of allocator -template inline -bool operator==(const allocator &alloc1, - const allocator &alloc2) - { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } - -//!Inequality test for same type -//!of allocator -template inline -bool operator!=(const allocator &alloc1, - const allocator &alloc2) - { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } - -} //namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -struct has_trivial_destructor; - -template -struct has_trivial_destructor - > -{ - static const bool value = true; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP - diff --git a/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp deleted file mode 100644 index 0ccf1f3638e..00000000000 --- a/extern/boost/boost/interprocess/allocators/cached_adaptive_pool.hpp +++ /dev/null @@ -1,357 +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_CACHED_ADAPTIVE_POOL_HPP -#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail { - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - , std::size_t MaxFreeBlocks = 2 - , unsigned char OverheadPercent = 5 - > -class cached_adaptive_pool_v1 - : public ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_adaptive_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - , 1> -{ - public: - typedef ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_adaptive_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - , 1> base_t; - - template - struct rebind - { - typedef cached_adaptive_pool_v1 - other; - }; - - typedef typename base_t::size_type size_type; - - cached_adaptive_pool_v1(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) - : base_t(segment_mngr, max_cached_nodes) - {} - - template - cached_adaptive_pool_v1 - (const cached_adaptive_pool_v1 - &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail{ - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!An STL node allocator that uses a segment manager as memory -//!source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -//! -//!This node allocator shares a segregated storage between all instances of -//!cached_adaptive_pool with equal sizeof(T) placed in the same -//!memory segment. But also caches some nodes privately to -//!avoid some synchronization overhead. -//! -//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when -//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks -//!that the adaptive node pool will hold. The rest of the totally free blocks will be -//!deallocated with the segment manager. -//! -//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: -//!(memory usable for nodes / total memory allocated from the segment manager) -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class cached_adaptive_pool - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_adaptive_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - , 2> - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - typedef ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_adaptive_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - , 2> base_t; - - public: - typedef boost::interprocess::version_type version; - - template - struct rebind - { - typedef cached_adaptive_pool - other; - }; - - cached_adaptive_pool(SegmentManager *segment_mngr, - std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) - : base_t(segment_mngr, max_cached_nodes) - {} - - template - cached_adaptive_pool - (const cached_adaptive_pool &other) - : base_t(other) - {} - - #else - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - //!Obtains cached_adaptive_pool from - //!cached_adaptive_pool - template - struct rebind - { - typedef cached_adaptive_pool other; - }; - - private: - //!Not assignable from - //!related cached_adaptive_pool - template - cached_adaptive_pool& operator= - (const cached_adaptive_pool&); - - //!Not assignable from - //!other cached_adaptive_pool - cached_adaptive_pool& operator=(const cached_adaptive_pool&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - cached_adaptive_pool(segment_manager *segment_mngr); - - //!Copy constructor from other cached_adaptive_pool. Increments the reference - //!count of the associated node pool. Never throws - cached_adaptive_pool(const cached_adaptive_pool &other); - - //!Copy constructor from related cached_adaptive_pool. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - cached_adaptive_pool - (const cached_adaptive_pool &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~cached_adaptive_pool(); - - //!Returns a pointer to the node pool. - //!Never throws - node_pool_t* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; - - //!Copy construct an object. - //!Throws if T's copy constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain); - //!Sets the new max cached nodes value. This can provoke deallocations - //!if "newmax" is less than current cached nodes. Never throws - void set_max_cached_nodes(size_type newmax); - - //!Returns the max cached nodes parameter. - //!Never throws - size_type get_max_cached_nodes() const; - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of cached_adaptive_pool -template inline -bool operator==(const cached_adaptive_pool &alloc1, - const cached_adaptive_pool &alloc2); - -//!Inequality test for same type -//!of cached_adaptive_pool -template inline -bool operator!=(const cached_adaptive_pool &alloc1, - const cached_adaptive_pool &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - - -#include - -#endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP - diff --git a/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp b/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp deleted file mode 100644 index 4eff061b0a3..00000000000 --- a/extern/boost/boost/interprocess/allocators/cached_node_allocator.hpp +++ /dev/null @@ -1,328 +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_CACHED_NODE_ALLOCATOR_HPP -#define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail { - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - > -class cached_node_allocator_v1 - : public ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - > - , 1> -{ - public: - typedef ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - > - , 1> base_t; - - template - struct rebind - { - typedef cached_node_allocator_v1 - other; - }; - - typedef typename base_t::size_type size_type; - - cached_node_allocator_v1(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) - : base_t(segment_mngr, max_cached_nodes) - {} - - template - cached_node_allocator_v1 - (const cached_node_allocator_v1 - &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail{ - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - > -class cached_node_allocator - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - > - , 2> - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - typedef ipcdetail::cached_allocator_impl - < T - , ipcdetail::shared_node_pool - < SegmentManager - , sizeof_value::value - , NodesPerBlock - > - , 2> base_t; - - public: - typedef boost::interprocess::version_type version; - typedef typename base_t::size_type size_type; - - template - struct rebind - { - typedef cached_node_allocator other; - }; - - cached_node_allocator(SegmentManager *segment_mngr, - size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) - : base_t(segment_mngr, max_cached_nodes) - {} - - template - cached_node_allocator - (const cached_node_allocator &other) - : base_t(other) - {} - - #else - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename SegmentManager::size_type size_type; - typedef typename SegmentManager::difference_type difference_type; - - //!Obtains cached_node_allocator from - //!cached_node_allocator - template - struct rebind - { - typedef cached_node_allocator other; - }; - - private: - //!Not assignable from - //!related cached_node_allocator - template - cached_node_allocator& operator= - (const cached_node_allocator&); - - //!Not assignable from - //!other cached_node_allocator - cached_node_allocator& operator=(const cached_node_allocator&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - cached_node_allocator(segment_manager *segment_mngr); - - //!Copy constructor from other cached_node_allocator. Increments the reference - //!count of the associated node pool. Never throws - cached_node_allocator(const cached_node_allocator &other); - - //!Copy constructor from related cached_node_allocator. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - cached_node_allocator - (const cached_node_allocator &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~cached_node_allocator(); - - //!Returns a pointer to the node pool. - //!Never throws - node_pool_t* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; - - //!Default construct an object. - //!Throws if T's default constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - multiallocation_chain allocate_individual(size_type num_elements); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain it); - //!Sets the new max cached nodes value. This can provoke deallocations - //!if "newmax" is less than current cached nodes. Never throws - void set_max_cached_nodes(size_type newmax); - - //!Returns the max cached nodes parameter. - //!Never throws - size_type get_max_cached_nodes() const; - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of cached_node_allocator -template inline -bool operator==(const cached_node_allocator &alloc1, - const cached_node_allocator &alloc2); - -//!Inequality test for same type -//!of cached_node_allocator -template inline -bool operator!=(const cached_node_allocator &alloc1, - const cached_node_allocator &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP - diff --git a/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp deleted file mode 100644 index e9a8e2655cf..00000000000 --- a/extern/boost/boost/interprocess/allocators/detail/adaptive_node_pool.hpp +++ /dev/null @@ -1,115 +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_ADAPTIVE_NODE_POOL_HPP -#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes the real adaptive pool shared by many Interprocess pool allocators - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template< class SegmentManager - , std::size_t NodeSize - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class private_adaptive_node_pool - : public boost::container::dtl::private_adaptive_node_pool_impl_rt - < typename SegmentManager::segment_manager_base_type - , ::boost::container::adaptive_pool_flag::size_ordered | - ::boost::container::adaptive_pool_flag::address_ordered - > -{ - typedef boost::container::dtl::private_adaptive_node_pool_impl_rt - < typename SegmentManager::segment_manager_base_type - , ::boost::container::adaptive_pool_flag::size_ordered | - ::boost::container::adaptive_pool_flag::address_ordered - > base_t; - //Non-copyable - private_adaptive_node_pool(); - private_adaptive_node_pool(const private_adaptive_node_pool &); - private_adaptive_node_pool &operator=(const private_adaptive_node_pool &); - - public: - typedef SegmentManager segment_manager; - typedef typename base_t::size_type size_type; - - static const size_type nodes_per_block = NodesPerBlock; - - //!Constructor from a segment manager. Never throws - private_adaptive_node_pool(segment_manager *segment_mngr) - : base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent) - {} - - //!Returns the segment manager. Never throws - segment_manager* get_segment_manager() const - { return static_cast(base_t::get_segment_manager_base()); } -}; - -//!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is -//!responsibility of user classes. Node size (NodeSize) and the number of -//!nodes allocated per block (NodesPerBlock) are known at compile time -template< class SegmentManager - , std::size_t NodeSize - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class shared_adaptive_node_pool - : public ipcdetail::shared_pool_impl - < private_adaptive_node_pool - - > -{ - typedef ipcdetail::shared_pool_impl - < private_adaptive_node_pool - - > base_t; - public: - shared_adaptive_node_pool(SegmentManager *segment_mgnr) - : base_t(segment_mgnr) - {} -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp b/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp deleted file mode 100644 index bb301ebfbb8..00000000000 --- a/extern/boost/boost/interprocess/allocators/detail/allocator_common.hpp +++ /dev/null @@ -1,857 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP -#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include //to_raw_pointer -#include //boost::addressof -#include //BOOST_ASSERT -#include //bad_alloc -#include //scoped_lock -#include //boost::interprocess::allocation_type -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { - -template -struct sizeof_value -{ - static const std::size_t value = sizeof(T); -}; - -template <> -struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; - -template <> -struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; - -template <> -struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; - -template <> -struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; - -namespace ipcdetail { - -//!Object function that creates the node allocator if it is not created and -//!increments reference count if it is already created -template -struct get_or_create_node_pool_func -{ - - //!This connects or constructs the unique instance of node_pool_t - //!Can throw boost::interprocess::bad_alloc - void operator()() - { - //Find or create the node_pool_t - mp_node_pool = mp_segment_manager->template find_or_construct - (boost::interprocess::unique_instance)(mp_segment_manager); - //If valid, increment link count - if(mp_node_pool != 0) - mp_node_pool->inc_ref_count(); - } - - //!Constructor. Initializes function - //!object parameters - get_or_create_node_pool_func(typename NodePool::segment_manager *mngr) - : mp_segment_manager(mngr){} - - NodePool *mp_node_pool; - typename NodePool::segment_manager *mp_segment_manager; -}; - -template -inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr) -{ - ipcdetail::get_or_create_node_pool_func func(mgnr); - mgnr->atomic_func(func); - return func.mp_node_pool; -} - -//!Object function that decrements the reference count. If the count -//!reaches to zero destroys the node allocator from memory. -//!Never throws -template -struct destroy_if_last_link_func -{ - //!Decrements reference count and destroys the object if there is no - //!more attached allocators. Never throws - void operator()() - { - //If not the last link return - if(mp_node_pool->dec_ref_count() != 0) return; - - //Last link, let's destroy the segment_manager - mp_node_pool->get_segment_manager()->template destroy(boost::interprocess::unique_instance); - } - - //!Constructor. Initializes function - //!object parameters - destroy_if_last_link_func(NodePool *pool) - : mp_node_pool(pool) - {} - - NodePool *mp_node_pool; -}; - -//!Destruction function, initializes and executes destruction function -//!object. Never throws -template -inline void destroy_node_pool_if_last_link(NodePool *pool) -{ - //Get segment manager - typename NodePool::segment_manager *mngr = pool->get_segment_manager(); - //Execute destruction functor atomically - destroy_if_last_link_funcfunc(pool); - mngr->atomic_func(func); -} - -template -class cache_impl -{ - typedef typename NodePool::segment_manager:: - void_pointer void_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type node_pool_ptr; - typedef typename NodePool::multiallocation_chain multiallocation_chain; - typedef typename NodePool::segment_manager::size_type size_type; - node_pool_ptr mp_node_pool; - multiallocation_chain m_cached_nodes; - size_type m_max_cached_nodes; - - public: - typedef typename NodePool::segment_manager segment_manager; - - cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes) - : mp_node_pool(get_or_create_node_pool(segment_mngr)) - , m_max_cached_nodes(max_cached_nodes) - {} - - cache_impl(const cache_impl &other) - : mp_node_pool(other.get_node_pool()) - , m_max_cached_nodes(other.get_max_cached_nodes()) - { - mp_node_pool->inc_ref_count(); - } - - ~cache_impl() - { - this->deallocate_all_cached_nodes(); - ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); - } - - NodePool *get_node_pool() const - { return ipcdetail::to_raw_pointer(mp_node_pool); } - - segment_manager *get_segment_manager() const - { return mp_node_pool->get_segment_manager(); } - - size_type get_max_cached_nodes() const - { return m_max_cached_nodes; } - - void *cached_allocation() - { - //If don't have any cached node, we have to get a new list of free nodes from the pool - if(m_cached_nodes.empty()){ - mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes); - } - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); - return ret; - } - - void cached_allocation(size_type n, multiallocation_chain &chain) - { - size_type count = n, allocated(0); - BOOST_TRY{ - //If don't have any cached node, we have to get a new list of free nodes from the pool - while(!m_cached_nodes.empty() && count--){ - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); - chain.push_back(ret); - ++allocated; - } - - if(allocated != n){ - mp_node_pool->allocate_nodes(n - allocated, chain); - } - } - BOOST_CATCH(...){ - this->cached_deallocation(chain); - BOOST_RETHROW - } BOOST_CATCH_END - } - - void cached_deallocation(void *ptr) - { - //Check if cache is full - if(m_cached_nodes.size() >= m_max_cached_nodes){ - //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more - //deallocations are probably coming, we'll make some room in cache - //in a single, efficient multi node deallocation. - this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); - } - m_cached_nodes.push_front(ptr); - } - - void cached_deallocation(multiallocation_chain &chain) - { - m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain); - - //Check if cache is full - if(m_cached_nodes.size() >= m_max_cached_nodes){ - //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more - //deallocations are probably coming, we'll make some room in cache - //in a single, efficient multi node deallocation. - this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); - } - } - - //!Sets the new max cached nodes value. This can provoke deallocations - //!if "newmax" is less than current cached nodes. Never throws - void set_max_cached_nodes(size_type newmax) - { - m_max_cached_nodes = newmax; - this->priv_deallocate_remaining_nodes(); - } - - //!Frees all cached nodes. - //!Never throws - void deallocate_all_cached_nodes() - { - if(m_cached_nodes.empty()) return; - mp_node_pool->deallocate_nodes(m_cached_nodes); - } - - private: - //!Frees all cached nodes at once. - //!Never throws - void priv_deallocate_remaining_nodes() - { - if(m_cached_nodes.size() > m_max_cached_nodes){ - priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes); - } - } - - //!Frees n cached nodes at once. Never throws - void priv_deallocate_n_nodes(size_type n) - { - //This only occurs if this allocator deallocate memory allocated - //with other equal allocator. Since the cache is full, and more - //deallocations are probably coming, we'll make some room in cache - //in a single, efficient multi node deallocation. - size_type count(n); - typename multiallocation_chain::iterator it(m_cached_nodes.before_begin()); - while(count--){ - ++it; - } - multiallocation_chain chain; - chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n); - //Deallocate all new linked list at once - mp_node_pool->deallocate_nodes(chain); - } - - public: - void swap(cache_impl &other) - { - ::boost::adl_move_swap(mp_node_pool, other.mp_node_pool); - ::boost::adl_move_swap(m_cached_nodes, other.m_cached_nodes); - ::boost::adl_move_swap(m_max_cached_nodes, other.m_max_cached_nodes); - } -}; - -template -class array_allocation_impl -{ - const Derived *derived() const - { return static_cast(this); } - Derived *derived() - { return static_cast(this); } - - typedef typename SegmentManager::void_pointer void_pointer; - - public: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename SegmentManager::size_type size_type; - typedef typename SegmentManager::difference_type difference_type; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - - public: - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const - { - return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T); - } - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) - { - value_type *reuse_raw = ipcdetail::to_raw_pointer(reuse); - pointer const p = this->derived()->get_segment_manager()->allocation_command - (command, limit_size, prefer_in_recvd_out_size, reuse_raw); - reuse = reuse_raw; - return p; - } - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain) - { - if(size_overflows(elem_size)){ - throw bad_alloc(); - } - this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain); - } - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain) - { - this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain); - } - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain) - { this->derived()->get_segment_manager()->deallocate_many(chain); } - - //!Returns the number of elements that could be - //!allocated. Never throws - size_type max_size() const - { return this->derived()->get_segment_manager()->get_size()/sizeof(T); } - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const - { return pointer(boost::addressof(value)); } - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const - { return const_pointer(boost::addressof(value)); } - - //!Constructs an object - //!Throws if T's constructor throws - //!For backwards compatibility with libraries using C++03 allocators - template - void construct(const pointer &ptr, BOOST_FWD_REF(P) p) - { ::new((void*)ipcdetail::to_raw_pointer(ptr), boost_container_new_t()) value_type(::boost::forward

(p)); } - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr) - { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } -}; - - -template -class node_pool_allocation_impl - : public array_allocation_impl - < Derived - , T - , SegmentManager> -{ - const Derived *derived() const - { return static_cast(this); } - Derived *derived() - { return static_cast(this); } - - typedef typename SegmentManager::void_pointer void_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type cvoid_pointer; - - public: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename SegmentManager::size_type size_type; - typedef typename SegmentManager::difference_type difference_type; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - - template - struct node_pool - { - typedef typename Derived::template node_pool<0>::type type; - static type *get(void *p) - { return static_cast(p); } - }; - - public: - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0) - { - (void)hint; - typedef typename node_pool<0>::type node_pool_t; - node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - if(size_overflows(count)){ - throw bad_alloc(); - } - else if(Version == 1 && count == 1){ - return pointer(static_cast - (pool->allocate_node())); - } - else{ - return pointer(static_cast - (pool->get_segment_manager()->allocate(count*sizeof(T)))); - } - } - - //!Deallocate allocated memory. Never throws - void deallocate(const pointer &ptr, size_type count) - { - (void)count; - typedef typename node_pool<0>::type node_pool_t; - node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - if(Version == 1 && count == 1) - pool->deallocate_node(ipcdetail::to_raw_pointer(ptr)); - else - pool->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); - } - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one() - { - typedef typename node_pool<0>::type node_pool_t; - node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - return pointer(static_cast(pool->allocate_node())); - } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain) - { - typedef typename node_pool<0>::type node_pool_t; - node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - pool->allocate_nodes(num_elements, chain); - } - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p) - { - typedef typename node_pool<0>::type node_pool_t; - node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - pool->deallocate_node(ipcdetail::to_raw_pointer(p)); - } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain) - { - node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes - (chain); - } - - //!Deallocates all free blocks of the pool - void deallocate_free_blocks() - { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } - - //!Deprecated, use deallocate_free_blocks. - //!Deallocates all free chunks of the pool. - void deallocate_free_chunks() - { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } -}; - -template -class cached_allocator_impl - : public array_allocation_impl - , T, typename NodePool::segment_manager> -{ - cached_allocator_impl & operator=(const cached_allocator_impl& other); - typedef array_allocation_impl - < cached_allocator_impl - - , T - , typename NodePool::segment_manager> base_t; - - public: - typedef NodePool node_pool_t; - typedef typename NodePool::segment_manager segment_manager; - typedef typename segment_manager::void_pointer void_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type cvoid_pointer; - typedef typename base_t::pointer pointer; - typedef typename base_t::size_type size_type; - typedef typename base_t::multiallocation_chain multiallocation_chain; - typedef typename base_t::value_type value_type; - - public: - static const std::size_t DEFAULT_MAX_CACHED_NODES = 64; - - cached_allocator_impl(segment_manager *segment_mngr, size_type max_cached_nodes) - : m_cache(segment_mngr, max_cached_nodes) - {} - - cached_allocator_impl(const cached_allocator_impl &other) - : m_cache(other.m_cache) - {} - - //!Copy constructor from related cached_adaptive_pool_base. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - cached_allocator_impl - (const cached_allocator_impl - &other) - : m_cache(other.get_segment_manager(), other.get_max_cached_nodes()) - {} - - //!Returns a pointer to the node pool. - //!Never throws - node_pool_t* get_node_pool() const - { return m_cache.get_node_pool(); } - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const - { return m_cache.get_segment_manager(); } - - //!Sets the new max cached nodes value. This can provoke deallocations - //!if "newmax" is less than current cached nodes. Never throws - void set_max_cached_nodes(size_type newmax) - { m_cache.set_max_cached_nodes(newmax); } - - //!Returns the max cached nodes parameter. - //!Never throws - size_type get_max_cached_nodes() const - { return m_cache.get_max_cached_nodes(); } - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0) - { - (void)hint; - void * ret; - if(size_overflows(count)){ - throw bad_alloc(); - } - else if(Version == 1 && count == 1){ - ret = m_cache.cached_allocation(); - } - else{ - ret = this->get_segment_manager()->allocate(count*sizeof(T)); - } - return pointer(static_cast(ret)); - } - - //!Deallocate allocated memory. Never throws - void deallocate(const pointer &ptr, size_type count) - { - (void)count; - if(Version == 1 && count == 1){ - m_cache.cached_deallocation(ipcdetail::to_raw_pointer(ptr)); - } - else{ - this->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); - } - } - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one() - { return pointer(static_cast(this->m_cache.cached_allocation())); } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain) - { this->m_cache.cached_allocation(num_elements, chain); } - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p) - { this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); } - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain) - { m_cache.cached_deallocation(chain); } - - //!Deallocates all free blocks of the pool - void deallocate_free_blocks() - { m_cache.get_node_pool()->deallocate_free_blocks(); } - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different shared memory segments, the result is undefined. - friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2) - { ::boost::adl_move_swap(alloc1.m_cache, alloc2.m_cache); } - - void deallocate_cache() - { m_cache.deallocate_all_cached_nodes(); } - - //!Deprecated use deallocate_free_blocks. - void deallocate_free_chunks() - { m_cache.get_node_pool()->deallocate_free_blocks(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - cache_impl m_cache; - #endif //!defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -}; - -//!Equality test for same type of -//!cached_allocator_impl -template inline -bool operator==(const cached_allocator_impl &alloc1, - const cached_allocator_impl &alloc2) - { return alloc1.get_node_pool() == alloc2.get_node_pool(); } - -//!Inequality test for same type of -//!cached_allocator_impl -template inline -bool operator!=(const cached_allocator_impl &alloc1, - const cached_allocator_impl &alloc2) - { return alloc1.get_node_pool() != alloc2.get_node_pool(); } - - -//!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is -//!responsibility of user classes. Node size (NodeSize) and the number of -//!nodes allocated per block (NodesPerBlock) are known at compile time -template -class shared_pool_impl - : public private_node_allocator_t -{ - public: - //!Segment manager typedef - typedef typename private_node_allocator_t:: - segment_manager segment_manager; - typedef typename private_node_allocator_t:: - multiallocation_chain multiallocation_chain; - typedef typename private_node_allocator_t:: - size_type size_type; - - private: - typedef typename segment_manager::mutex_family::mutex_type mutex_type; - - public: - //!Constructor from a segment manager. Never throws - shared_pool_impl(segment_manager *segment_mngr) - : private_node_allocator_t(segment_mngr) - {} - - //!Destructor. Deallocates all allocated blocks. Never throws - ~shared_pool_impl() - {} - - //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc - void *allocate_node() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return private_node_allocator_t::allocate_node(); - } - - //!Deallocates an array pointed by ptr. Never throws - void deallocate_node(void *ptr) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::deallocate_node(ptr); - } - - //!Allocates n nodes. - //!Can throw boost::interprocess::bad_alloc - void allocate_nodes(const size_type n, multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::allocate_nodes(n, chain); - } - - //!Deallocates a linked list of nodes ending in null pointer. Never throws - void deallocate_nodes(multiallocation_chain &nodes, size_type num) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::deallocate_nodes(nodes, num); - } - - //!Deallocates the nodes pointed by the multiallocation iterator. Never throws - void deallocate_nodes(multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::deallocate_nodes(chain); - } - - //!Deallocates all the free blocks of memory. Never throws - void deallocate_free_blocks() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::deallocate_free_blocks(); - } - - //!Deallocates all used memory from the common pool. - //!Precondition: all nodes allocated from this pool should - //!already be deallocated. Otherwise, undefined behavior. Never throws - void purge_blocks() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::purge_blocks(); - } - - //!Increments internal reference count and returns new count. Never throws - size_type inc_ref_count() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return ++m_header.m_usecount; - } - - //!Decrements internal reference count and returns new count. Never throws - size_type dec_ref_count() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - BOOST_ASSERT(m_header.m_usecount > 0); - return --m_header.m_usecount; - } - - //!Deprecated, use deallocate_free_blocks. - void deallocate_free_chunks() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::deallocate_free_blocks(); - } - - //!Deprecated, use purge_blocks. - void purge_chunks() - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - private_node_allocator_t::purge_blocks(); - } - - private: - //!This struct includes needed data and derives from - //!the mutex type to allow EBO when using null_mutex - struct header_t : mutex_type - { - size_type m_usecount; //Number of attached allocators - - header_t() - : m_usecount(0) {} - } m_header; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp b/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp deleted file mode 100644 index 552410ad597..00000000000 --- a/extern/boost/boost/interprocess/allocators/detail/node_pool.hpp +++ /dev/null @@ -1,111 +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_NODE_POOL_HPP -#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include - - -//!\file -//!Describes the real adaptive pool shared by many Interprocess adaptive pool allocators - -namespace boost { -namespace interprocess { -namespace ipcdetail { - - - -//!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is -//!responsibility of user classes. Node size (NodeSize) and the number of -//!nodes allocated per block (NodesPerBlock) are known at compile time -template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > -class private_node_pool - //Inherit from the implementation to avoid template bloat - : public boost::container::dtl:: - private_node_pool_impl -{ - typedef boost::container::dtl::private_node_pool_impl - base_t; - //Non-copyable - private_node_pool(); - private_node_pool(const private_node_pool &); - private_node_pool &operator=(const private_node_pool &); - - public: - typedef SegmentManager segment_manager; - typedef typename base_t::size_type size_type; - - static const size_type nodes_per_block = NodesPerBlock; - //Deprecated, use nodes_per_block - static const size_type nodes_per_chunk = NodesPerBlock; - - //!Constructor from a segment manager. Never throws - private_node_pool(segment_manager *segment_mngr) - : base_t(segment_mngr, NodeSize, NodesPerBlock) - {} - - //!Returns the segment manager. Never throws - segment_manager* get_segment_manager() const - { return static_cast(base_t::get_segment_manager_base()); } -}; - - -//!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is -//!responsibility of user classes. Node size (NodeSize) and the number of -//!nodes allocated per block (NodesPerBlock) are known at compile time -//!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is -//!responsibility of user classes. Node size (NodeSize) and the number of -//!nodes allocated per block (NodesPerBlock) are known at compile time -template< class SegmentManager - , std::size_t NodeSize - , std::size_t NodesPerBlock - > -class shared_node_pool - : public ipcdetail::shared_pool_impl - < private_node_pool - - > -{ - typedef ipcdetail::shared_pool_impl - < private_node_pool - - > base_t; - public: - shared_node_pool(SegmentManager *segment_mgnr) - : base_t(segment_mgnr) - {} -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP diff --git a/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp b/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp deleted file mode 100644 index 7f5a4f515c5..00000000000 --- a/extern/boost/boost/interprocess/allocators/detail/node_tools.hpp +++ /dev/null @@ -1,54 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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_NODE_TOOLS_HPP -#define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - - -template -struct node_slist -{ - //This hook will be used to chain the individual nodes - typedef typename bi::make_slist_base_hook - , bi::link_mode >::type slist_hook_t; - - //A node object will hold node_t when it's not allocated - struct node_t - : public slist_hook_t - {}; - - typedef typename bi::make_slist - , bi::base_hook >::type node_slist_t; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP diff --git a/extern/boost/boost/interprocess/allocators/node_allocator.hpp b/extern/boost/boost/interprocess/allocators/node_allocator.hpp deleted file mode 100644 index 34af80c711e..00000000000 --- a/extern/boost/boost/interprocess/allocators/node_allocator.hpp +++ /dev/null @@ -1,454 +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_NODE_ALLOCATOR_HPP -#define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes node_allocator pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail{ - -template < unsigned int Version - , class T - , class SegmentManager - , std::size_t NodesPerBlock - > -class node_allocator_base - : public node_pool_allocation_impl - < node_allocator_base - < Version, T, SegmentManager, NodesPerBlock> - , Version - , T - , SegmentManager - > -{ - public: - typedef typename SegmentManager::void_pointer void_pointer; - typedef SegmentManager segment_manager; - typedef node_allocator_base - self_t; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - template - struct node_pool - { - typedef ipcdetail::shared_node_pool - < SegmentManager, sizeof_value::value, NodesPerBlock> type; - - static type *get(void *p) - { return static_cast(p); } - }; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - BOOST_STATIC_ASSERT((Version <=2)); - - public: - //------- - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - typedef boost::interprocess::version_type version; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - //!Obtains node_allocator_base from - //!node_allocator_base - template - struct rebind - { - typedef node_allocator_base other; - }; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - //!Not assignable from related node_allocator_base - template - node_allocator_base& operator= - (const node_allocator_base&); - - //!Not assignable from other node_allocator_base - //node_allocator_base& operator=(const node_allocator_base&); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - node_allocator_base(segment_manager *segment_mngr) - : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(segment_mngr)) { } - - //!Copy constructor from other node_allocator_base. Increments the reference - //!count of the associated node pool. Never throws - node_allocator_base(const node_allocator_base &other) - : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); - } - - //!Copy constructor from related node_allocator_base. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - node_allocator_base - (const node_allocator_base &other) - : mp_node_pool(ipcdetail::get_or_create_node_pool::type>(other.get_segment_manager())) { } - - //!Assignment from other node_allocator_base - node_allocator_base& operator=(const node_allocator_base &other) - { - node_allocator_base c(other); - boost::adl_move_swap(*this, c); - return *this; - } - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~node_allocator_base() - { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); } - - //!Returns a pointer to the node pool. - //!Never throws - void* get_node_pool() const - { return ipcdetail::to_raw_pointer(mp_node_pool); } - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const - { return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); } - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2) - { boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - void_pointer mp_node_pool; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Equality test for same type -//!of node_allocator_base -template inline -bool operator==(const node_allocator_base &alloc1, - const node_allocator_base &alloc2) - { return alloc1.get_node_pool() == alloc2.get_node_pool(); } - -//!Inequality test for same type -//!of node_allocator_base -template inline -bool operator!=(const node_allocator_base &alloc1, - const node_allocator_base &alloc2) - { return alloc1.get_node_pool() != alloc2.get_node_pool(); } - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - > -class node_allocator_v1 - : public node_allocator_base - < 1 - , T - , SegmentManager - , NodesPerBlock - > -{ - public: - typedef ipcdetail::node_allocator_base - < 1, T, SegmentManager, NodesPerBlock> base_t; - - template - struct rebind - { - typedef node_allocator_v1 other; - }; - - node_allocator_v1(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - node_allocator_v1 - (const node_allocator_v1 &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail{ - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!An STL node allocator that uses a segment manager as memory -//!source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -//!This node allocator shares a segregated storage between all instances -//!of node_allocator with equal sizeof(T) placed in the same segment -//!group. NodesPerBlock is the number of nodes allocated at once when the allocator -//!runs out of nodes -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - > -class node_allocator - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::node_allocator_base - < 2 - , T - , SegmentManager - , NodesPerBlock - > - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef ipcdetail::node_allocator_base - < 2, T, SegmentManager, NodesPerBlock> base_t; - public: - typedef boost::interprocess::version_type version; - - template - struct rebind - { - typedef node_allocator other; - }; - - node_allocator(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - node_allocator - (const node_allocator &other) - : base_t(other) - {} - - #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - //!Obtains node_allocator from - //!node_allocator - template - struct rebind - { - typedef node_allocator other; - }; - - private: - //!Not assignable from - //!related node_allocator - template - node_allocator& operator= - (const node_allocator&); - - //!Not assignable from - //!other node_allocator - //node_allocator& operator=(const node_allocator&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - node_allocator(segment_manager *segment_mngr); - - //!Copy constructor from other node_allocator. Increments the reference - //!count of the associated node pool. Never throws - node_allocator(const node_allocator &other); - - //!Copy constructor from related node_allocator. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - node_allocator - (const node_allocator &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~node_allocator(); - - //!Returns a pointer to the node pool. - //!Never throws - void* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; - - //!Copy construct an object. - //!Throws if T's copy constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain); - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of node_allocator -template inline -bool operator==(const node_allocator &alloc1, - const node_allocator &alloc2); - -//!Inequality test for same type -//!of node_allocator -template inline -bool operator!=(const node_allocator &alloc1, - const node_allocator &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP diff --git a/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp b/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp deleted file mode 100644 index a6da71e58ab..00000000000 --- a/extern/boost/boost/interprocess/allocators/private_adaptive_pool.hpp +++ /dev/null @@ -1,470 +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_PRIVATE_ADAPTIVE_POOL_HPP -#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail { - -template < unsigned int Version - , class T - , class SegmentManager - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class private_adaptive_pool_base - : public node_pool_allocation_impl - < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock - , MaxFreeBlocks, OverheadPercent> - , Version - , T - , SegmentManager - > -{ - public: - //Segment manager - typedef SegmentManager segment_manager; - typedef typename SegmentManager::void_pointer void_pointer; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef private_adaptive_pool_base - < Version, T, SegmentManager, NodesPerBlock - , MaxFreeBlocks, OverheadPercent> self_t; - typedef ipcdetail::private_adaptive_node_pool - ::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > node_pool_t; - - BOOST_STATIC_ASSERT((Version <=2)); - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - typedef boost::interprocess::version_type - version; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - //!Obtains node_allocator from other node_allocator - template - struct rebind - { - typedef private_adaptive_pool_base - other; - }; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - template - struct node_pool - { - typedef ipcdetail::private_adaptive_node_pool - ::value - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > type; - - static type *get(void *p) - { return static_cast(p); } - }; - - private: - //!Not assignable from related private_adaptive_pool_base - template - private_adaptive_pool_base& operator= - (const private_adaptive_pool_base&); - - //!Not assignable from other private_adaptive_pool_base - private_adaptive_pool_base& operator=(const private_adaptive_pool_base&); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor from a segment manager - private_adaptive_pool_base(segment_manager *segment_mngr) - : m_node_pool(segment_mngr) - {} - - //!Copy constructor from other private_adaptive_pool_base. Never throws - private_adaptive_pool_base(const private_adaptive_pool_base &other) - : m_node_pool(other.get_segment_manager()) - {} - - //!Copy constructor from related private_adaptive_pool_base. Never throws. - template - private_adaptive_pool_base - (const private_adaptive_pool_base - &other) - : m_node_pool(other.get_segment_manager()) - {} - - //!Destructor, frees all used memory. Never throws - ~private_adaptive_pool_base() - {} - - //!Returns the segment manager. Never throws - segment_manager* get_segment_manager()const - { return m_node_pool.get_segment_manager(); } - - //!Returns the internal node pool. Never throws - node_pool_t* get_node_pool() const - { return const_cast(&m_node_pool); } - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different shared memory segments, the result is undefined. - friend void swap(self_t &alloc1,self_t &alloc2) - { boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - node_pool_t m_node_pool; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Equality test for same type of private_adaptive_pool_base -template inline -bool operator==(const private_adaptive_pool_base &alloc1, - const private_adaptive_pool_base &alloc2) -{ return &alloc1 == &alloc2; } - -//!Inequality test for same type of private_adaptive_pool_base -template inline -bool operator!=(const private_adaptive_pool_base &alloc1, - const private_adaptive_pool_base &alloc2) -{ return &alloc1 != &alloc2; } - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - , std::size_t MaxFreeBlocks = 2 - , unsigned char OverheadPercent = 5 - > -class private_adaptive_pool_v1 - : public private_adaptive_pool_base - < 1 - , T - , SegmentManager - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > -{ - public: - typedef ipcdetail::private_adaptive_pool_base - < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; - - template - struct rebind - { - typedef private_adaptive_pool_v1 other; - }; - - private_adaptive_pool_v1(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - private_adaptive_pool_v1 - (const private_adaptive_pool_v1 &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail { - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!An STL node allocator that uses a segment manager as memory -//!source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -//!This allocator has its own node pool. -//! -//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when -//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks -//!that the adaptive node pool will hold. The rest of the totally free blocks will be -//!deallocated with the segment manager. -//! -//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: -//!(memory usable for nodes / total memory allocated from the segment manager) -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - , std::size_t MaxFreeBlocks - , unsigned char OverheadPercent - > -class private_adaptive_pool - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::private_adaptive_pool_base - < 2 - , T - , SegmentManager - , NodesPerBlock - , MaxFreeBlocks - , OverheadPercent - > - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef ipcdetail::private_adaptive_pool_base - < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; - public: - typedef boost::interprocess::version_type version; - - template - struct rebind - { - typedef private_adaptive_pool - other; - }; - - private_adaptive_pool(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - private_adaptive_pool - (const private_adaptive_pool &other) - : base_t(other) - {} - - #else - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - - //!Obtains private_adaptive_pool from - //!private_adaptive_pool - template - struct rebind - { - typedef private_adaptive_pool - other; - }; - - private: - //!Not assignable from - //!related private_adaptive_pool - template - private_adaptive_pool& operator= - (const private_adaptive_pool&); - - //!Not assignable from - //!other private_adaptive_pool - private_adaptive_pool& operator=(const private_adaptive_pool&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - private_adaptive_pool(segment_manager *segment_mngr); - - //!Copy constructor from other private_adaptive_pool. Increments the reference - //!count of the associated node pool. Never throws - private_adaptive_pool(const private_adaptive_pool &other); - - //!Copy constructor from related private_adaptive_pool. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - private_adaptive_pool - (const private_adaptive_pool &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~private_adaptive_pool(); - - //!Returns a pointer to the node pool. - //!Never throws - node_pool_t* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; - - //!Copy construct an object. - //!Throws if T's copy constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain); - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of private_adaptive_pool -template inline -bool operator==(const private_adaptive_pool &alloc1, - const private_adaptive_pool &alloc2); - -//!Inequality test for same type -//!of private_adaptive_pool -template inline -bool operator!=(const private_adaptive_pool &alloc1, - const private_adaptive_pool &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP - diff --git a/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp b/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp deleted file mode 100644 index 703e0d74e52..00000000000 --- a/extern/boost/boost/interprocess/allocators/private_node_allocator.hpp +++ /dev/null @@ -1,447 +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_PRIVATE_NODE_ALLOCATOR_HPP -#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes private_node_allocator_base pooled shared memory STL compatible allocator - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail { - -template < unsigned int Version - , class T - , class SegmentManager - , std::size_t NodesPerBlock - > -class private_node_allocator_base - : public node_pool_allocation_impl - < private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock> - , Version - , T - , SegmentManager - > -{ - public: - //Segment manager - typedef SegmentManager segment_manager; - typedef typename SegmentManager::void_pointer void_pointer; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef private_node_allocator_base - < Version, T, SegmentManager, NodesPerBlock> self_t; - typedef ipcdetail::private_node_pool - ::value - , NodesPerBlock - > node_pool_t; - - BOOST_STATIC_ASSERT((Version <=2)); - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manager::difference_type difference_type; - typedef boost::interprocess::version_type - version; - typedef boost::container::dtl::transform_multiallocation_chain - multiallocation_chain; - - //!Obtains node_allocator from other node_allocator - template - struct rebind - { - typedef private_node_allocator_base - other; - }; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - template - struct node_pool - { - typedef ipcdetail::private_node_pool - ::value - , NodesPerBlock - > type; - - static type *get(void *p) - { return static_cast(p); } - }; - - private: - //!Not assignable from related private_node_allocator_base - template - private_node_allocator_base& operator= - (const private_node_allocator_base&); - - //!Not assignable from other private_node_allocator_base - private_node_allocator_base& operator=(const private_node_allocator_base&); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor from a segment manager - private_node_allocator_base(segment_manager *segment_mngr) - : m_node_pool(segment_mngr) - {} - - //!Copy constructor from other private_node_allocator_base. Never throws - private_node_allocator_base(const private_node_allocator_base &other) - : m_node_pool(other.get_segment_manager()) - {} - - //!Copy constructor from related private_node_allocator_base. Never throws. - template - private_node_allocator_base - (const private_node_allocator_base - &other) - : m_node_pool(other.get_segment_manager()) - {} - - //!Destructor, frees all used memory. Never throws - ~private_node_allocator_base() - {} - - //!Returns the segment manager. Never throws - segment_manager* get_segment_manager()const - { return m_node_pool.get_segment_manager(); } - - //!Returns the internal node pool. Never throws - node_pool_t* get_node_pool() const - { return const_cast(&m_node_pool); } - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different shared memory segments, the result is undefined. - friend void swap(self_t &alloc1,self_t &alloc2) - { boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - node_pool_t m_node_pool; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Equality test for same type of private_node_allocator_base -template inline -bool operator==(const private_node_allocator_base &alloc1, - const private_node_allocator_base &alloc2) -{ return &alloc1 == &alloc2; } - -//!Inequality test for same type of private_node_allocator_base -template inline -bool operator!=(const private_node_allocator_base &alloc1, - const private_node_allocator_base &alloc2) -{ return &alloc1 != &alloc2; } - -template < class T - , class SegmentManager - , std::size_t NodesPerBlock = 64 - > -class private_node_allocator_v1 - : public private_node_allocator_base - < 1 - , T - , SegmentManager - , NodesPerBlock - > -{ - public: - typedef ipcdetail::private_node_allocator_base - < 1, T, SegmentManager, NodesPerBlock> base_t; - - template - struct rebind - { - typedef private_node_allocator_v1 other; - }; - - private_node_allocator_v1(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - private_node_allocator_v1 - (const private_node_allocator_v1 &other) - : base_t(other) - {} -}; - -} //namespace ipcdetail { - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!An STL node allocator that uses a segment manager as memory -//!source. The internal pointer type will of the same type (raw, smart) as -//!"typename SegmentManager::void_pointer" type. This allows -//!placing the allocator in shared memory, memory mapped-files, etc... -//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated -//!at once when the allocator needs runs out of nodes -template < class T - , class SegmentManager - , std::size_t NodesPerBlock - > -class private_node_allocator - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::private_node_allocator_base - < 2 - , T - , SegmentManager - , NodesPerBlock - > - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef ipcdetail::private_node_allocator_base - < 2, T, SegmentManager, NodesPerBlock> base_t; - public: - typedef boost::interprocess::version_type version; - - template - struct rebind - { - typedef private_node_allocator - other; - }; - - private_node_allocator(SegmentManager *segment_mngr) - : base_t(segment_mngr) - {} - - template - private_node_allocator - (const private_node_allocator &other) - : base_t(other) - {} - - #else - public: - typedef implementation_defined::segment_manager segment_manager; - typedef segment_manager::void_pointer void_pointer; - typedef implementation_defined::pointer pointer; - typedef implementation_defined::const_pointer const_pointer; - typedef T value_type; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename segment_manager::size_type size_type; - typedef typename segment_manage::difference_type difference_type; - - //!Obtains private_node_allocator from - //!private_node_allocator - template - struct rebind - { - typedef private_node_allocator - other; - }; - - private: - //!Not assignable from - //!related private_node_allocator - template - private_node_allocator& operator= - (const private_node_allocator&); - - //!Not assignable from - //!other private_node_allocator - private_node_allocator& operator=(const private_node_allocator&); - - public: - //!Constructor from a segment manager. If not present, constructs a node - //!pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - private_node_allocator(segment_manager *segment_mngr); - - //!Copy constructor from other private_node_allocator. Increments the reference - //!count of the associated node pool. Never throws - private_node_allocator(const private_node_allocator &other); - - //!Copy constructor from related private_node_allocator. If not present, constructs - //!a node pool. Increments the reference count of the associated node pool. - //!Can throw boost::interprocess::bad_alloc - template - private_node_allocator - (const private_node_allocator &other); - - //!Destructor, removes node_pool_t from memory - //!if its reference count reaches to zero. Never throws - ~private_node_allocator(); - - //!Returns a pointer to the node pool. - //!Never throws - node_pool_t* get_node_pool() const; - - //!Returns the segment manager. - //!Never throws - segment_manager* get_segment_manager()const; - - //!Returns the number of elements that could be allocated. - //!Never throws - size_type max_size() const; - - //!Allocate memory for an array of count elements. - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate(size_type count, cvoid_pointer hint = 0); - - //!Deallocate allocated memory. - //!Never throws - void deallocate(const pointer &ptr, size_type count); - - //!Deallocates all free blocks - //!of the pool - void deallocate_free_blocks(); - - //!Swaps allocators. Does not throw. If each allocator is placed in a - //!different memory segment, the result is undefined. - friend void swap(self_t &alloc1, self_t &alloc2); - - //!Returns address of mutable object. - //!Never throws - pointer address(reference value) const; - - //!Returns address of non mutable object. - //!Never throws - const_pointer address(const_reference value) const; - - //!Copy construct an object. - //!Throws if T's copy constructor throws - void construct(const pointer &ptr, const_reference v); - - //!Destroys object. Throws if object's - //!destructor throws - void destroy(const pointer &ptr); - - //!Returns maximum the number of objects the previously allocated memory - //!pointed by p can hold. This size only works for memory allocated with - //!allocate, allocation_command and allocate_many. - size_type size(const pointer &p) const; - - pointer allocation_command(boost::interprocess::allocation_type command, - size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); - - //!Allocates n_elements elements, each one of size elem_sizes[i]in a - //!contiguous block - //!of memory. The elements must be deallocated - void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); - - //!Allocates many elements of size elem_size in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. The elements must be deallocated - //!with deallocate(...) - void deallocate_many(multiallocation_chain &chain); - - //!Allocates just one object. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - //!Throws boost::interprocess::bad_alloc if there is no enough memory - pointer allocate_one(); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void allocate_individual(size_type num_elements, multiallocation_chain &chain); - - //!Deallocates memory previously allocated with allocate_one(). - //!You should never use deallocate_one to deallocate memory allocated - //!with other functions different from allocate_one(). Never throws - void deallocate_one(const pointer &p); - - //!Allocates many elements of size == 1 in a contiguous block - //!of memory. The minimum number to be allocated is min_elements, - //!the preferred and maximum number is - //!preferred_elements. The number of actually allocated elements is - //!will be assigned to received_size. Memory allocated with this function - //!must be deallocated only with deallocate_one(). - void deallocate_individual(multiallocation_chain &chain); - #endif -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Equality test for same type -//!of private_node_allocator -template inline -bool operator==(const private_node_allocator &alloc1, - const private_node_allocator &alloc2); - -//!Inequality test for same type -//!of private_node_allocator -template inline -bool operator!=(const private_node_allocator &alloc1, - const private_node_allocator &alloc2); - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP - diff --git a/extern/boost/boost/interprocess/anonymous_shared_memory.hpp b/extern/boost/boost/interprocess/anonymous_shared_memory.hpp deleted file mode 100644 index 4e0ec61b19a..00000000000 --- a/extern/boost/boost/interprocess/anonymous_shared_memory.hpp +++ /dev/null @@ -1,125 +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_ANONYMOUS_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -#if (!defined(BOOST_INTERPROCESS_WINDOWS)) -# include //open, O_CREAT, O_*... -# include //mmap -# include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, -#else -#include -#endif - - -//!\file -//!Describes a function that creates anonymous shared memory that can be -//!shared between forked processes - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail{ - - class raw_mapped_region_creator - { - public: - static mapped_region - create_posix_mapped_region(void *address, std::size_t size) - { - mapped_region region; - region.m_base = address; - region.m_size = size; - return region; - } - }; -} - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!A function that creates an anonymous shared memory segment of size "size". -//!If "address" is passed the function will try to map the segment in that address. -//!Otherwise the operating system will choose the mapping address. -//!The function returns a mapped_region holding that segment or throws -//!interprocess_exception if the function fails. -//static mapped_region -inline mapped_region -anonymous_shared_memory(std::size_t size, void *address = 0) -#if (!defined(BOOST_INTERPROCESS_WINDOWS)) -{ - int flags; - int fd = -1; - - #if defined(MAP_ANONYMOUS) //Use MAP_ANONYMOUS - flags = MAP_ANONYMOUS | MAP_SHARED; - #elif !defined(MAP_ANONYMOUS) && defined(MAP_ANON) //use MAP_ANON - flags = MAP_ANON | MAP_SHARED; - #else // Use "/dev/zero" - fd = open("/dev/zero", O_RDWR); - flags = MAP_SHARED; - if(fd == -1){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - #endif - - - address = mmap( address - , size - , PROT_READ|PROT_WRITE - , flags - , fd - , 0); - - if(address == MAP_FAILED){ - if(fd != -1) - close(fd); - error_info err = system_error_code(); - throw interprocess_exception(err); - } - - if(fd != -1) - close(fd); - - return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size); -} -#else -{ - windows_shared_memory anonymous_mapping(create_only, (char*)0, read_write, size); - return mapped_region(anonymous_mapping, read_write, 0, size, address); -} - -#endif - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/containers/allocation_type.hpp b/extern/boost/boost/interprocess/containers/allocation_type.hpp deleted file mode 100644 index d99b7ab51de..00000000000 --- a/extern/boost/boost/interprocess/containers/allocation_type.hpp +++ /dev/null @@ -1,44 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_ALLOCATION_TYPE_HPP -#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -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; -static const allocation_type expand_bwd = boost::container::expand_bwd; -static const allocation_type shrink_in_place = boost::container::shrink_in_place; -static const allocation_type try_shrink_in_place= boost::container::try_shrink_in_place; -static const allocation_type nothrow_allocation = boost::container::nothrow_allocation; -static const allocation_type zero_memory = boost::container::zero_memory; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP diff --git a/extern/boost/boost/interprocess/containers/containers_fwd.hpp b/extern/boost/boost/interprocess/containers/containers_fwd.hpp deleted file mode 100644 index 9620a92ee92..00000000000 --- a/extern/boost/boost/interprocess/containers/containers_fwd.hpp +++ /dev/null @@ -1,44 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_CONTAINERS_CONTAINERS_FWD_HPP -#define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -////////////////////////////////////////////////////////////////////////////// -// Standard predeclarations -////////////////////////////////////////////////////////////////////////////// - -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::ordered_range; -using boost::container::ordered_unique_range; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP diff --git a/extern/boost/boost/interprocess/containers/deque.hpp b/extern/boost/boost/interprocess/containers/deque.hpp deleted file mode 100644 index 50073060050..00000000000 --- a/extern/boost/boost/interprocess/containers/deque.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_DEQUE_HPP -#define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::deque; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP - diff --git a/extern/boost/boost/interprocess/containers/flat_map.hpp b/extern/boost/boost/interprocess/containers/flat_map.hpp deleted file mode 100644 index 6b9262b8dfc..00000000000 --- a/extern/boost/boost/interprocess/containers/flat_map.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_FLAT_MAP_HPP -#define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::flat_map; -using boost::container::flat_multimap; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP diff --git a/extern/boost/boost/interprocess/containers/flat_set.hpp b/extern/boost/boost/interprocess/containers/flat_set.hpp deleted file mode 100644 index 9c729a67e03..00000000000 --- a/extern/boost/boost/interprocess/containers/flat_set.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_FLAT_SET_HPP -#define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::flat_set; -using boost::container::flat_multiset; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP diff --git a/extern/boost/boost/interprocess/containers/list.hpp b/extern/boost/boost/interprocess/containers/list.hpp deleted file mode 100644 index 465e8828645..00000000000 --- a/extern/boost/boost/interprocess/containers/list.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_LIST_HPP -#define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::list; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP - diff --git a/extern/boost/boost/interprocess/containers/map.hpp b/extern/boost/boost/interprocess/containers/map.hpp deleted file mode 100644 index 966abdf3962..00000000000 --- a/extern/boost/boost/interprocess/containers/map.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_MAP_HPP -#define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::map; -using boost::container::multimap; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP diff --git a/extern/boost/boost/interprocess/containers/pair.hpp b/extern/boost/boost/interprocess/containers/pair.hpp deleted file mode 100644 index ccd3c235f04..00000000000 --- a/extern/boost/boost/interprocess/containers/pair.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_PAIR_HPP -#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::dtl::pair; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP - diff --git a/extern/boost/boost/interprocess/containers/set.hpp b/extern/boost/boost/interprocess/containers/set.hpp deleted file mode 100644 index 433607ba284..00000000000 --- a/extern/boost/boost/interprocess/containers/set.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_SET_HPP -#define BOOST_INTERPROCESS_CONTAINERS_SET_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::set; -using boost::container::multiset; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP diff --git a/extern/boost/boost/interprocess/containers/slist.hpp b/extern/boost/boost/interprocess/containers/slist.hpp deleted file mode 100644 index 1f1aee63ded..00000000000 --- a/extern/boost/boost/interprocess/containers/slist.hpp +++ /dev/null @@ -1,36 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_SLIST_HPP -#define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::slist; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP diff --git a/extern/boost/boost/interprocess/containers/stable_vector.hpp b/extern/boost/boost/interprocess/containers/stable_vector.hpp deleted file mode 100644 index f6d1ee1b04f..00000000000 --- a/extern/boost/boost/interprocess/containers/stable_vector.hpp +++ /dev/null @@ -1,36 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_STABLE_VECTOR_HPP -#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { - namespace interprocess { - - using boost::container::stable_vector; - - } //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP diff --git a/extern/boost/boost/interprocess/containers/string.hpp b/extern/boost/boost/interprocess/containers/string.hpp deleted file mode 100644 index bd1286411a8..00000000000 --- a/extern/boost/boost/interprocess/containers/string.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_STRING_HPP -#define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::basic_string; -using boost::container::string; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP diff --git a/extern/boost/boost/interprocess/containers/vector.hpp b/extern/boost/boost/interprocess/containers/vector.hpp deleted file mode 100644 index 89b3e471499..00000000000 --- a/extern/boost/boost/interprocess/containers/vector.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_VECTOR_HPP -#define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::vector; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP - diff --git a/extern/boost/boost/interprocess/containers/version_type.hpp b/extern/boost/boost/interprocess/containers/version_type.hpp deleted file mode 100644 index 68850729923..00000000000 --- a/extern/boost/boost/interprocess/containers/version_type.hpp +++ /dev/null @@ -1,37 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_VERSION_TYPE_HPP -#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -namespace boost { -namespace interprocess { - -using boost::container::dtl::version_type; -using boost::container::dtl::version; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP - diff --git a/extern/boost/boost/interprocess/detail/cast_tags.hpp b/extern/boost/boost/interprocess/detail/cast_tags.hpp deleted file mode 100644 index e47b86344cc..00000000000 --- a/extern/boost/boost/interprocess/detail/cast_tags.hpp +++ /dev/null @@ -1,31 +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_CAST_TAGS_HPP -#define BOOST_INTERPROCESS_DETAIL_CAST_TAGS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -namespace boost { namespace interprocess { namespace ipcdetail { - -struct static_cast_tag {}; -struct const_cast_tag {}; -struct dynamic_cast_tag {}; -struct reinterpret_cast_tag {}; - -}}} //namespace boost { namespace interprocess { namespace ipcdetail { - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_CAST_TAGS_HPP diff --git a/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp b/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp deleted file mode 100644 index c6688e619c1..00000000000 --- a/extern/boost/boost/interprocess/detail/file_locking_helpers.hpp +++ /dev/null @@ -1,302 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_FILE_LOCKING_HELPERS_HPP -#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -#include -#include -#include - -#else //defined(BOOST_INTERPROCESS_WINDOWS) - -#include -#include -#include - -#endif //defined(BOOST_INTERPROCESS_WINDOWS) - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -#if defined(BOOST_INTERPROCESS_WINDOWS) - -struct locking_file_serial_id -{ - int fd; - unsigned long dwVolumeSerialNumber; - unsigned long nFileIndexHigh; - unsigned long nFileIndexLow; - //This reference count counts the number of modules attached - //to the shared memory and lock file. This serves to unlink - //the locking file and shared memory when all modules are - //done with the global memory (shared memory) - volatile boost::uint32_t modules_attached_to_gmem_count; -}; - -inline bool lock_locking_file(int fd) -{ - int ret = 0; - while(ret != 0 && errno == EDEADLK){ - ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/); - } - return 0 == ret; -} - -inline bool try_lock_locking_file(int fd) -{ - return 0 == _locking(fd, _LK_NBLCK , 1); -} - -inline int open_or_create_and_lock_file(const char *name) -{ - permissions p; - p.set_unrestricted(); - while(1){ - file_handle_t handle = create_or_open_file(name, read_write, p); - int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); - if(fd < 0){ - close_file(handle); - return fd; - } - if(!try_lock_locking_file(fd)){ - _close(fd); - return -1; - } - struct _stat s; - if(0 == _stat(name, &s)){ - return fd; - } - else{ - _close(fd); - } - } -} - -inline int try_open_and_lock_file(const char *name) -{ - file_handle_t handle = open_existing_file(name, read_write); - int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); - if(fd < 0){ - close_file(handle); - return fd; - } - if(!try_lock_locking_file(fd)){ - _close(fd); - return -1; - } - return fd; -} - -inline void close_lock_file(int fd) -{ _close(fd); } - -inline bool is_valid_fd(int fd) -{ - struct _stat s; - return EBADF != _fstat(fd, &s); -} - -inline bool is_normal_file(int fd) -{ - if(_isatty(fd)) - return false; - struct _stat s; - if(0 != _fstat(fd, &s)) - return false; - return 0 != (s.st_mode & _S_IFREG); -} - -inline std::size_t get_size(int fd) -{ - struct _stat s; - if(0 != _fstat(fd, &s)) - return 0u; - return (std::size_t)s.st_size; -} - -inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) -{ - winapi::interprocess_by_handle_file_information info; - if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) - return false; - id.fd = fd; - id.dwVolumeSerialNumber = info.dwVolumeSerialNumber; - id.nFileIndexHigh = info.nFileIndexHigh; - id.nFileIndexLow = info.nFileIndexLow; - id.modules_attached_to_gmem_count = 1; //Initialize attached count - return true; -} - -inline bool compare_file_serial(int fd, const locking_file_serial_id &id) -{ - winapi::interprocess_by_handle_file_information info; - if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) - return false; - - return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber && - id.nFileIndexHigh == info.nFileIndexHigh && - id.nFileIndexLow == info.nFileIndexLow; -} - -#else //UNIX - -struct locking_file_serial_id -{ - int fd; - dev_t st_dev; - ino_t st_ino; - //This reference count counts the number of modules attached - //to the shared memory and lock file. This serves to unlink - //the locking file and shared memory when all modules are - //done with the global memory (shared memory) - volatile boost::uint32_t modules_attached_to_gmem_count; -}; - -inline bool lock_locking_file(int fd) -{ - int ret = 0; - while(ret != 0 && errno != EINTR){ - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - ret = fcntl (fd, F_SETLKW, &lock); - } - return 0 == ret; -} - -inline bool try_lock_locking_file(int fd) -{ - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - return 0 == fcntl (fd, F_SETLK, &lock); -} - -inline int open_or_create_and_lock_file(const char *name) -{ - permissions p; - p.set_unrestricted(); - while(1){ - int fd = create_or_open_file(name, read_write, p); - if(fd < 0){ - return fd; - } - if(!try_lock_locking_file(fd)){ - close(fd); - return -1; - } - struct stat s; - if(0 == stat(name, &s)){ - return fd; - } - else{ - close(fd); - } - } -} - -inline int try_open_and_lock_file(const char *name) -{ - int fd = open_existing_file(name, read_write); - if(fd < 0){ - return fd; - } - if(!try_lock_locking_file(fd)){ - close(fd); - return -1; - } - return fd; -} - -inline void close_lock_file(int fd) -{ close(fd); } - -inline bool is_valid_fd(int fd) -{ - struct stat s; - return EBADF != fstat(fd, &s); -} - -inline bool is_normal_file(int fd) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return false; - return 0 != (s.st_mode & S_IFREG); -} - -inline std::size_t get_size(int fd) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return 0u; - return (std::size_t)s.st_size; -} - -inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) -{ - struct stat s; - if(0 != fstat(fd, &s)) - return false; - id.fd = fd; - id.st_dev = s.st_dev; - id.st_ino = s.st_ino; - id.modules_attached_to_gmem_count = 1; //Initialize attached count - return true; -} - -inline bool compare_file_serial(int fd, const locking_file_serial_id &id) -{ - struct stat info; - if(0 != fstat(fd, &info)) - return false; - - return id.st_dev == info.st_dev && - id.st_ino == info.st_ino; -} - -#endif - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP diff --git a/extern/boost/boost/interprocess/detail/file_wrapper.hpp b/extern/boost/boost/interprocess/detail/file_wrapper.hpp deleted file mode 100644 index 84b495362a9..00000000000 --- a/extern/boost/boost/interprocess/detail/file_wrapper.hpp +++ /dev/null @@ -1,233 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2006-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_FILE_WRAPPER_HPP -#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -class file_wrapper -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Default constructor. - //!Represents an empty file_wrapper. - file_wrapper(); - - //!Creates a file object with name "name" and mode "mode", with the access mode "mode" - //!If the file previously exists, throws an error. - file_wrapper(create_only_t, const char *name, mode_t mode, const permissions &perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); } - - //!Tries to create a file 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. - file_wrapper(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } - - //!Tries to open a file with name "name", with the access mode "mode". - //!If the file does not previously exist, it throws an error. - file_wrapper(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 file 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). - file_wrapper(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 file 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). - file_wrapper(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 file 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). - file_wrapper(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 file to *this. - //!After the call, "moved" does not represent any file. - //!Does not throw - file_wrapper(BOOST_RV_REF(file_wrapper) moved) - : m_handle(file_handle_t(ipcdetail::invalid_file())) - { this->swap(moved); } - - //!Moves the ownership of "moved"'s file to *this. - //!After the call, "moved" does not represent any file. - //!Does not throw - file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved) - { - file_wrapper tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps to file_wrappers. - //!Does not throw - void swap(file_wrapper &other); - - //!Erases a file from the system. - //!Returns false on error. Never throws - static bool remove(const char *name); - - //!Sets the size of the file - void truncate(offset_t length); - - //!Closes the - //!file - ~file_wrapper(); - - //!Returns the name of the file - //!used in the constructor - const char *get_name() const; - - //!Returns the name of the file - //!used in the constructor - bool get_size(offset_t &size) const; - - //!Returns access mode - //!used in the constructor - mode_t get_mode() const; - - //!Get mapping handle - //!to use with mapped_region - mapping_handle_t get_mapping_handle() const; - - private: - //!Closes a previously opened file mapping. Never throws. - void priv_close(); - //!Closes a previously opened file mapping. Never throws. - template - 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; -}; - -inline file_wrapper::file_wrapper() - : m_handle(file_handle_t(ipcdetail::invalid_file())) - , m_mode(read_only) -{} - -inline file_wrapper::~file_wrapper() -{ this->priv_close(); } - -inline bool file_wrapper::get_size(offset_t &size) const -{ return get_file_size((file_handle_t)m_handle, size); } - -inline void file_wrapper::swap(file_wrapper &other) -{ - (simple_swap)(m_handle, other.m_handle); - (simple_swap)(m_mode, other.m_mode); -} - -inline mapping_handle_t file_wrapper::get_mapping_handle() const -{ return mapping_handle_from_file_handle(m_handle); } - -inline mode_t file_wrapper::get_mode() const -{ return m_mode; } - -template -inline bool file_wrapper::priv_open_or_create - ( ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm) -{ - if(mode != read_only && mode != read_write){ - error_info err(mode_error); - throw interprocess_exception(err); - } - - //Open file existing native API to obtain the handle - switch(type){ - case ipcdetail::DoOpen: - m_handle = open_existing_file(filename, mode); - break; - case ipcdetail::DoCreate: - m_handle = create_new_file(filename, mode, perm); - break; - case ipcdetail::DoOpenOrCreate: - m_handle = create_or_open_file(filename, mode, perm); - break; - default: - { - error_info err = other_error; - throw interprocess_exception(err); - } - } - - //Check for error - if(m_handle == invalid_file()){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - - m_mode = mode; - return true; -} - -inline bool file_wrapper::remove(const char *filename) -{ return delete_file(filename); } - -inline void file_wrapper::truncate(offset_t length) -{ - if(!truncate_file(m_handle, (std::size_t)length)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -inline void file_wrapper::priv_close() -{ - if(m_handle != invalid_file()){ - close_file(m_handle); - m_handle = invalid_file(); - } -} - -} //namespace ipcdetail{ -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/detail/in_place_interface.hpp b/extern/boost/boost/interprocess/detail/in_place_interface.hpp deleted file mode 100644 index 89ad74eac76..00000000000 --- a/extern/boost/boost/interprocess/detail/in_place_interface.hpp +++ /dev/null @@ -1,77 +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_IN_PLACE_INTERFACE_HPP -#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include //alignment_of, aligned_storage -#include //typeid - -//!\file -//!Describes an abstract interface for placement construction and destruction. - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -struct in_place_interface -{ - in_place_interface(std::size_t alignm, std::size_t sz, const char *tname) - : alignment(alignm), size(sz), type_name(tname) - {} - - std::size_t alignment; - std::size_t size; - const char *type_name; - - virtual void construct_n(void *mem, std::size_t num) = 0; - virtual void destroy_n(void *mem, std::size_t num) = 0; - virtual ~in_place_interface(){} -}; - -template -struct placement_destroy : public in_place_interface -{ - placement_destroy() - : in_place_interface(::boost::container::dtl::alignment_of::value, sizeof(T), typeid(T).name()) - {} - - virtual void destroy_n(void *mem, std::size_t num) BOOST_OVERRIDE - { - T* memory = static_cast(mem); - for(std::size_t destroyed = 0; destroyed < num; ++destroyed) - (memory++)->~T(); - } - - virtual void construct_n(void *, std::size_t) BOOST_OVERRIDE {} - - private: - void destroy(void *mem) - { static_cast(mem)->~T(); } -}; - -} -} -} //namespace boost { namespace interprocess { namespace ipcdetail { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP diff --git a/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp b/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp deleted file mode 100644 index 24148d47590..00000000000 --- a/extern/boost/boost/interprocess/detail/intermodule_singleton.hpp +++ /dev/null @@ -1,53 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_INTERMODULE_SINGLETON_HPP -#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include - -#ifdef BOOST_INTERPROCESS_WINDOWS - #include -#else - #include -#endif - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -//Now this class is a singleton, initializing the singleton in -//the first get() function call if LazyInit is true. If false -//then the singleton will be initialized when loading the module. -template -class intermodule_singleton - #ifdef BOOST_INTERPROCESS_WINDOWS - : public windows_intermodule_singleton - #else - : public portable_intermodule_singleton - #endif -{}; - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif diff --git a/extern/boost/boost/interprocess/detail/interprocess_tester.hpp b/extern/boost/boost/interprocess/detail/interprocess_tester.hpp deleted file mode 100644 index 368820f82a3..00000000000 --- a/extern/boost/boost/interprocess/detail/interprocess_tester.hpp +++ /dev/null @@ -1,39 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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_INTERPROCESS_TESTER_HPP -#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -class interprocess_tester -{ - public: - template - static void dont_close_on_destruction(T &t) - { t.dont_close_on_destruction(); } -}; - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP - diff --git a/extern/boost/boost/interprocess/detail/managed_global_memory.hpp b/extern/boost/boost/interprocess/detail/managed_global_memory.hpp deleted file mode 100644 index fdf9e1f0481..00000000000 --- a/extern/boost/boost/interprocess/detail/managed_global_memory.hpp +++ /dev/null @@ -1,119 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_BASIC_GLOBAL_MEMORY_HPP -#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -struct intermodule_singleton_mutex_family -{ - typedef boost::interprocess::ipcdetail::spin_mutex mutex_type; - typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type; -}; - -struct intermodule_types -{ - //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory - //at a different address than other DLLs or the main executable - typedef rbtree_best_fit > mem_algo; - template - struct open_or_create - { - typedef managed_open_or_create_impl - type; - }; -}; - -//we must implement our own managed shared memory to avoid circular dependencies -template -class basic_managed_global_memory - : public basic_managed_memory_impl - < char - , intermodule_types::mem_algo - , iset_index - , intermodule_types::open_or_create::type::ManagedOpenOrCreateUserOffset - > - , private intermodule_types::open_or_create::type -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef typename intermodule_types::template open_or_create::type base2_t; - - typedef basic_managed_memory_impl - < char - , intermodule_types::mem_algo - , iset_index - , base2_t::ManagedOpenOrCreateUserOffset - > base_t; - - typedef create_open_func create_open_func_t; - - basic_managed_global_memory *get_this_pointer() - { return this; } - - public: - typedef typename base_t::size_type size_type; - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - - basic_managed_global_memory (open_or_create_t, - const char *name, size_type size, - const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(open_or_create_t(), name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - DoOpenOrCreate), perm) - {} - - basic_managed_global_memory (open_only_t , const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only_t(), name, read_write, addr, - create_open_func_t(get_this_pointer(), - DoOpen)) - {} -}; - - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif //#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp b/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp deleted file mode 100644 index 72e242d50ac..00000000000 --- a/extern/boost/boost/interprocess/detail/managed_memory_impl.hpp +++ /dev/null @@ -1,775 +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_MANAGED_MEMORY_IMPL_HPP -#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -// -#include -// -#include -#include - -//!\file -//!Describes a named shared memory allocation user class. -//! - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template -class create_open_func; - -template< - class CharType, - class MemoryAlgorithm, - template class IndexType - > -struct segment_manager_type -{ - typedef segment_manager type; -}; - -//!This class is designed to be a base class to classes that manage -//!creation of objects in a fixed size memory buffer. Apart -//!from allocating raw memory, the user can construct named objects. To -//!achieve this, this class uses the reserved space provided by the allocation -//!algorithm to place a named_allocator_algo, who takes care of name mappings. -//!The class can be customized with the char type used for object names -//!and the memory allocation algorithm to be used.*/ -template < class CharType - , class MemoryAlgorithm - , template class IndexType - , std::size_t Offset = 0 - > -class basic_managed_memory_impl -{ - //Non-copyable - basic_managed_memory_impl(const basic_managed_memory_impl &); - basic_managed_memory_impl &operator=(const basic_managed_memory_impl &); - - template - friend class create_open_func; - - public: - typedef typename segment_manager_type - ::type segment_manager; - typedef CharType char_type; - typedef MemoryAlgorithm memory_algorithm; - typedef typename MemoryAlgorithm::mutex_family mutex_family; - typedef CharType char_t; - typedef typename MemoryAlgorithm::size_type size_type; - typedef typename MemoryAlgorithm::difference_type difference_type; - typedef difference_type handle_t; - typedef typename segment_manager:: - const_named_iterator const_named_iterator; - typedef typename segment_manager:: - const_unique_iterator const_unique_iterator; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - typedef typename - segment_manager::char_ptr_holder_t char_ptr_holder_t; - //Experimental. Don't use. - - typedef typename segment_manager::multiallocation_chain multiallocation_chain; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation; - - private: - typedef basic_managed_memory_impl - self_t; - protected: - template - static bool grow(const CharT *filename, size_type extra_bytes) - { - typedef typename ManagedMemory::device_type device_type; - //Increase file size - BOOST_TRY{ - offset_t old_size; - { - device_type f(open_or_create, filename, read_write); - if(!f.get_size(old_size)) - return false; - f.truncate(old_size + static_cast(extra_bytes)); - } - ManagedMemory managed_memory(open_only, filename); - //Grow always works - managed_memory.self_t::grow(extra_bytes); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END - return true; - } - - template - static bool shrink_to_fit(const CharT *filename) - { - typedef typename ManagedMemory::device_type device_type; - size_type new_size; - BOOST_TRY{ - ManagedMemory managed_memory(open_only, filename); - managed_memory.get_size(); - managed_memory.self_t::shrink_to_fit(); - new_size = managed_memory.get_size(); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END - - //Decrease file size - { - device_type f(open_or_create, filename, read_write); - f.truncate(static_cast(new_size)); - } - return true; - } - - //!Constructor. Allocates basic resources. Never throws. - basic_managed_memory_impl() - : mp_header(0){} - - //!Destructor. Calls close. Never throws. - ~basic_managed_memory_impl() - { this->close_impl(); } - - //!Places segment manager in the reserved space. This can throw. - bool create_impl (void *addr, size_type size) - { - if(mp_header) return false; - - //Check if there is enough space - if(size < segment_manager::get_min_size()) - return false; - - //This function should not throw. The index construction can - //throw if constructor allocates memory. So we must catch it. - BOOST_TRY{ - //Let's construct the allocator in memory - BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of::value)); - mp_header = ::new(addr, boost_container_new_t()) segment_manager(size); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END - return true; - } - - //!Connects to a segment manager in the reserved buffer. Never throws. - bool open_impl (void *addr, size_type) - { - if(mp_header) return false; - mp_header = static_cast(addr); - return true; - } - - //!Frees resources. Never throws. - bool close_impl() - { - bool ret = mp_header != 0; - mp_header = 0; - return ret; - } - - //!Frees resources and destroys common resources. Never throws. - bool destroy_impl() - { - if(mp_header == 0) - return false; - mp_header->~segment_manager(); - this->close_impl(); - return true; - } - - //! - void grow(size_type extra_bytes) - { mp_header->grow(extra_bytes); } - - void shrink_to_fit() - { mp_header->shrink_to_fit(); } - - public: - - //!Returns segment manager. Never throws. - segment_manager *get_segment_manager() const - { return mp_header; } - - //!Returns the base address of the memory in this process. Never throws. - void * get_address () const - { return reinterpret_cast(mp_header) - Offset; } - - //!Returns the size of memory segment. Never throws. - size_type get_size () const - { return mp_header->get_size() + Offset; } - - //!Returns the number of free bytes of the memory - //!segment - size_type get_free_memory() const - { return mp_header->get_free_memory(); } - - //!Returns the result of "all_memory_deallocated()" function - //!of the used memory algorithm - bool all_memory_deallocated() - { return mp_header->all_memory_deallocated(); } - - //!Returns the result of "check_sanity()" function - //!of the used memory algorithm - bool check_sanity() - { return mp_header->check_sanity(); } - - //!Writes to zero free memory (memory not yet allocated) of - //!the memory algorithm - void zero_free_memory() - { mp_header->zero_free_memory(); } - - //!Transforms an absolute address into an offset from base address. - //!The address must belong to the memory segment. Never throws. - handle_t get_handle_from_address (const void *ptr) const - { - return (handle_t)(reinterpret_cast(ptr) - - reinterpret_cast(this->get_address())); - } - - //!Returns true if the address belongs to the managed memory segment - bool belongs_to_segment (const void *ptr) const - { - return ptr >= this->get_address() && - ptr < (reinterpret_cast(this->get_address()) + this->get_size()); - } - - //!Transforms previously obtained offset into an absolute address in the - //!process space of the current process. Never throws.*/ - void * get_address_from_handle (handle_t offset) const - { return reinterpret_cast(this->get_address()) + offset; } - - //!Searches for nbytes of free memory in the segment, marks the - //!memory as used and return the pointer to the memory. If no - //!memory is available throws a boost::interprocess::bad_alloc exception - void* allocate (size_type nbytes) - { return mp_header->allocate(nbytes); } - - //!Searches for nbytes of free memory in the segment, marks the - //!memory as used and return the pointer to the memory. If no memory - //!is available returns 0. Never throws. - void* allocate (size_type nbytes, const std::nothrow_t &tag) - { return mp_header->allocate(nbytes, tag); } - - //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" - //!must be power of two. If no memory - //!is available returns 0. Never throws. - void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag) - { return mp_header->allocate_aligned(nbytes, alignment, tag); } - - template - T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse) - { return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } - - //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" - //!must be power of two. If no - //!memory is available throws a boost::interprocess::bad_alloc exception - void * allocate_aligned(size_type nbytes, size_type alignment) - { return mp_header->allocate_aligned(nbytes, alignment); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Experimental. Don't use. - - //!Allocates n_elements of elem_bytes bytes. - //!Throws bad_alloc on failure. chain.size() is not increased on failure. - void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) - { mp_header->allocate_many(elem_bytes, n_elements, chain); } - - //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. - //!Throws bad_alloc on failure. chain.size() is not increased on failure. - void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); } - - //!Allocates n_elements of elem_bytes bytes. - //!Non-throwing version. chain.size() is not increased on failure. - void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) - { mp_header->allocate_many(tag, elem_bytes, n_elements, chain); } - - //!Allocates n_elements, each one of - //!element_lengths[i]*sizeof_element bytes. - //!Non-throwing version. chain.size() is not increased on failure. - void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); } - - //!Deallocates all elements contained in chain. - //!Never throws. - void deallocate_many(multiallocation_chain &chain) - { mp_header->deallocate_many(chain); } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Marks previously allocated memory as free. Never throws. - void deallocate (void *addr) - { if (mp_header) mp_header->deallocate(addr); } - - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find (char_ptr_holder_t name) - { return mp_header->template find(name); } - - //!Creates a named object or array in memory - //! - //!Allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. If an array is being constructed all objects are - //!created using the same parameters given to this function. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and if an - //!array was being constructed, destructors of created objects are called - //!before freeing the memory. - template - typename segment_manager::template construct_proxy::type - construct(char_ptr_holder_t name) - { return mp_header->template construct(name); } - - //!Finds or creates a named object or array in memory - //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. If an array is being constructed all objects are - //!created using the same parameters given to this function. - //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and if an - //!array was being constructed, destructors of created objects are called - //!before freeing the memory. - template - typename segment_manager::template construct_proxy::type - find_or_construct(char_ptr_holder_t name) - { return mp_header->template find_or_construct(name); } - - //!Creates a named object or array in memory - //! - //!Allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. If an array is being constructed all objects are - //!created using the same parameters given to this function. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> Returns 0 if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and if an - //!array was being constructed, destructors of created objects are called - //!before freeing the memory. - template - typename segment_manager::template construct_proxy::type - construct(char_ptr_holder_t name, const std::nothrow_t &tag) - { return mp_header->template construct(name, tag); } - - //!Finds or creates a named object or array in memory - //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs a T object or an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. If an array is being constructed all objects are - //!created using the same parameters given to this function. - //! - //!-> Returns 0 if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and if an - //!array was being constructed, destructors of created objects are called - //!before freeing the memory. - template - typename segment_manager::template construct_proxy::type - find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag) - { return mp_header->template find_or_construct(name, tag); } - - //!Creates a named array from iterators in memory - //! - //!Allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. Each element in the array is created using the - //!objects returned when dereferencing iterators as parameters - //!and incrementing all iterators for each element. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and - //!destructors of created objects are called before freeing the memory. - template - typename segment_manager::template construct_iter_proxy::type - construct_it(char_ptr_holder_t name) - { return mp_header->template construct_it(name); } - - //!Finds or creates a named array from iterators in memory - //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. Each element in the array is created using the - //!objects returned when dereferencing iterators as parameters - //!and incrementing all iterators for each element. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> Throws boost::interprocess::bad_alloc if there is no available memory - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and - //!destructors of created objects are called before freeing the memory. - template - typename segment_manager::template construct_iter_proxy::type - find_or_construct_it(char_ptr_holder_t name) - { return mp_header->template find_or_construct_it(name); } - - //!Creates a named array from iterators in memory - //! - //!Allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. Each element in the array is created using the - //!objects returned when dereferencing iterators as parameters - //!and incrementing all iterators for each element. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> If there is no available memory, returns 0. - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and - //!destructors of created objects are called before freeing the memory.*/ - template - typename segment_manager::template construct_iter_proxy::type - construct_it(char_ptr_holder_t name, const std::nothrow_t &tag) - { return mp_header->template construct_it(name, tag); } - - //!Finds or creates a named array from iterators in memory - //! - //!Tries to find an object with the given name in memory. If - //!found, returns the pointer to this pointer. If the object is not found, - //!allocates and constructs an array of T in memory, - //!associates this with the given name and returns a pointer to the - //!created object. Each element in the array is created using the - //!objects returned when dereferencing iterators as parameters - //!and incrementing all iterators for each element. - //! - //!-> If the name was previously used, returns 0. - //! - //!-> If there is no available memory, returns 0. - //! - //!-> If T's constructor throws, the function throws that exception. - //! - //!Memory is freed automatically if T's constructor throws and - //!destructors of created objects are called before freeing the memory.*/ - template - typename segment_manager::template construct_iter_proxy::type - find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag) - { return mp_header->template find_or_construct_it(name, tag); } - - //!Calls a functor and guarantees that no new construction, search or - //!destruction will be executed by any process while executing the object - //!function call. If the functor throws, this function throws. - template - void atomic_func(Func &f) - { mp_header->atomic_func(f); } - - //!Tries to call a functor guaranteeing that no new construction, search or - //!destruction will be executed by any process while executing the object - //!function call. If the atomic function can't be immediatelly executed - //!because the internal mutex is already locked, returns false. - //!If the functor throws, this function throws. - template - bool try_atomic_func(Func &f) - { return mp_header->try_atomic_func(f); } - - //!Destroys a named memory object or array. - //! - //!Finds the object with the given name, calls its destructors, - //!frees used memory and returns true. - //! - //!-> If the object is not found, it returns false. - //! - //!Exception Handling: - //! - //!When deleting a dynamically object or array, the Standard - //!does not guarantee that dynamically allocated memory, will be released. - //!Also, when deleting arrays, the Standard doesn't require calling - //!destructors for the rest of the objects if for one of them the destructor - //!terminated with an exception. - //! - //!Destroying an object: - //! - //!If the destructor throws, the memory will be freed and that exception - //!will be thrown. - //! - //!Destroying an array: - //! - //!When destroying an array, if a destructor throws, the rest of - //!destructors are called. If any of these throws, the exceptions are - //!ignored. The name association will be erased, memory will be freed and - //!the first exception will be thrown. This guarantees the unlocking of - //!mutexes and other resources. - //! - //!For all theses reasons, classes with throwing destructors are not - //!recommended. - template - bool destroy(const CharType *name) - { return mp_header->template destroy(name); } - - //!Destroys the unique instance of type T - //! - //!Calls the destructor, frees used memory and returns true. - //! - //!Exception Handling: - //! - //!When deleting a dynamically object, the Standard does not - //!guarantee that dynamically allocated memory will be released. - //! - //!Destroying an object: - //! - //!If the destructor throws, the memory will be freed and that exception - //!will be thrown. - //! - //!For all theses reasons, classes with throwing destructors are not - //!recommended for memory. - template - bool destroy(const unique_instance_t *const ) - { return mp_header->template destroy(unique_instance); } - - //!Destroys the object (named, unique, or anonymous) - //! - //!Calls the destructor, frees used memory and returns true. - //! - //!Exception Handling: - //! - //!When deleting a dynamically object, the Standard does not - //!guarantee that dynamically allocated memory will be released. - //! - //!Destroying an object: - //! - //!If the destructor throws, the memory will be freed and that exception - //!will be thrown. - //! - //!For all theses reasons, classes with throwing destructors are not - //!recommended for memory. - template - void destroy_ptr(const T *ptr) - { mp_header->template destroy_ptr(ptr); } - - //!Returns the name of an object created with construct/find_or_construct - //!functions. If ptr points to an unique instance typeid(T).name() is returned. - template - static const char_type *get_instance_name(const T *ptr) - { return segment_manager::get_instance_name(ptr); } - - //!Returns is the type an object created with construct/find_or_construct - //!functions. Does not throw. - template - static instance_type get_instance_type(const T *ptr) - { return segment_manager::get_instance_type(ptr); } - - //!Returns the length of an object created with construct/find_or_construct - //!functions (1 if is a single element, >=1 if it's an array). Does not throw. - template - static size_type get_instance_length(const T *ptr) - { return segment_manager::get_instance_length(ptr); } - - //!Preallocates needed index resources to optimize the - //!creation of "num" named objects in the memory segment. - //!Can throw boost::interprocess::bad_alloc if there is no enough memory. - void reserve_named_objects(size_type num) - { mp_header->reserve_named_objects(num); } - - //!Preallocates needed index resources to optimize the - //!creation of "num" unique objects in the memory segment. - //!Can throw boost::interprocess::bad_alloc if there is no enough memory. - void reserve_unique_objects(size_type num) - { mp_header->reserve_unique_objects(num); } - - //!Calls shrink_to_fit in both named and unique object indexes - //to try to free unused memory from those indexes. - void shrink_to_fit_indexes() - { mp_header->shrink_to_fit_indexes(); } - - //!Returns the number of named objects stored - //!in the managed segment. - size_type get_num_named_objects() - { return mp_header->get_num_named_objects(); } - - //!Returns the number of unique objects stored - //!in the managed segment. - size_type get_num_unique_objects() - { return mp_header->get_num_unique_objects(); } - - //!Returns a constant iterator to the index storing the - //!named allocations. NOT thread-safe. Never throws. - const_named_iterator named_begin() const - { return mp_header->named_begin(); } - - //!Returns a constant iterator to the end of the index - //!storing the named allocations. NOT thread-safe. Never throws. - const_named_iterator named_end() const - { return mp_header->named_end(); } - - //!Returns a constant iterator to the index storing the - //!unique allocations. NOT thread-safe. Never throws. - const_unique_iterator unique_begin() const - { return mp_header->unique_begin(); } - - //!Returns a constant iterator to the end of the index - //!storing the unique allocations. NOT thread-safe. Never throws. - const_unique_iterator unique_end() const - { return mp_header->unique_end(); } - - //!This is the default allocator to allocate types T - //!from this managed segment - template - struct allocator - { - typedef typename segment_manager::template allocator::type type; - }; - - //!Returns an instance of the default allocator for type T - //!initialized that allocates memory from this segment manager. - template - typename allocator::type - get_allocator() - { return mp_header->template get_allocator(); } - - //!This is the default deleter to delete types T - //!from this managed segment. - template - struct deleter - { - typedef typename segment_manager::template deleter::type type; - }; - - //!Returns an instance of the default allocator for type T - //!initialized that allocates memory from this segment manager. - template - typename deleter::type - get_deleter() - { return mp_header->template get_deleter(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find_no_lock (char_ptr_holder_t name) - { return mp_header->template find_no_lock(name); } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - protected: - //!Swaps the segment manager's managed by this managed memory segment. - //!NOT thread-safe. Never throws. - void swap(basic_managed_memory_impl &other) - { (simple_swap)(mp_header, other.mp_header); } - - private: - segment_manager *mp_header; -}; - -template -class create_open_func -{ - typedef typename BasicManagedMemoryImpl::size_type size_type; - - public: - - create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type) - : m_frontend(frontend), m_type(type){} - - bool operator()(void *addr, std::size_t size, bool created) const - { - if( ((m_type == DoOpen) && created) || - ((m_type == DoCreate) && !created) || - //Check for overflow - size_type(-1) < size ){ - return false; - } - else if(created){ - return m_frontend->create_impl(addr, static_cast(size)); - } - else{ - return m_frontend->open_impl (addr, static_cast(size)); - } - } - - static std::size_t get_min_size() - { - const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size(); - if(sz > std::size_t(-1)){ - //The minimum size is not representable by std::size_t - BOOST_ASSERT(false); - return std::size_t(-1); - } - else{ - return static_cast(sz); - } - } - - private: - BasicManagedMemoryImpl *m_frontend; - create_enum_t m_type; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP - diff --git a/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp b/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp deleted file mode 100644 index f7acdb89da4..00000000000 --- a/extern/boost/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ /dev/null @@ -1,574 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2006-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_MANAGED_OPEN_OR_CREATE_IMPL -#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include //alignment_of, aligned_storage -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template -class managed_open_or_create_impl_device_holder -{ - public: - DeviceAbstraction &get_device() - { static DeviceAbstraction dev; return dev; } - - const DeviceAbstraction &get_device() const - { static DeviceAbstraction dev; return dev; } -}; - -template -class managed_open_or_create_impl_device_holder -{ - public: - DeviceAbstraction &get_device() - { return dev; } - - const DeviceAbstraction &get_device() const - { return dev; } - - private: - DeviceAbstraction dev; -}; - -template -class managed_open_or_create_impl - : public managed_open_or_create_impl_device_holder -{ - //Non-copyable - BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl) - typedef bool_ file_like_t; - - static const unsigned MaxCreateOrOpenTries = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES; - static const unsigned MaxInitializeTimeSec = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC; - - typedef managed_open_or_create_impl_device_holder DevHolder; - enum - { - UninitializedSegment, - InitializingSegment, - InitializedSegment, - CorruptedSegment - }; - - static const std::size_t RequiredAlignment = - MemAlignment ? MemAlignment - : boost::container::dtl::alignment_of< boost::container::dtl::max_align_t >::value - ; - - public: - static const std::size_t ManagedOpenOrCreateUserOffset = - ct_rounded_size::value; - - managed_open_or_create_impl() - {} - - template - managed_open_or_create_impl(create_only_t, - const DeviceId & id, - std::size_t size, - mode_t mode, - const void *addr, - const permissions &perm) - { - priv_open_or_create - ( DoCreate - , id - , size - , mode - , addr - , perm - , null_mapped_region_function()); - } - - template - managed_open_or_create_impl(open_only_t, - const DeviceId & id, - mode_t mode, - const void *addr) - { - priv_open_or_create - ( DoOpen - , id - , 0 - , mode - , addr - , permissions() - , null_mapped_region_function()); - } - - template - managed_open_or_create_impl(open_or_create_t, - const DeviceId & id, - std::size_t size, - mode_t mode, - const void *addr, - const permissions &perm) - { - priv_open_or_create - ( DoOpenOrCreate - , id - , size - , mode - , addr - , perm - , null_mapped_region_function()); - } - - template - managed_open_or_create_impl(create_only_t, - const DeviceId & id, - std::size_t size, - mode_t mode, - const void *addr, - const ConstructFunc &construct_func, - const permissions &perm) - { - priv_open_or_create - (DoCreate - , id - , size - , mode - , addr - , perm - , construct_func); - } - - template - managed_open_or_create_impl(open_only_t, - const DeviceId & id, - mode_t mode, - const void *addr, - const ConstructFunc &construct_func) - { - priv_open_or_create - ( DoOpen - , id - , 0 - , mode - , addr - , permissions() - , construct_func); - } - - template - managed_open_or_create_impl(open_or_create_t, - const DeviceId & id, - std::size_t size, - mode_t mode, - const void *addr, - const ConstructFunc &construct_func, - const permissions &perm) - { - priv_open_or_create - ( DoOpenOrCreate - , id - , size - , mode - , addr - , perm - , construct_func); - } - - template - managed_open_or_create_impl(std::size_t size, void *addr, const ConstructFunc &construct_func) - { - priv_map_anonymous - ( size - , addr - , construct_func); - } - - managed_open_or_create_impl(BOOST_RV_REF(managed_open_or_create_impl) moved) - { this->swap(moved); } - - managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved) - { - managed_open_or_create_impl tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - ~managed_open_or_create_impl() - {} - - std::size_t get_user_size() const - { return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; } - - void *get_user_address() const - { return static_cast(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset; } - - std::size_t get_real_size() const - { return m_mapped_region.get_size(); } - - void *get_real_address() const - { return m_mapped_region.get_address(); } - - void swap(managed_open_or_create_impl &other) - { - this->m_mapped_region.swap(other.m_mapped_region); - } - - bool flush() - { return m_mapped_region.flush(); } - - const mapped_region &get_mapped_region() const - { return m_mapped_region; } - - DeviceAbstraction &get_device() - { return this->DevHolder::get_device(); } - - const DeviceAbstraction &get_device() const - { return this->DevHolder::get_device(); } - - private: - - //These are templatized to allow explicit instantiations - template - static void truncate_device(DeviceAbstraction &, offset_t, false_) - {} //Empty - - template - static void truncate_device(DeviceAbstraction &dev, offset_t size, true_) - { dev.truncate(size); } - - - template - static bool check_offset_t_size(std::size_t , false_) - { return true; } //Empty - - template - static bool check_offset_t_size(std::size_t size, true_) - { return size == std::size_t(offset_t(size)); } - - //These are templatized to allow explicit instantiations - template - static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm, false_ /*file_like*/) - { - DeviceAbstraction tmp(create_only, id, read_write, size, perm); - tmp.swap(dev); - } - - template - static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t, const permissions &perm, true_ /*file_like*/) - { - DeviceAbstraction tmp(create_only, id, read_write, perm); - tmp.swap(dev); - } - - template - static bool do_create_else_open(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm) - { - //This loop is very ugly, but brute force is sometimes better - //than diplomacy. In POSIX file-based resources we can' know if we - //effectively created the file or not (there is no ERROR_ALREADY_EXISTS equivalent), - //so we try to create exclusively and fallback to open if already exists, with - //some retries if opening also fails because the file does not exist - //(there is a race, the creator just removed the file after creating it). - // - //We'll put a maximum retry limit just to avoid possible deadlocks, we don't - //want to support pathological use cases. - spin_wait swait; - unsigned tries = 0; - while(1){ - BOOST_TRY{ - create_device(dev, id, size, perm, file_like_t()); - return true; - } - BOOST_CATCH(interprocess_exception &ex){ - #ifndef BOOST_NO_EXCEPTIONS - if(ex.get_error_code() != already_exists_error){ - BOOST_RETHROW - } - else if (++tries == MaxCreateOrOpenTries) { - //File existing when trying to create, but non-existing when - //trying to open, and tried MaxCreateOrOpenTries times. Something fishy - //is happening here and we can't solve it - throw interprocess_exception(error_info(corrupted_error)); - } - else{ - BOOST_TRY{ - DeviceAbstraction tmp(open_only, id, read_write); - dev.swap(tmp); - return false; - } - BOOST_CATCH(interprocess_exception &e){ - if(e.get_error_code() != not_found_error){ - BOOST_RETHROW - } - } - BOOST_CATCH(...){ - BOOST_RETHROW - } BOOST_CATCH_END - } - #endif //#ifndef BOOST_NO_EXCEPTIONS - } - BOOST_CATCH(...){ - BOOST_RETHROW - } BOOST_CATCH_END - swait.yield(); - } - return false; - } - - template - static void do_map_after_create - (DeviceAbstraction &dev, mapped_region &final_region, - std::size_t size, const void *addr, ConstructFunc construct_func) - { - BOOST_TRY{ - //If this throws, we are lost - truncate_device(dev, static_cast(size), file_like_t()); - - //If the following throws, we will truncate the file to 1 - mapped_region region(dev, read_write, 0, 0, addr); - boost::uint32_t *patomic_word = 0; //avoid gcc warning - patomic_word = static_cast(region.get_address()); - boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment); - - if(previous == UninitializedSegment){ - BOOST_TRY{ - construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset - , size - ManagedOpenOrCreateUserOffset, true); - //All ok, just move resources to the external mapped region - final_region.swap(region); - } - BOOST_CATCH(...){ - atomic_write32(patomic_word, CorruptedSegment); - BOOST_RETHROW - } BOOST_CATCH_END - atomic_write32(patomic_word, InitializedSegment); - } - else{ - atomic_write32(patomic_word, CorruptedSegment); - throw interprocess_exception(error_info(corrupted_error)); - } - } - BOOST_CATCH(...){ - BOOST_TRY{ - truncate_device(dev, 1u, file_like_t()); - } - BOOST_CATCH(...){ - } - BOOST_CATCH_END - BOOST_RETHROW - } - BOOST_CATCH_END - } - - template - static void do_map_after_open - ( DeviceAbstraction &dev, mapped_region &final_region - , const void *addr, ConstructFunc construct_func - , bool ronly, bool cow) - { - const usduration TimeoutSec(usduration_from_seconds(MaxInitializeTimeSec)); - - if(FileBased){ - offset_t filesize = 0; - spin_wait swait; - - //If a file device was used, the creator might be truncating the device, so wait - //until the file size is enough to map the initial word - ustime ustime_start = microsec_clock::universal_time(); - - while(1){ - if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - if (filesize != 0) - break; - else { - //More than MaxZeroTruncateTimeSec seconds waiting to the creator - //to minimally increase the size of the file: something bad has happened - const usduration elapsed(microsec_clock::universal_time() - ustime_start); - if (elapsed > TimeoutSec){ - throw interprocess_exception(error_info(corrupted_error)); - } - swait.yield(); - } - } - //The creator detected an error creating the file and signalled it with size 1 - if(filesize == 1){ - throw interprocess_exception(error_info(corrupted_error)); - } - } - - mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr); - - boost::uint32_t *patomic_word = static_cast(region.get_address()); - boost::uint32_t value = atomic_read32(patomic_word); - - if (value != InitializedSegment){ - ustime ustime_start = microsec_clock::universal_time(); - spin_wait swait; - while ((value = atomic_read32(patomic_word)) != InitializedSegment){ - if(value == CorruptedSegment){ - throw interprocess_exception(error_info(corrupted_error)); - } - //More than MaxZeroTruncateTimeSec seconds waiting to the creator - //to minimally increase the size of the file: something bad has happened - const usduration elapsed(microsec_clock::universal_time() - ustime_start); - if (elapsed > TimeoutSec){ - throw interprocess_exception(error_info(corrupted_error)); - } - swait.yield(); - } - //The size of the file might have grown while Uninitialized -> Initializing, so remap - { - mapped_region null_map; - region.swap(null_map); - } - mapped_region final_size_map(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr); - final_size_map.swap(region); - } - construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset - , region.get_size() - ManagedOpenOrCreateUserOffset - , false); - //All ok, just move resources to the external mapped region - final_region.swap(region); - } - - template inline - void priv_open_or_create - (create_enum_t type, - const DeviceId & id, - std::size_t size, - mode_t mode, const void *addr, - const permissions &perm, - ConstructFunc construct_func) - { - if(type != DoOpen){ - //Check if the requested size is enough to build the managed metadata - const std::size_t func_min_size = construct_func.get_min_size(); - if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size || - size < (func_min_size + ManagedOpenOrCreateUserOffset) ){ - throw interprocess_exception(error_info(size_error)); - } - //Check size can be represented by offset_t (used by truncate) - if (!check_offset_t_size(size, file_like_t())){ - throw interprocess_exception(error_info(size_error)); - } - } - - //Now create the device (file, shm file, etc.) - DeviceAbstraction dev; - (void)mode; - bool created = false; - bool ronly = false; - bool cow = false; - if(type == DoOpen){ - DeviceAbstraction tmp(open_only, id, mode == read_write ? read_write : read_only); - tmp.swap(dev); - ronly = mode == read_only; - cow = mode == copy_on_write; - } - else if(type == DoCreate){ - create_device(dev, id, size, perm, file_like_t()); - created = true; - } - else { //DoOpenOrCreate - created = this->do_create_else_open(dev, id, size, perm); - } - - if(created){ - this->do_map_after_create(dev, m_mapped_region, size, addr, construct_func); - } - else{ - this->do_map_after_open(dev, m_mapped_region, addr, construct_func, ronly, cow); - } - - if(StoreDevice){ - this->DevHolder::get_device() = boost::move(dev); - } - } - - template inline - void priv_map_anonymous - (std::size_t size, - void *addr, - ConstructFunc construct_func) - { - mapped_region region = anonymous_shared_memory(size, addr); - - boost::uint32_t *patomic_word = 0; //avoid gcc warning - patomic_word = static_cast(region.get_address()); - boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment); - - if(previous == UninitializedSegment){ - BOOST_TRY{ - construct_func( static_cast(region.get_address()) + ManagedOpenOrCreateUserOffset - , size - ManagedOpenOrCreateUserOffset, true); - //All ok, just move resources to the external mapped region - m_mapped_region.swap(region); - } - BOOST_CATCH(...){ - atomic_write32(patomic_word, CorruptedSegment); - BOOST_RETHROW - } BOOST_CATCH_END - atomic_write32(patomic_word, InitializedSegment); - } - else{ - atomic_write32(patomic_word, CorruptedSegment); - throw interprocess_exception(error_info(corrupted_error)); - } - } - - friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right) - { - left.swap(right); - } - - private: - friend class interprocess_tester; - void dont_close_on_destruction() - { interprocess_tester::dont_close_on_destruction(m_mapped_region); } - - mapped_region m_mapped_region; -}; - -} //namespace ipcdetail { - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL diff --git a/extern/boost/boost/interprocess/detail/math_functions.hpp b/extern/boost/boost/interprocess/detail/math_functions.hpp deleted file mode 100644 index a19efac1a42..00000000000 --- a/extern/boost/boost/interprocess/detail/math_functions.hpp +++ /dev/null @@ -1,118 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Stephen Cleary 2000. -// (C) Copyright Ion Gaztanaga 2007-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. -// -// This file is a slightly modified file from Boost.Pool -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP -#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -// Greatest common divisor and least common multiple - -// -// gcd is an algorithm that calculates the greatest common divisor of two -// integers, using Euclid's algorithm. -// -// Pre: A > 0 && B > 0 -// Recommended: A > B -template -inline Integer gcd(Integer A, Integer B) -{ - do - { - const Integer tmp(B); - B = A % B; - A = tmp; - } while (B != 0); - - return A; -} - -// -// lcm is an algorithm that calculates the least common multiple of two -// integers. -// -// Pre: A > 0 && B > 0 -// Recommended: A > B -template -inline Integer lcm(const Integer & A, const Integer & B) -{ - Integer ret = A; - ret /= gcd(A, B); - ret *= B; - return ret; -} - -template -inline Integer log2_ceil(const Integer & A) -{ - Integer i = 0; - Integer power_of_2 = 1; - - while(power_of_2 < A){ - power_of_2 <<= 1; - ++i; - } - return i; -} - -template -inline Integer upper_power_of_2(const Integer & A) -{ - Integer power_of_2 = 1; - - while(power_of_2 < A){ - power_of_2 <<= 1; - } - return power_of_2; -} - -//This function uses binary search to discover the -//highest set bit of the integer -inline std::size_t floor_log2 (std::size_t x) -{ - const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; - const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); - BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true)); - - std::size_t n = x; - std::size_t log2 = 0; - - for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ - std::size_t tmp = n >> shift; - if (tmp) - log2 += shift, n = tmp; - } - - return log2; -} - -} // namespace ipcdetail -} // namespace interprocess -} // namespace boost - -#endif diff --git a/extern/boost/boost/interprocess/detail/move.hpp b/extern/boost/boost/interprocess/detail/move.hpp deleted file mode 100644 index 3a2c29b051c..00000000000 --- a/extern/boost/boost/interprocess/detail/move.hpp +++ /dev/null @@ -1,36 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2010-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/move for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -//! \file - -#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP -#define BOOST_INTERPROCESS_DETAIL_MOVE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include - -namespace boost { -namespace interprocess { - -using ::boost::move; -using ::boost::forward; - -} //namespace interprocess { -} //namespace boost { - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP diff --git a/extern/boost/boost/interprocess/detail/named_proxy.hpp b/extern/boost/boost/interprocess/detail/named_proxy.hpp deleted file mode 100644 index f8a46d09874..00000000000 --- a/extern/boost/boost/interprocess/detail/named_proxy.hpp +++ /dev/null @@ -1,284 +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_NAMED_PROXY_HPP -#define BOOST_INTERPROCESS_NAMED_PROXY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess/detail -#include -#include -#include -#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING -#include -#else -#include -#include -#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING -#include - -#include - -//!\file -//!Describes a proxy class that implements named allocation syntax. - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING - -template -struct CtorArgN : public placement_destroy -{ - typedef bool_ IsIterator; - typedef CtorArgN self_t; - typedef typename build_number_seq::type index_tuple_t; - - self_t& operator++() - { - this->do_increment(IsIterator(), index_tuple_t()); - return *this; - } - - self_t operator++(int) { return ++*this; *this; } - - CtorArgN(Args && ...args) - : args_(args...) - {} - - virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE - { - std::size_t constructed = 0; - BOOST_TRY{ - T* memory = static_cast(mem); - for(constructed = 0; constructed < num; ++constructed){ - this->construct(memory++, IsIterator(), index_tuple_t()); - this->do_increment(IsIterator(), index_tuple_t()); - } - } - BOOST_CATCH(...) { - this->placement_destroy::destroy_n(mem, constructed); - BOOST_RETHROW - } BOOST_CATCH_END - } - - private: - template - void construct(void *mem, true_, const index_tuple&) - { ::new((void*)mem, boost_container_new_t())T(*boost::forward((get)(args_))...); } - - template - void construct(void *mem, false_, const index_tuple&) - { ::new((void*)mem, boost_container_new_t())T(boost::forward((get)(args_))...); } - - template - void do_increment(true_, const index_tuple&) - { - this->expansion_helper(++(get)(args_)...); - } - - template - void expansion_helper(ExpansionArgs &&...) - {} - - template - void do_increment(false_, const index_tuple&) - {} - - tuple args_; -}; - -//!Describes a proxy class that implements named -//!allocation syntax. -template - < class SegmentManager //segment manager to construct the object - , class T //type of object to build - , bool is_iterator //passing parameters are normal object or iterators? - > -class named_proxy -{ - typedef typename SegmentManager::char_type char_type; - const char_type * mp_name; - SegmentManager * mp_mngr; - mutable std::size_t m_num; - const bool m_find; - const bool m_dothrow; - - public: - named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) - : mp_name(name), mp_mngr(mngr), m_num(1) - , m_find(find), m_dothrow(dothrow) - {} - - template - T *operator()(Args &&...args) const - { - CtorArgN &&ctor_obj = CtorArgN - (boost::forward(args)...); - return mp_mngr->template - generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); - } - - //This operator allows --> named_new("Name")[3]; <-- syntax - const named_proxy &operator[](std::size_t num) const - { m_num *= num; return *this; } -}; - -#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING - -#define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\ -\ -template \ -struct CtorArg##N : placement_destroy\ -{\ - typedef CtorArg##N self_t;\ - \ - CtorArg##N ( BOOST_MOVE_UREF##N )\ - BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\ - \ - virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\ - {\ - std::size_t constructed = 0;\ - BOOST_TRY{\ - T* memory = static_cast(mem);\ - for (constructed = 0; constructed < num; ++constructed) {\ - ::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\ - }\ - }\ - BOOST_CATCH(...) {\ - this->placement_destroy::destroy_n(mem, constructed);\ - BOOST_RETHROW\ - } BOOST_CATCH_END\ - }\ - \ - private:\ - BOOST_MOVE_MREF##N\ -};\ -//! -BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN) -#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN - -#define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\ -\ -template \ -struct CtorIt##N : public placement_destroy\ -{\ - typedef CtorIt##N self_t;\ - \ - self_t& operator++()\ - { BOOST_MOVE_MINC##N; return *this; }\ - \ - self_t operator++(int) { return ++*this; *this; }\ - \ - CtorIt##N ( BOOST_MOVE_VAL##N )\ - BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\ - \ - virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\ - {\ - std::size_t constructed = 0;\ - BOOST_TRY{\ - T* memory = static_cast(mem);\ - for(constructed = 0; constructed < num; ++constructed){\ - ::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\ - ++(*this);\ - }\ - }\ - BOOST_CATCH(...) {\ - this->placement_destroy::destroy_n(mem, constructed);\ - BOOST_RETHROW\ - } BOOST_CATCH_END\ - }\ - \ - private:\ - BOOST_MOVE_MEMB##N\ -};\ -//! -BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN) -#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN - -//!Describes a proxy class that implements named -//!allocation syntax. -template - < class SegmentManager //segment manager to construct the object - , class T //type of object to build - , bool is_iterator //passing parameters are normal object or iterators? - > -class named_proxy -{ - typedef typename SegmentManager::char_type char_type; - const char_type * mp_name; - SegmentManager * mp_mngr; - mutable std::size_t m_num; - const bool m_find; - const bool m_dothrow; - - public: - named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) - : mp_name(name), mp_mngr(mngr), m_num(1) - , m_find(find), m_dothrow(dothrow) - {} - - #define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\ - \ - BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - T *operator()( BOOST_MOVE_UREF##N ) const\ - {\ - typedef typename if_c \ - , CtorArg##N \ - >::type ctor_obj_t;\ - ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\ - return mp_mngr->template generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj);\ - }\ - // - BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR) - #undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR - - //////////////////////////////////////////////////////////////////////// - // What the macro should generate (n == 2) - //////////////////////////////////////////////////////////////////////// - // - // template - // T *operator()(P1 &p1, P2 &p2) const - // { - // typedef CtorArg2 - // - // ctor_obj_t; - // ctor_obj_t ctor_obj(p1, p2); - // - // return mp_mngr->template generic_construct - // (mp_name, m_num, m_find, m_dothrow, ctor_obj); - // } - // - ////////////////////////////////////////////////////////////////////////// - - //This operator allows --> named_new("Name")[3]; <-- syntax - const named_proxy &operator[](std::size_t num) const - { m_num *= num; return *this; } -}; - -#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING - -}}} //namespace boost { namespace interprocess { namespace ipcdetail { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP diff --git a/extern/boost/boost/interprocess/detail/nothrow.hpp b/extern/boost/boost/interprocess/detail/nothrow.hpp deleted file mode 100644 index d79ba7647ec..00000000000 --- a/extern/boost/boost/interprocess/detail/nothrow.hpp +++ /dev/null @@ -1,42 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2014-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/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP -#define BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -namespace std { //no namespace versioning in clang+libc++ - -struct nothrow_t; - -} //namespace std { - -namespace boost{ namespace interprocess { - -template -struct nothrow -{ - static const std::nothrow_t &get() { return *pnothrow; } - static std::nothrow_t *pnothrow; -}; - -template -std::nothrow_t *nothrow::pnothrow = - reinterpret_cast(0x1234); //Avoid sanitizer warnings on references to null - -}} //namespace boost{ namespace interprocess { - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NOTHROW_HPP diff --git a/extern/boost/boost/interprocess/detail/pointer_type.hpp b/extern/boost/boost/interprocess/detail/pointer_type.hpp deleted file mode 100644 index 125858653e4..00000000000 --- a/extern/boost/boost/interprocess/detail/pointer_type.hpp +++ /dev/null @@ -1,78 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005-2012. -// (C) Copyright Gennaro Prota 2003 - 2004. -// -// 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_POINTER_TYPE_HPP -#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -struct two {char _[2];}; - -namespace pointer_type_imp { - -template static two test(...); -template static char test(typename U::pointer* = 0); - -} //namespace pointer_type_imp { - -template -struct has_pointer_type -{ - static const bool value = sizeof(pointer_type_imp::test(0)) == 1; -}; - -namespace pointer_type_imp { - -template ::value> -struct pointer_type -{ - typedef typename D::pointer type; -}; - -template -struct pointer_type -{ - typedef T* type; -}; - -} //namespace pointer_type_imp { - -template -struct pointer_type -{ - typedef typename pointer_type_imp::pointer_type::type>::type type; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP - diff --git a/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp b/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp deleted file mode 100644 index 32e196a6f65..00000000000 --- a/extern/boost/boost/interprocess/detail/portable_intermodule_singleton.hpp +++ /dev/null @@ -1,361 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_PORTABLE_INTERMODULE_SINGLETON_HPP -#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -typedef basic_managed_global_memory managed_global_memory; - -namespace intermodule_singleton_helpers { - -static void create_tmp_subdir_and_get_pid_based_filepath - (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false) -{ - //Let's create a lock file for each process gmem that will mark if - //the process is alive or not - create_shared_dir_and_clean_old(s); - s += "/"; - s += subdir_name; - if(!open_or_create_shared_directory(s.c_str())){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - s += "/"; - s += file_prefix; - if(creation_time){ - std::string sstamp; - get_pid_creation_time_str(sstamp); - s += sstamp; - } - else{ - pid_str_t pid_str; - get_pid_str(pid_str, pid); - s += pid_str; - } -} - -static bool check_if_filename_complies_with_pid - (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false) -{ - //Check if filename complies with lock file name pattern - std::string fname(filename); - std::string fprefix(prefix); - if(fname.size() <= fprefix.size()){ - return false; - } - fname.resize(fprefix.size()); - if(fname != fprefix){ - return false; - } - - //If not our lock file, delete it if we can lock it - fname = filename; - fname.erase(0, fprefix.size()); - pid_str_t pid_str; - get_pid_str(pid_str, pid); - file_suffix = pid_str; - if(creation_time){ - std::size_t p = fname.find('_'); - if (p == std::string::npos){ - return false; - } - std::string save_suffix(fname); - fname.erase(p); - fname.swap(file_suffix); - bool ret = (file_suffix == fname); - file_suffix.swap(save_suffix); - return ret; - } - else{ - fname.swap(file_suffix); - return (file_suffix == fname); - } -} - -template<> -struct thread_safe_global_map_dependant -{ - private: - static const int GMemMarkToBeRemoved = -1; - static const int GMemNotPresent = -2; - - static const char *get_lock_file_subdir_name() - { return "gmem"; } - - static const char *get_lock_file_base_name() - { return "lck"; } - - static void create_and_get_singleton_lock_file_path(std::string &s) - { - create_tmp_subdir_and_get_pid_based_filepath - (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true); - } - - struct gmem_erase_func - { - gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm) - :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm) - {} - - void operator()() - { - locking_file_serial_id *pserial_id = shm_.find("lock_file_fd").first; - if(pserial_id){ - pserial_id->fd = GMemMarkToBeRemoved; - } - delete_file(singleton_lock_file_path_); - shared_memory_object::remove(shm_name_); - } - - const char * const shm_name_; - const char * const singleton_lock_file_path_; - managed_global_memory & shm_; - }; - - //This function applies shared memory erasure logic based on the passed lock file. - static void apply_gmem_erase_logic(const char *filepath, const char *filename) - { - int fd = GMemMarkToBeRemoved; - BOOST_TRY{ - std::string str; - //If the filename is current process lock file, then avoid it - if(check_if_filename_complies_with_pid - (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){ - return; - } - //Open and lock the other process' lock file - fd = try_open_and_lock_file(filepath); - if(fd < 0){ - return; - } - //If done, then the process is dead so take global shared memory name - //(the name is based on the lock file name) and try to apply erasure logic - str.insert(0, get_map_base_name()); - BOOST_TRY{ - managed_global_memory shm(open_only, str.c_str()); - gmem_erase_func func(str.c_str(), filepath, shm); - shm.try_atomic_func(func); - } - BOOST_CATCH(interprocess_exception &e){ - //If shared memory is not found erase the lock file - if(e.get_error_code() == not_found_error){ - delete_file(filepath); - } - } BOOST_CATCH_END - } - BOOST_CATCH(...){ - - } BOOST_CATCH_END - if(fd >= 0){ - close_lock_file(fd); - } - } - - public: - - static bool remove_old_gmem() - { - std::string refcstrRootDirectory; - get_shared_dir(refcstrRootDirectory); - refcstrRootDirectory += "/"; - refcstrRootDirectory += get_lock_file_subdir_name(); - return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); - } - - struct lock_file_logic - { - lock_file_logic(managed_global_memory &shm) - : mshm(shm) - { shm.atomic_func(*this); } - - void operator()(void) - { - retry_with_new_map = false; - - //First find the file locking descriptor id - locking_file_serial_id *pserial_id = - mshm.find("lock_file_fd").first; - - int fd; - //If not found schedule a creation - if(!pserial_id){ - fd = GMemNotPresent; - } - //Else get it - else{ - fd = pserial_id->fd; - } - //If we need to create a new one, do it - if(fd == GMemNotPresent){ - std::string lck_str; - //Create a unique current pid based lock file path - create_and_get_singleton_lock_file_path(lck_str); - //Open or create and lock file - int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str()); - //If failed, write a bad file descriptor to notify other modules that - //something was wrong and unlink shared memory. Mark the function object - //to tell caller to retry with another shared memory - if(fd_lockfile < 0){ - this->register_lock_file(GMemMarkToBeRemoved); - std::string s; - get_map_name(s); - shared_memory_object::remove(s.c_str()); - retry_with_new_map = true; - } - //If successful, register the file descriptor - else{ - this->register_lock_file(fd_lockfile); - } - } - //If the fd was invalid (maybe a previous try failed) notify caller that - //should retry creation logic, since this shm might have been already - //unlinked since the shm was removed - else if (fd == GMemMarkToBeRemoved){ - retry_with_new_map = true; - } - //If the stored fd is not valid (a open fd, a normal file with the - //expected size, or does not have the same file id number, - //then it's an old shm from an old process with the same pid. - //If that's the case, mark it as invalid - else if(!is_valid_fd(fd) || - !is_normal_file(fd) || - 0 != get_size(fd) || - !compare_file_serial(fd, *pserial_id)){ - pserial_id->fd = GMemMarkToBeRemoved; - std::string s; - get_map_name(s); - shared_memory_object::remove(s.c_str()); - retry_with_new_map = true; - } - else{ - //If the lock file is ok, increment reference count of - //attached modules to shared memory - atomic_inc32(&pserial_id->modules_attached_to_gmem_count); - } - } - - bool retry() const { return retry_with_new_map; } - - private: - locking_file_serial_id * register_lock_file(int fd) - { - locking_file_serial_id *pinfo = mshm.construct("lock_file_fd")(); - fill_file_serial_id(fd, *pinfo); - return pinfo; - } - - managed_global_memory &mshm; - bool retry_with_new_map; - }; - - static void construct_map(void *addr) - { - std::string s; - intermodule_singleton_helpers::get_map_name(s); - const char *MapName = s.c_str(); - const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();; - ::new (addr)managed_global_memory(open_or_create, MapName, MapSize); - } - - struct unlink_map_logic - { - unlink_map_logic(managed_global_memory &mshm) - : mshm_(mshm) - { mshm.atomic_func(*this); } - - void operator()() - { - locking_file_serial_id *pserial_id = - mshm_.find - ("lock_file_fd").first; - BOOST_ASSERT(0 != pserial_id); - if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){ - int fd = pserial_id->fd; - if(fd > 0){ - pserial_id->fd = GMemMarkToBeRemoved; - std::string s; - create_and_get_singleton_lock_file_path(s); - delete_file(s.c_str()); - close_lock_file(fd); - intermodule_singleton_helpers::get_map_name(s); - shared_memory_object::remove(s.c_str()); - } - } - } - - private: - managed_global_memory &mshm_; - }; - - static ref_count_ptr *find(managed_global_memory &map, const char *name) - { - return map.find(name).first; - } - - static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref) - { - return map.construct(name)(ref); - } - - static bool erase(managed_global_memory &map, const char *name) - { - return map.destroy(name); - } - - template - static void atomic_func(managed_global_memory &map, F &f) - { - map.atomic_func(f); - } -}; - -} //namespace intermodule_singleton_helpers { - -template -class portable_intermodule_singleton - : public intermodule_singleton_impl -{}; - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif //#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP diff --git a/extern/boost/boost/interprocess/detail/robust_emulation.hpp b/extern/boost/boost/interprocess/detail/robust_emulation.hpp deleted file mode 100644 index 707782df5fb..00000000000 --- a/extern/boost/boost/interprocess/detail/robust_emulation.hpp +++ /dev/null @@ -1,387 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2010-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_ROBUST_EMULATION_HPP -#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost{ -namespace interprocess{ -namespace ipcdetail{ - -namespace robust_emulation_helpers { - -template -class mutex_traits -{ - public: - static void take_ownership(T &t) - { t.take_ownership(); } -}; - -inline void remove_if_can_lock_file(const char *file_path) -{ - file_handle_t fhnd = open_existing_file(file_path, read_write); - - if(fhnd != invalid_file()){ - bool acquired; - if(try_acquire_file_lock(fhnd, acquired) && acquired){ - delete_file(file_path); - } - close_file(fhnd); - } -} - -inline const char *robust_lock_subdir_path() -{ return "robust"; } - -inline const char *robust_lock_prefix() -{ return "lck"; } - -inline void robust_lock_path(std::string &s) -{ - get_shared_dir(s); - s += "/"; - s += robust_lock_subdir_path(); -} - -inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid) -{ - intermodule_singleton_helpers::create_tmp_subdir_and_get_pid_based_filepath - (robust_lock_subdir_path(), robust_lock_prefix(), pid, s); -} - -//This class will be a intermodule_singleton. The constructor will create -//a lock file, the destructor will erase it. -// -//We should take in care that another process might be erasing unlocked -//files while creating this one, so there are some race conditions we must -//take in care to guarantee some robustness. -class robust_mutex_lock_file -{ - file_handle_t fd; - std::string fname; - public: - robust_mutex_lock_file() - { - permissions p; - p.set_unrestricted(); - //Remove old lock files of other processes - remove_old_robust_lock_files(); - //Create path and obtain lock file path for this process - create_and_get_robust_lock_file_path(fname, get_current_process_id()); - - //Now try to open or create the lock file - fd = create_or_open_file(fname.c_str(), read_write, p); - //If we can't open or create it, then something unrecoverable has happened - if(fd == invalid_file()){ - throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file"); - } - - //Now we must take in care a race condition with another process - //calling "remove_old_robust_lock_files()". No other threads from this - //process will be creating the lock file because intermodule_singleton - //guarantees this. So let's loop acquiring the lock and checking if we - //can't exclusively create the file (if the file is erased by another process - //then this exclusive open would fail). If the file can't be exclusively created - //then we have correctly open/create and lock the file. If the file can - //be exclusively created, then close previous locked file and try again. - while(1){ - bool acquired; - if(!try_acquire_file_lock(fd, acquired) || !acquired ){ - throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock"); - } - //Creating exclusively must fail with already_exists_error - //to make sure we've locked the file and no one has - //deleted it between creation and locking - file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p); - if(fd2 != invalid_file()){ - close_file(fd); - fd = fd2; - continue; - } - //If exclusive creation fails with expected error go ahead - else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist - //Leak descriptor to mantain the file locked until the process dies - break; - } - //If exclusive creation fails with unexpected error throw an unrecoverable error - else{ - close_file(fd); - throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error"); - } - } - } - - ~robust_mutex_lock_file() - { - //The destructor is guaranteed by intermodule_singleton to be - //executed serialized between all threads from current process, - //so we just need to close and unlink the file. - close_file(fd); - //If some other process deletes the file before us after - //closing it there should not be any problem. - delete_file(fname.c_str()); - } - - private: - //This functor is execute for all files in the lock file directory - class other_process_lock_remover - { - public: - void operator()(const char *filepath, const char *filename) - { - std::string pid_str; - //If the lock file is not our own lock file, then try to do the cleanup - if(!intermodule_singleton_helpers::check_if_filename_complies_with_pid - (filename, robust_lock_prefix(), get_current_process_id(), pid_str)){ - remove_if_can_lock_file(filepath); - } - } - }; - - bool remove_old_robust_lock_files() - { - std::string refcstrRootDirectory; - robust_lock_path(refcstrRootDirectory); - return for_each_file_in_dir(refcstrRootDirectory.c_str(), other_process_lock_remover()); - } -}; - -} //namespace robust_emulation_helpers { - -//This is the mutex class. Mutex should follow mutex concept -//with an additonal "take_ownership()" function to take ownership of the -//mutex when robust_spin_mutex determines the previous owner was dead. -template -class robust_spin_mutex -{ - public: - static const boost::uint32_t correct_state = 0; - static const boost::uint32_t fixing_state = 1; - static const boost::uint32_t broken_state = 2; - - typedef robust_emulation_helpers::mutex_traits mutex_traits_t; - - robust_spin_mutex(); - void lock(); - bool try_lock(); - template - bool timed_lock(const TimePoint &abs_time); - void unlock(); - void consistent(); - bool previous_owner_dead(); - - private: - static const unsigned int spin_threshold = 100u; - bool lock_own_unique_file(); - bool robust_check(); - bool check_if_owner_dead_and_take_ownership_atomically(); - bool is_owner_dead(boost::uint32_t own); - void owner_to_filename(boost::uint32_t own, std::string &s); - //The real mutex - Mutex mtx; - //The pid of the owner - volatile boost::uint32_t owner; - //The state of the mutex (correct, fixing, broken) - volatile boost::uint32_t state; -}; - -template -inline robust_spin_mutex::robust_spin_mutex() - : mtx(), owner((boost::uint32_t)get_invalid_process_id()), state(correct_state) -{} - -template -inline void robust_spin_mutex::lock() -{ try_based_lock(*this); } - -template -inline bool robust_spin_mutex::try_lock() -{ - //Same as lock() but without spinning - if(atomic_read32(&this->state) == broken_state){ - throw interprocess_exception(lock_error, "Broken id"); - } - - if(!this->lock_own_unique_file()){ - throw interprocess_exception(lock_error, "Broken id"); - } - - if (mtx.try_lock()){ - atomic_write32(&this->owner, static_cast(get_current_process_id())); - return true; - } - else{ - if(!this->robust_check()){ - return false; - } - else{ - return true; - } - } -} - -template -template -inline bool robust_spin_mutex::timed_lock - (const TimePoint &abs_time) -{ return try_based_timed_lock(*this, abs_time); } - -template -inline void robust_spin_mutex::owner_to_filename(boost::uint32_t own, std::string &s) -{ - robust_emulation_helpers::create_and_get_robust_lock_file_path(s, (OS_process_id_t)own); -} - -template -inline bool robust_spin_mutex::robust_check() -{ - //If the old owner was dead, and we've acquired ownership, mark - //the mutex as 'fixing'. This means that a "consistent()" is needed - //to avoid marking the mutex as "broken" when the mutex is unlocked. - if(!this->check_if_owner_dead_and_take_ownership_atomically()){ - return false; - } - atomic_write32(&this->state, fixing_state); - return true; -} - -template -inline bool robust_spin_mutex::check_if_owner_dead_and_take_ownership_atomically() -{ - boost::uint32_t cur_owner = static_cast(get_current_process_id()); - boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2; - //The cas loop guarantees that only one thread from this or another process - //will succeed taking ownership - do{ - //Check if owner is dead - if(!this->is_owner_dead(old_owner)){ - return false; - } - //If it's dead, try to mark this process as the owner in the owner field - old_owner2 = old_owner; - old_owner = atomic_cas32(&this->owner, cur_owner, old_owner); - }while(old_owner2 != old_owner); - //If success, we fix mutex internals to assure our ownership - mutex_traits_t::take_ownership(mtx); - return true; -} - -template -inline bool robust_spin_mutex::is_owner_dead(boost::uint32_t own) -{ - //If owner is an invalid id, then it's clear it's dead - if(own == static_cast(get_invalid_process_id())){ - return true; - } - - //Obtain the lock filename of the owner field - std::string file; - this->owner_to_filename(own, file); - - //Now the logic is to open and lock it - file_handle_t fhnd = open_existing_file(file.c_str(), read_write); - - if(fhnd != invalid_file()){ - //If we can open the file, lock it. - bool acquired; - if(try_acquire_file_lock(fhnd, acquired) && acquired){ - //If locked, just delete the file - delete_file(file.c_str()); - close_file(fhnd); - return true; - } - //If not locked, the owner is suppossed to be still alive - close_file(fhnd); - } - else{ - //If the lock file does not exist then the owner is dead (a previous cleanup) - //function has deleted the file. If there is another reason, then this is - //an unrecoverable error - if(error_info(system_error_code()).get_error_code() == not_found_error){ - return true; - } - } - return false; -} - -template -inline void robust_spin_mutex::consistent() -{ - //This function supposes the previous state was "fixing" - //and the current process holds the mutex - if(atomic_read32(&this->state) != fixing_state && - atomic_read32(&this->owner) != (boost::uint32_t)get_current_process_id()){ - throw interprocess_exception(lock_error, "Broken id"); - } - //If that's the case, just update mutex state - atomic_write32(&this->state, correct_state); -} - -template -inline bool robust_spin_mutex::previous_owner_dead() -{ - //Notifies if a owner recovery has been performed in the last lock() - return atomic_read32(&this->state) == fixing_state; -} - -template -inline void robust_spin_mutex::unlock() -{ - //If in "fixing" state, unlock and mark the mutex as unrecoverable - //so next locks will fail and all threads will be notified that the - //data protected by the mutex was not recoverable. - if(atomic_read32(&this->state) == fixing_state){ - atomic_write32(&this->state, broken_state); - } - //Write an invalid owner to minimize pid reuse possibility - atomic_write32(&this->owner, static_cast(get_invalid_process_id())); - mtx.unlock(); -} - -template -inline bool robust_spin_mutex::lock_own_unique_file() -{ - //This function forces instantiation of the singleton - robust_emulation_helpers::robust_mutex_lock_file* dummy = - &ipcdetail::intermodule_singleton - ::get(); - return dummy != 0; -} - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif diff --git a/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp b/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp deleted file mode 100644 index f943cf7363f..00000000000 --- a/extern/boost/boost/interprocess/detail/segment_manager_helper.hpp +++ /dev/null @@ -1,503 +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_SEGMENT_MANAGER_BASE_HPP -#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess -#include -// interprocess/detail -#include -#include -#include -// container/detail -#include //alignment_of -#include -// intrusive -#include -// move/detail -#include //make_unsigned -#include -// other boost -#include //BOOST_ASSERT -#include -// std -#include //std::size_t - -//!\file -//!Describes the object placed in a memory segment that provides -//!named object allocation capabilities. - -namespace boost{ -namespace interprocess{ - -template -class segment_manager_base; - -//!An integer that describes the type of the -//!instance constructed in memory -enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type }; - -namespace ipcdetail{ - -template -class mem_algo_deallocator -{ - void * m_ptr; - MemoryAlgorithm & m_algo; - - public: - mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo) - : m_ptr(ptr), m_algo(algo) - {} - - void release() - { m_ptr = 0; } - - ~mem_algo_deallocator() - { if(m_ptr) m_algo.deallocate(m_ptr); } -}; - -template -struct block_header -{ - size_type m_value_bytes; - unsigned short m_num_char; - unsigned char m_value_alignment; - unsigned char m_alloc_type_sizeof_char; - - block_header(size_type val_bytes - ,size_type val_alignment - ,unsigned char al_type - ,std::size_t szof_char - ,std::size_t num_char - ) - : m_value_bytes(val_bytes) - , m_num_char((unsigned short)num_char) - , m_value_alignment((unsigned char)val_alignment) - , m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) ) - {}; - - template - block_header &operator= (const T& ) - { return *this; } - - size_type total_size() const - { - if(alloc_type() != anonymous_type){ - return name_offset() + (m_num_char+1u)*sizeof_char(); - } - else{ - return this->value_offset() + m_value_bytes; - } - } - - size_type value_bytes() const - { return m_value_bytes; } - - template - size_type total_size_with_header() const - { - return get_rounded_size - ( size_type(sizeof(Header)) - , size_type(::boost::container::dtl::alignment_of >::value)) - + total_size(); - } - - unsigned char alloc_type() const - { return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; } - - unsigned char sizeof_char() const - { return m_alloc_type_sizeof_char & (unsigned char)0x1F; } - - template - CharType *name() const - { - return const_cast(move_detail::force_ptr - (reinterpret_cast(this) + name_offset())); - } - - unsigned short name_length() const - { return m_num_char; } - - size_type name_offset() const - { - return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char())); - } - - void *value() const - { - return const_cast((reinterpret_cast(this) + this->value_offset())); - } - - size_type value_offset() const - { - return get_rounded_size(size_type(sizeof(block_header)), size_type(m_value_alignment)); - } - - template - bool less_comp(const block_header &b) const - { - return m_num_char < b.m_num_char || - (m_num_char < b.m_num_char && - std::char_traits::compare(name(), b.name(), m_num_char) < 0); - } - - template - bool equal_comp(const block_header &b) const - { - return m_num_char == b.m_num_char && - std::char_traits::compare(name(), b.name(), m_num_char) == 0; - } - - template - static block_header *block_header_from_value(T *value) - { return block_header_from_value(value, sizeof(T), ::boost::container::dtl::alignment_of::value); } - - static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) - { - block_header * hdr = - const_cast - (move_detail::force_ptr(reinterpret_cast(value) - - get_rounded_size(sizeof(block_header), algn))); - (void)sz; - //Some sanity checks - BOOST_ASSERT(hdr->m_value_alignment == algn); - BOOST_ASSERT(hdr->m_value_bytes % sz == 0); - return hdr; - } - - template - static block_header *from_first_header(Header *header) - { - block_header * hdr = - move_detail::force_ptr*>(reinterpret_cast(header) + - get_rounded_size( size_type(sizeof(Header)) - , size_type(::boost::container::dtl::alignment_of >::value))); - //Some sanity checks - return hdr; - } - - template - static Header *to_first_header(block_header *bheader) - { - Header * hdr = - move_detail::force_ptr(reinterpret_cast(bheader) - - get_rounded_size( size_type(sizeof(Header)) - , size_type(::boost::container::dtl::alignment_of >::value))); - //Some sanity checks - return hdr; - } -}; - -template -struct intrusive_compare_key -{ - typedef CharT char_type; - - intrusive_compare_key(const CharT *str, std::size_t len) - : mp_str(str), m_len(len) - {} - - const CharT * mp_str; - std::size_t m_len; -}; - -//!This struct indicates an anonymous object creation -//!allocation -template -class instance_t -{ - instance_t(){} -}; - -template -struct char_if_void -{ - typedef T type; -}; - -template<> -struct char_if_void -{ - typedef char type; -}; - -typedef instance_t anonymous_instance_t; -typedef instance_t unique_instance_t; - - -template -struct intrusive_value_type_impl - : public Hook -{ - private: - //Non-copyable - intrusive_value_type_impl(const intrusive_value_type_impl &); - intrusive_value_type_impl& operator=(const intrusive_value_type_impl &); - - public: - typedef CharType char_type; - typedef SizeType size_type; - - intrusive_value_type_impl(){} - - enum { BlockHdrAlignment = ::boost::container::dtl::alignment_of >::value }; - - block_header *get_block_header() const - { - return const_cast*> - (move_detail::force_ptr *>(reinterpret_cast(this) + - get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment)))); - } - - bool operator <(const intrusive_value_type_impl & other) const - { return (this->get_block_header())->template less_comp(*other.get_block_header()); } - - bool operator ==(const intrusive_value_type_impl & other) const - { return (this->get_block_header())->template equal_comp(*other.get_block_header()); } - - static intrusive_value_type_impl *get_intrusive_value_type(block_header *hdr) - { - return move_detail::force_ptr(reinterpret_cast(hdr) - - get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment))); - } - - CharType *name() const - { return get_block_header()->template name(); } - - unsigned short name_length() const - { return get_block_header()->name_length(); } - - void *value() const - { return get_block_header()->value(); } -}; - -template -class char_ptr_holder -{ - public: - char_ptr_holder(const CharType *name) - : m_name(name) - {} - - char_ptr_holder(const anonymous_instance_t *) - : m_name(static_cast(0)) - {} - - char_ptr_holder(const unique_instance_t *) - : m_name(reinterpret_cast(-1)) - {} - - operator const CharType *() - { return m_name; } - - const CharType *get() const - { return m_name; } - - bool is_unique() const - { return m_name == reinterpret_cast(-1); } - - bool is_anonymous() const - { return m_name == static_cast(0); } - - private: - const CharType *m_name; -}; - -//!The key of the the named allocation information index. Stores an offset pointer -//!to a null terminated string and the length of the string to speed up sorting -template -struct index_key -{ - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_char_ptr_t; - typedef CharT char_type; - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::move_detail::make_unsigned::type size_type; - - private: - //Offset pointer to the object's name - const_char_ptr_t mp_str; - //Length of the name buffer (null NOT included) - size_type m_len; - public: - - //!Constructor of the key - index_key (const char_type *nm, size_type length) - : mp_str(nm), m_len(length) - {} - - //!Less than function for index ordering - bool operator < (const index_key & right) const - { - return (m_len < right.m_len) || - (m_len == right.m_len && - std::char_traits::compare - (to_raw_pointer(mp_str),to_raw_pointer(right.mp_str), m_len) < 0); - } - - //!Equal to function for index ordering - bool operator == (const index_key & right) const - { - return m_len == right.m_len && - std::char_traits::compare - (to_raw_pointer(mp_str), to_raw_pointer(right.mp_str), m_len) == 0; - } - - void name(const CharT *nm) - { mp_str = nm; } - - void name_length(size_type len) - { m_len = len; } - - const CharT *name() const - { return to_raw_pointer(mp_str); } - - size_type name_length() const - { return m_len; } -}; - -//!The index_data stores a pointer to a buffer and the element count needed -//!to know how many destructors must be called when calling destroy -template -struct index_data -{ - typedef VoidPointer void_pointer; - void_pointer m_ptr; - explicit index_data(void *ptr) : m_ptr(ptr){} - - void *value() const - { return static_cast(to_raw_pointer(m_ptr)); } -}; - -template -struct segment_manager_base_type -{ typedef segment_manager_base type; }; - -template -struct index_config -{ - typedef typename MemoryAlgorithm::void_pointer void_pointer; - typedef CharT char_type; - typedef index_key key_type; - typedef index_data mapped_type; - typedef typename segment_manager_base_type - ::type segment_manager_base; - - template - struct intrusive_value_type - { typedef intrusive_value_type_impl type; }; - - typedef intrusive_compare_key intrusive_compare_key_type; -}; - -template -class segment_manager_iterator_value_adaptor -{ - typedef typename Iterator::value_type iterator_val_t; - typedef typename iterator_val_t::char_type char_type; - - public: - segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) - : m_val(&val) - {} - - const char_type *name() const - { return m_val->name(); } - - unsigned short name_length() const - { return m_val->name_length(); } - - const void *value() const - { return m_val->value(); } - - const typename Iterator::value_type *m_val; -}; - - -template -class segment_manager_iterator_value_adaptor -{ - typedef typename Iterator::value_type iterator_val_t; - typedef typename iterator_val_t::first_type first_type; - typedef typename iterator_val_t::second_type second_type; - typedef typename first_type::char_type char_type; - typedef typename first_type::size_type size_type; - - public: - segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) - : m_val(&val) - {} - - const char_type *name() const - { return m_val->first.name(); } - - size_type name_length() const - { return m_val->first.name_length(); } - - const void *value() const - { - return move_detail::force_ptr*> - (to_raw_pointer(m_val->second.m_ptr))->value(); - } - - const typename Iterator::value_type *m_val; -}; - -template -struct segment_manager_iterator_transform -{ - typedef segment_manager_iterator_value_adaptor result_type; - - template result_type operator()(const T &arg) const - { return result_type(arg); } -}; - -} //namespace ipcdetail { - -//These pointers are the ones the user will use to -//indicate previous allocation types -static const ipcdetail::anonymous_instance_t * anonymous_instance = 0; -static const ipcdetail::unique_instance_t * unique_instance = 0; - -namespace ipcdetail_really_deep_namespace { - -//Otherwise, gcc issues a warning of previously defined -//anonymous_instance and unique_instance -struct dummy -{ - dummy() - { - (void)anonymous_instance; - (void)unique_instance; - } -}; - -} //detail_really_deep_namespace - -}} //namespace boost { namespace interprocess - -#include - -#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP - diff --git a/extern/boost/boost/interprocess/detail/transform_iterator.hpp b/extern/boost/boost/interprocess/detail/transform_iterator.hpp deleted file mode 100644 index d409b523622..00000000000 --- a/extern/boost/boost/interprocess/detail/transform_iterator.hpp +++ /dev/null @@ -1,44 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005-2015. -// (C) Copyright Gennaro Prota 2003 - 2004. -// -// 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_TRANSFORM_ITERATORS_HPP -#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess -#include -// container/detail -#include - -namespace boost { -namespace interprocess { - -using boost::container::make_transform_iterator; -using boost::container::transform_iterator; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP diff --git a/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp b/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp deleted file mode 100644 index 936f702bc26..00000000000 --- a/extern/boost/boost/interprocess/detail/variadic_templates_tools.hpp +++ /dev/null @@ -1,35 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_VARIADIC_TEMPLATES_TOOLS_HPP -#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -using boost::container::dtl::tuple; -using boost::container::dtl::build_number_seq; -using boost::container::dtl::index_tuple; -using boost::container::dtl::get; - -}}} //namespace boost { namespace interprocess { namespace ipcdetail { - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP diff --git a/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp deleted file mode 100644 index b1fe449281e..00000000000 --- a/extern/boost/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp +++ /dev/null @@ -1,88 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP -#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) -#error "This header can't be used in operating systems without XSI (System V) shared memory support" -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - -//!\file -//!Describes a class representing a pseudo-file implemented on top of xsi shared memory. - -namespace boost { -namespace interprocess { - -class xsi_shared_memory_file_wrapper - : public xsi_shared_memory -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} - - xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) - : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions()) - {} - - xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) - : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions()) - {} - - xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t, const permissions& = permissions()) - : xsi_shared_memory(open_only_t(), key) - {} - - xsi_shared_memory_file_wrapper(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) - { this->swap(moved); } - - xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) - { - xsi_shared_memory_file_wrapper tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps two xsi_shared_memory_file_wrapper. Does not throw - void swap(xsi_shared_memory_file_wrapper &other) - { this->xsi_shared_memory::swap(other); } -}; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/file_mapping.hpp b/extern/boost/boost/interprocess/file_mapping.hpp deleted file mode 100644 index 88268fa0ef0..00000000000 --- a/extern/boost/boost/interprocess/file_mapping.hpp +++ /dev/null @@ -1,250 +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_FILE_MAPPING_HPP -#define BOOST_INTERPROCESS_FILE_MAPPING_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#if !defined(BOOST_INTERPROCESS_MAPPED_FILES) -#error "Boost.Interprocess: This platform does not support memory mapped files!" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes file_mapping and mapped region classes - -namespace boost { -namespace interprocess { - -//!A class that wraps a file-mapping that can be used to -//!create mapped regions from the mapped files -class file_mapping -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructs an empty file mapping. - //!Does not throw - file_mapping() BOOST_NOEXCEPT; - - //!Opens a file mapping of file "filename", starting in offset - //!"file_offset", and the mapping's size will be "size". The mapping - //!can be opened for read-only "read_only" or read-write "read_write" - //!modes. Throws interprocess_exception on error. - file_mapping(const char *filename, mode_t mode); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Opens a file mapping of file "filename", starting in offset - //!"file_offset", and the mapping's size will be "size". The mapping - //!can be opened for read-only "read_only" or read-write "read_write" - //!modes. Throws interprocess_exception on error. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - file_mapping(const wchar_t *filename, mode_t mode); - #endif - - //!Moves the ownership of "moved"'s file mapping object to *this. - //!After the call, "moved" does not represent any file mapping object. - //!Does not throw - file_mapping(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT - : m_handle(file_handle_t(ipcdetail::invalid_file())) - , m_mode(read_only) - { this->swap(moved); } - - //!Moves the ownership of "moved"'s file mapping to *this. - //!After the call, "moved" does not represent any file mapping. - //!Does not throw - file_mapping &operator=(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT - { - file_mapping tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps to file_mappings. - //!Does not throw. - void swap(file_mapping &other) BOOST_NOEXCEPT; - - //!Returns access mode - //!used in the constructor - mode_t get_mode() const BOOST_NOEXCEPT; - - //!Obtains the mapping handle - //!to be used with mapped_region - mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; - - //!Destroys the file mapping. All mapped regions created from this are still - //!valid. Does not throw - ~file_mapping(); - - //!Returns the name of the file - //!used in the constructor. - const char *get_name() const BOOST_NOEXCEPT; - - //!Removes the file named "filename" even if it's been memory mapped. - //!Returns true on success. - //!The function might fail in some operating systems if the file is - //!being used other processes and no deletion permission was shared. - static bool remove(const char *filename); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Removes the file named "filename" even if it's been memory mapped. - //!Returns true on success. - //!The function might fail in some operating systems if the file is - //!being used other processes and no deletion permission was shared. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - static bool remove(const wchar_t *filename); - #endif - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - //!Closes a previously opened file mapping. Never throws. - void priv_close(); - file_handle_t m_handle; - mode_t m_mode; - char_wchar_holder m_filename; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline file_mapping::file_mapping() BOOST_NOEXCEPT - : m_handle(file_handle_t(ipcdetail::invalid_file())) - , m_mode(read_only) -{} - -inline file_mapping::~file_mapping() -{ this->priv_close(); } - -inline const char *file_mapping::get_name() const BOOST_NOEXCEPT -{ return m_filename.getn(); } - -inline void file_mapping::swap(file_mapping &other) BOOST_NOEXCEPT -{ - (simple_swap)(m_handle, other.m_handle); - (simple_swap)(m_mode, other.m_mode); - m_filename.swap(other.m_filename); -} - -inline mapping_handle_t file_mapping::get_mapping_handle() const BOOST_NOEXCEPT -{ return ipcdetail::mapping_handle_from_file_handle(m_handle); } - -inline mode_t file_mapping::get_mode() const BOOST_NOEXCEPT -{ return m_mode; } - -inline file_mapping::file_mapping - (const char *filename, mode_t mode) - : m_filename(filename) -{ - //Check accesses - if (mode != read_write && mode != read_only){ - error_info err = other_error; - throw interprocess_exception(err); - } - - //Open file - m_handle = ipcdetail::open_existing_file(filename, mode); - - //Check for error - if(m_handle == ipcdetail::invalid_file()){ - error_info err = system_error_code(); - this->priv_close(); - throw interprocess_exception(err); - } - m_mode = mode; -} - -inline bool file_mapping::remove(const char *filename) -{ return ipcdetail::delete_file(filename); } - -#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES -inline file_mapping::file_mapping - (const wchar_t *filename, mode_t mode) - : m_filename(filename) -{ - //Check accesses - if (mode != read_write && mode != read_only){ - error_info err = other_error; - throw interprocess_exception(err); - } - - //Open file - m_handle = ipcdetail::open_existing_file(filename, mode); - - //Check for error - if(m_handle == ipcdetail::invalid_file()){ - error_info err = system_error_code(); - this->priv_close(); - throw interprocess_exception(err); - } - m_mode = mode; -} - -inline bool file_mapping::remove(const wchar_t *filename) -{ return ipcdetail::delete_file(filename); } - -#endif - - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void file_mapping::priv_close() -{ - if(m_handle != ipcdetail::invalid_file()){ - ipcdetail::close_file(m_handle); - m_handle = ipcdetail::invalid_file(); - } -} - -//!A class that stores the name of a file -//!and tries to remove it in its destructor -//!Useful to remove temporary files in the presence -//!of exceptions -class remove_file_on_destroy -{ - const char * m_name; - public: - remove_file_on_destroy(const char *name) - : m_name(name) - {} - - ~remove_file_on_destroy() - { ipcdetail::delete_file(m_name); } -}; - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_FILE_MAPPING_HPP diff --git a/extern/boost/boost/interprocess/indexes/flat_map_index.hpp b/extern/boost/boost/interprocess/indexes/flat_map_index.hpp deleted file mode 100644 index 027b75be47c..00000000000 --- a/extern/boost/boost/interprocess/indexes/flat_map_index.hpp +++ /dev/null @@ -1,93 +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_FLAT_MAP_INDEX_HPP -#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess -#include -#include -// intrusive/detail -#include //std::pair -#include //std::less - - -//!\file -//!Describes index adaptor of boost::map container, to use it -//!as name/shared memory index - -//[flat_map_index -namespace boost { namespace interprocess { - -#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Helper class to define typedefs from IndexTraits -template -struct flat_map_index_aux -{ - typedef typename MapConfig::key_type key_type; - typedef typename MapConfig::mapped_type mapped_type; - typedef typename MapConfig:: - segment_manager_base segment_manager_base; - typedef std::less key_less; - typedef std::pair value_type; - typedef allocator allocator_type; - typedef flat_map index_t; -}; - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Index type based in flat_map. Just derives from flat_map and -//!defines the interface needed by managed memory segments. -template -class flat_map_index - //Derive class from flat_map specialization - : public flat_map_index_aux::index_t -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef flat_map_index_aux index_aux; - typedef typename index_aux::index_t base_type; - typedef typename index_aux:: - segment_manager_base segment_manager_base; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Takes a pointer to the segment manager. Can throw - flat_map_index(segment_manager_base *segment_mngr) - : base_type(typename index_aux::key_less(), - typename index_aux::allocator_type(segment_mngr)) - {} - - //!This reserves memory to optimize the insertion of n elements in the index - void reserve(typename segment_manager_base::size_type n) - { base_type::reserve(n); } - - //!This frees all unnecessary memory - void shrink_to_fit() - { base_type::shrink_to_fit(); } -}; - -}} //namespace boost { namespace interprocess -//] -#include - -#endif //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/iset_index.hpp b/extern/boost/boost/interprocess/indexes/iset_index.hpp deleted file mode 100644 index ffaa24fa775..00000000000 --- a/extern/boost/boost/interprocess/indexes/iset_index.hpp +++ /dev/null @@ -1,158 +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_ISET_INDEX_HPP -#define BOOST_INTERPROCESS_ISET_INDEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include //std::pair -#include //std::less -#include //std::char_traits -#include - -//!\file -//!Describes index adaptor of boost::intrusive::set container, to use it -//!as name/shared memory index - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//!Helper class to define typedefs from IndexTraits -template -struct iset_index_aux -{ - typedef typename - MapConfig::segment_manager_base segment_manager_base; - - typedef typename - segment_manager_base::void_pointer void_pointer; - typedef typename bi::make_set_base_hook - < bi::void_pointer - , bi::optimize_size - >::type derivation_hook; - - typedef typename MapConfig::template - intrusive_value_type::type value_type; - typedef std::less value_compare; - typedef typename bi::make_set - < value_type - , bi::base_hook - >::type index_t; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Index type based in boost::intrusive::set. -//!Just derives from boost::intrusive::set -//!and defines the interface needed by managed memory segments*/ -template -class iset_index - //Derive class from map specialization - : public iset_index_aux::index_t -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef iset_index_aux index_aux; - typedef typename index_aux::index_t index_type; - typedef typename MapConfig:: - intrusive_compare_key_type intrusive_compare_key_type; - typedef typename MapConfig::char_type char_type; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef typename index_type::iterator iterator; - typedef typename index_type::const_iterator const_iterator; - typedef typename index_type::insert_commit_data insert_commit_data; - typedef typename index_type::value_type value_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - struct intrusive_key_value_less - { - bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { - std::size_t blen = b.name_length(); - return (i.m_len < blen) || - (i.m_len == blen && - std::char_traits::compare - (i.mp_str, b.name(), i.m_len) < 0); - } - - bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { - std::size_t blen = b.name_length(); - return (blen < i.m_len) || - (blen == i.m_len && - std::char_traits::compare - (b.name(), i.mp_str, i.m_len) < 0); - } - }; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - - //!Constructor. Takes a pointer to the - //!segment manager. Can throw - iset_index(typename MapConfig::segment_manager_base *) - : index_type(/*typename index_aux::value_compare()*/) - {} - - //!This reserves memory to optimize the insertion of n - //!elements in the index - void reserve(typename MapConfig::segment_manager_base::size_type) - { /*Does nothing, map has not reserve or rehash*/ } - - //!This frees all unnecessary memory - void shrink_to_fit() - { /*Does nothing, this intrusive index does not allocate memory;*/ } - - iterator find(const intrusive_compare_key_type &key) - { return index_type::find(key, intrusive_key_value_less()); } - - const_iterator find(const intrusive_compare_key_type &key) const - { return index_type::find(key, intrusive_key_value_less()); } - - std::pairinsert_check - (const intrusive_compare_key_type &key, insert_commit_data &commit_data) - { return index_type::insert_check(key, intrusive_key_value_less(), commit_data); } -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//!Trait class to detect if an index is an intrusive -//!index. -template -struct is_intrusive_index - > -{ - static const bool value = true; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost - -#include - -#endif //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp b/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp deleted file mode 100644 index 9599e8a422e..00000000000 --- a/extern/boost/boost/interprocess/indexes/iunordered_set_index.hpp +++ /dev/null @@ -1,390 +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_IUNORDERED_SET_INDEX_HPP -#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include //std::less -#include //std::char_traits -#include -#include - -//!\file -//!Describes index adaptor of boost::intrusive::unordered_set container, to use it -//!as name/shared memory index - -namespace boost { namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//!Helper class to define typedefs -//!from IndexTraits -template -struct iunordered_set_index_aux -{ - typedef typename - MapConfig::segment_manager_base segment_manager_base; - - typedef typename - segment_manager_base::void_pointer void_pointer; - - typedef typename bi::make_unordered_set_base_hook - < bi::void_pointer - >::type derivation_hook; - - typedef typename MapConfig::template - intrusive_value_type::type value_type; - - typedef typename MapConfig:: - intrusive_compare_key_type intrusive_compare_key_type; - - typedef std::equal_to value_equal; - - typedef typename MapConfig::char_type char_type; - - struct equal_function - { - bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { - return (i.m_len == b.name_length()) && - (std::char_traits::compare - (i.mp_str, b.name(), i.m_len) == 0); - } - - bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { - return (i.m_len == b.name_length()) && - (std::char_traits::compare - (i.mp_str, b.name(), i.m_len) == 0); - } - - bool operator()(const value_type &b1, const value_type &b2) const - { - return (b1.name_length() == b2.name_length()) && - (std::char_traits::compare - (b1.name(), b2.name(), b1.name_length()) == 0); - } - }; - - struct hash_function - { - typedef value_type argument_type; - typedef std::size_t result_type; - - std::size_t hash_char_range(const char_type* beg, const char_type* end) const - { - std::size_t seed = 0; - while (beg != end) { - boost::intrusive::detail::hash_combine_size_t(seed, boost::intrusive::detail::internal_hash_functor()(*beg)); - ++beg; - } - return seed; - } - - std::size_t operator()(const value_type &val) const - { - const char_type* beg = ipcdetail::to_raw_pointer(val.name()), - * end = beg + val.name_length(); - return hash_char_range(beg, end); - } - - std::size_t operator()(const intrusive_compare_key_type &i) const - { - const char_type *beg = i.mp_str, - *end = beg + i.m_len; - return hash_char_range(beg, end); - } - }; - - typedef typename bi::make_unordered_set - < value_type - , bi::hash - , bi::equal - , bi::size_type - >::type index_t; - typedef typename index_t::bucket_type bucket_type; - typedef allocator - allocator_type; - - struct allocator_holder - { - allocator_holder(segment_manager_base *mngr) - : alloc(mngr) - {} - allocator_type alloc; - bucket_type init_bucket; - }; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Index type based in boost::intrusive::set. -//!Just derives from boost::intrusive::set -//!and defines the interface needed by managed memory segments -template -class iunordered_set_index - //Derive class from map specialization - : private iunordered_set_index_aux::allocator_holder - , public iunordered_set_index_aux::index_t -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef iunordered_set_index_aux index_aux; - typedef typename index_aux::index_t index_type; - typedef typename MapConfig:: - intrusive_compare_key_type intrusive_compare_key_type; - typedef typename index_aux::equal_function equal_function; - typedef typename index_aux::hash_function hash_function; - typedef typename MapConfig::char_type char_type; - typedef typename - iunordered_set_index_aux::allocator_type allocator_type; - typedef typename - iunordered_set_index_aux::allocator_holder allocator_holder; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef typename index_type::iterator iterator; - typedef typename index_type::const_iterator const_iterator; - typedef typename index_type::insert_commit_data insert_commit_data; - typedef typename index_type::value_type value_type; - typedef typename index_type::bucket_ptr bucket_ptr; - typedef typename index_type::bucket_type bucket_type; - typedef typename index_type::bucket_traits bucket_traits; - typedef typename index_type::size_type size_type; - typedef typename index_type::difference_type difference_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef typename index_aux:: - segment_manager_base segment_manager_base; - - static const std::size_t InitBufferSize = 64; - - static bucket_ptr create_buckets(allocator_type &alloc, size_type num) - { - num = index_type::suggested_upper_bucket_count(num); - bucket_ptr buckets = alloc.allocate(num); - bucket_ptr buckets_init = buckets; - for(size_type i = 0; i < num; ++i){ - ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); - } - return buckets; - } - - static size_type shrink_buckets - ( bucket_ptr buckets, size_type old_size - , allocator_type &alloc, size_type new_size) - { - if(old_size <= new_size ) - return old_size; - size_type received_size = new_size; - if(!alloc.allocation_command - (boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, received_size, buckets)){ - return old_size; - } - - for( bucket_type *p = ipcdetail::to_raw_pointer(buckets) + received_size - , *pend = ipcdetail::to_raw_pointer(buckets) + old_size - ; p != pend - ; ++p){ - p->~bucket_type(); - } - - bucket_ptr shunk_p = alloc.allocation_command - (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, buckets); - BOOST_ASSERT(buckets == shunk_p); (void)shunk_p; - - bucket_ptr buckets_init = buckets + difference_type(received_size); - for(size_type i = 0; i < (old_size - received_size); ++i){ - to_raw_pointer(buckets_init++)->~bucket_type(); - } - return received_size; - } - - static bucket_ptr expand_or_create_buckets - ( bucket_ptr old_buckets, const size_type old_num - , allocator_type &alloc, const size_type new_num) - { - size_type received_size = new_num; - bucket_ptr reuse(old_buckets); - bucket_ptr ret = alloc.allocation_command - (boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, received_size, reuse); - if(ret == old_buckets){ - bucket_ptr buckets_init = old_buckets + difference_type(old_num); - for(size_type i = 0; i < (new_num - old_num); ++i){ - ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); - } - } - else{ - bucket_ptr buckets_init = ret; - for(size_type i = 0; i < new_num; ++i){ - ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type(); - } - } - return ret; - } - - static void destroy_buckets - (allocator_type &alloc, bucket_ptr buckets, size_type num) - { - bucket_ptr buckets_destroy = buckets; - for(size_type i = 0; i < num; ++i){ - to_raw_pointer(buckets_destroy++)->~bucket_type(); - } - alloc.deallocate(buckets, num); - } - - iunordered_set_index* get_this_pointer() - { return this; } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Takes a pointer to the - //!segment manager. Can throw - iunordered_set_index(segment_manager_base *mngr) - : allocator_holder(mngr) - , index_type(bucket_traits(&get_this_pointer()->init_bucket, 1)) - {} - - ~iunordered_set_index() - { - index_type::clear(); - if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){ - destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count()); - } - } - - //!This reserves memory to optimize the insertion of n - //!elements in the index - void reserve(size_type new_n) - { - //Let's maintain a 1.0f load factor - size_type old_n = this->bucket_count(); - if(new_n <= old_n) - return; - bucket_ptr old_p = this->bucket_pointer(); - new_n = index_type::suggested_upper_bucket_count(new_n); - bucket_ptr new_p; - //This can throw - BOOST_TRY{ - if(old_p != bucket_ptr(&this->init_bucket)) - new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n); - else - new_p = create_buckets(this->alloc, new_n); - } - BOOST_CATCH(...){ - return; - } BOOST_CATCH_END - //Rehashing does not throw, since neither the hash nor the - //comparison function can throw - this->rehash(bucket_traits(new_p, new_n)); - if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){ - destroy_buckets(this->alloc, old_p, old_n); - } - } - - //!This tries to free unused memory - //!previously allocated. - void shrink_to_fit() - { - size_type cur_size = this->size(); - size_type cur_count = this->bucket_count(); - bucket_ptr old_p = this->bucket_pointer(); - - if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){ - this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1)); - destroy_buckets(this->alloc, old_p, cur_count); - } - else{ - size_type sug_count = 0; //gcc warning - sug_count = index_type::suggested_upper_bucket_count(cur_size); - - if(sug_count >= cur_count) - return; - - BOOST_TRY{ - shrink_buckets(old_p, cur_count, this->alloc, sug_count); - } - BOOST_CATCH(...){ - return; - } BOOST_CATCH_END - - //Rehashing does not throw, since neither the hash nor the - //comparison function can throw - this->rehash(bucket_traits(old_p, sug_count)); - } - } - - iterator find(const intrusive_compare_key_type &key) - { return index_type::find(key, hash_function(), equal_function()); } - - const_iterator find(const intrusive_compare_key_type &key) const - { return index_type::find(key, hash_function(), equal_function()); } - - std::pairinsert_check - (const intrusive_compare_key_type &key, insert_commit_data &commit_data) - { return index_type::insert_check(key, hash_function(), equal_function(), commit_data); } - - iterator insert_commit(value_type &val, insert_commit_data &commit_data) - { - iterator it = index_type::insert_commit(val, commit_data); - size_type cur_size = this->size(); - if(cur_size > this->bucket_count()){ - BOOST_TRY{ - this->reserve(cur_size); - } - BOOST_CATCH(...){ - //Strong guarantee: if something goes wrong - //we should remove the insertion. - // - //We can use the iterator because the hash function - //can't throw and this means that "reserve" will - //throw only because of the memory allocation: - //the iterator has not been invalidated. - index_type::erase(it); - BOOST_RETHROW - } BOOST_CATCH_END - } - return it; - } -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//!Trait class to detect if an index is an intrusive -//!index -template -struct is_intrusive_index - > -{ - static const bool value = true; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -}} //namespace boost { namespace interprocess { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/map_index.hpp b/extern/boost/boost/interprocess/indexes/map_index.hpp deleted file mode 100644 index c7c3c865d13..00000000000 --- a/extern/boost/boost/interprocess/indexes/map_index.hpp +++ /dev/null @@ -1,109 +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_MAP_INDEX_HPP -#define BOOST_INTERPROCESS_MAP_INDEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include //std::pair -#include //std::less - -//!\file -//!Describes index adaptor of boost::map container, to use it -//!as name/shared memory index - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//!Helper class to define typedefs from IndexTraits -template -struct map_index_aux -{ - typedef typename MapConfig::key_type key_type; - typedef typename MapConfig::mapped_type mapped_type; - typedef std::less key_less; - typedef std::pair value_type; - - typedef private_adaptive_pool - allocator_type; - - typedef boost::interprocess::map - index_t; -}; - -} //namespace ipcdetail { - -//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map -//!and defines the interface needed by managed memory segments -template -class map_index - //Derive class from map specialization - : public ipcdetail::map_index_aux::index_t -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef ipcdetail::map_index_aux index_aux; - typedef typename index_aux::index_t base_type; - typedef typename MapConfig:: - segment_manager_base segment_manager_base; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Takes a pointer to the - //!segment manager. Can throw - map_index(segment_manager_base *segment_mngr) - : base_type(typename index_aux::key_less(), - segment_mngr){} - - //!This reserves memory to optimize the insertion of n - //!elements in the index - void reserve(typename segment_manager_base::size_type) - { /*Does nothing, map has not reserve or rehash*/ } - - //!This tries to free previously allocate - //!unused memory. - void shrink_to_fit() - { base_type::get_stored_allocator().deallocate_free_blocks(); } -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//!Trait class to detect if an index is a node -//!index. This allows more efficient operations -//!when deallocating named objects. -template -struct is_node_index - > -{ - static const bool value = true; -}; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -}} //namespace boost { namespace interprocess { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP diff --git a/extern/boost/boost/interprocess/indexes/null_index.hpp b/extern/boost/boost/interprocess/indexes/null_index.hpp deleted file mode 100644 index ed4797f8f76..00000000000 --- a/extern/boost/boost/interprocess/indexes/null_index.hpp +++ /dev/null @@ -1,76 +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_NULL_INDEX_HPP -#define BOOST_INTERPROCESS_NULL_INDEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -//!\file -//!Describes a null index adaptor, so that if we don't want to construct -//!named objects, we can use this null index type to save resources. - -namespace boost { -namespace interprocess { - -//!Null index type -//!used to save compilation time when -//!named indexes are not needed. -template -class null_index -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef typename MapConfig:: - segment_manager_base segment_manager_base; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef int * iterator; - typedef const int * const_iterator; - - //!begin() is equal - //!to end() - const_iterator begin() const - { return const_iterator(0); } - - //!begin() is equal - //!to end() - iterator begin() - { return iterator(0); } - - //!begin() is equal - //!to end() - const_iterator end() const - { return const_iterator(0); } - - //!begin() is equal - //!to end() - iterator end() - { return iterator(0); } - - //!Empty constructor - null_index(segment_manager_base *){} -}; - -}} //namespace boost { namespace interprocess { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP diff --git a/extern/boost/boost/interprocess/ipc/message_queue.hpp b/extern/boost/boost/interprocess/ipc/message_queue.hpp deleted file mode 100644 index bb70adaece6..00000000000 --- a/extern/boost/boost/interprocess/ipc/message_queue.hpp +++ /dev/null @@ -1,1131 +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_MESSAGE_QUEUE_HPP -#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include //make_unsigned, alignment_of -#include -#include -#include -#include //std::lower_bound -#include //std::size_t -#include //memcpy - - -//!\file -//!Describes an inter-process message queue. This class allows sending -//!messages between processes and allows blocking, non-blocking and timed -//!sending and receiving. - -namespace boost{ namespace interprocess{ - -namespace ipcdetail -{ - template - class msg_queue_initialization_func_t; - -} - -//Blocking modes -enum mqblock_types { blocking, timed, non_blocking }; - -//!A class that allows sending messages -//!between processes. -template -class message_queue_t -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - message_queue_t(); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef VoidPointer void_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type char_ptr; - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::container::dtl::make_unsigned::type size_type; - - //!Creates a process shared message queue with name "name". For this message queue, - //!the maximum number of messages will be "max_num_msg" and the maximum message size - //!will be "max_msg_size". Throws on error and if the queue was previously created. - message_queue_t(create_only_t, - const char *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm = permissions()); - - //!Opens or creates a process shared message queue with name "name". - //!If the queue is created, the maximum number of messages will be "max_num_msg" - //!and the maximum message size will be "max_msg_size". If queue was previously - //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters - //!are ignored. Throws on error. - message_queue_t(open_or_create_t, - const char *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm = permissions()); - - //!Opens a previously created process shared message queue with name "name". - //!If the queue was not previously created or there are no free resources, - //!throws an error. - message_queue_t(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a process shared message queue with name "name". For this message queue, - //!the maximum number of messages will be "max_num_msg" and the maximum message size - //!will be "max_msg_size". Throws on error and if the queue was previously created. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - message_queue_t(create_only_t, - const wchar_t *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm = permissions()); - - //!Opens or creates a process shared message queue with name "name". - //!If the queue is created, the maximum number of messages will be "max_num_msg" - //!and the maximum message size will be "max_msg_size". If queue was previously - //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters - //!are ignored. Throws on error. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - message_queue_t(open_or_create_t, - const wchar_t *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm = permissions()); - - //!Opens a previously created process shared message queue with name "name". - //!If the queue was not previously created or there are no free resources, - //!throws an error. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - message_queue_t(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a process shared message queue in anonymous memory. For this message queue, - //!the maximum number of messages will be "max_num_msg" and the maximum message size - //!will be "max_msg_size". Throws on error. - message_queue_t(size_type max_num_msg, - size_type max_msg_size); - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. All opened message queues are still - //!valid after destruction. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the message queue from the system - //!use remove(). - ~message_queue_t(); - - //!Sends a message stored in buffer "buffer" with size "buffer_size" in the - //!message queue with priority "priority". If the message queue is full - //!the sender is blocked. Throws interprocess_error on error. - void send (const void *buffer, size_type buffer_size, - unsigned int priority); - - //!Sends a message stored in buffer "buffer" with size "buffer_size" through the - //!message queue with priority "priority". If the message queue is full - //!the sender is not blocked and returns false, otherwise returns true. - //!Throws interprocess_error on error. - bool try_send (const void *buffer, size_type buffer_size, - unsigned int priority); - - //!Sends a message stored in buffer "buffer" with size "buffer_size" in the - //!message queue with priority "priority". If the message queue is full - //!the sender retries until time "abs_time" is reached. Returns true if - //!the message has been successfully sent. Returns false if timeout is reached. - //!Throws interprocess_error on error. - template - bool timed_send (const void *buffer, size_type buffer_size, - unsigned int priority, const TimePoint& abs_time); - - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size - //!"recvd_size" and priority "priority". If the message queue is empty - //!the receiver is blocked. Throws interprocess_error on error. - void receive (void *buffer, size_type buffer_size, - size_type &recvd_size,unsigned int &priority); - - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size - //!"recvd_size" and priority "priority". If the message queue is empty - //!the receiver is not blocked and returns false, otherwise returns true. - //!Throws interprocess_error on error. - bool try_receive (void *buffer, size_type buffer_size, - size_type &recvd_size,unsigned int &priority); - - //!Receives a message from the message queue. The message is stored in buffer - //!"buffer", which has size "buffer_size". The received message has size - //!"recvd_size" and priority "priority". If the message queue is empty - //!the receiver retries until time "abs_time" is reached. Returns true if - //!the message has been successfully sent. Returns false if timeout is reached. - //!Throws interprocess_error on error. - template - bool timed_receive (void *buffer, size_type buffer_size, - size_type &recvd_size,unsigned int &priority, - const TimePoint &abs_time); - - //!Returns the maximum number of messages allowed by the queue. The message - //!queue must be opened or created previously. Otherwise, returns 0. - //!Never throws - size_type get_max_msg() const; - - //!Returns the maximum size of message allowed by the queue. The message - //!queue must be opened or created previously. Otherwise, returns 0. - //!Never throws - size_type get_max_msg_size() const; - - //!Returns the number of messages currently stored. - //!Never throws - size_type get_num_msg() const; - - //!Removes the message queue 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) - - //!Removes the message queue 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 - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - friend class ipcdetail::msg_queue_initialization_func_t; - - template - bool do_receive(void *buffer, size_type buffer_size, - size_type &recvd_size, unsigned int &priority, - const TimePoint &abs_time); - - template - bool do_send(const void *buffer, size_type buffer_size, - unsigned int priority, const TimePoint &abs_time); - - //!Returns the needed memory size for the shared message queue. - //!Never throws - static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg); - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - - template - static bool do_cond_wait(ipcdetail::bool_, interprocess_condition &cond, Lock &lock, const TimePoint &abs_time) - { return cond.timed_wait(lock, abs_time); } - - template - static bool do_cond_wait(ipcdetail::bool_, interprocess_condition &cond, Lock &lock, const TimePoint &) - { cond.wait(lock); return true; } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace ipcdetail { - -//!This header is the prefix of each message in the queue -template -class msg_hdr_t -{ - typedef VoidPointer void_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type char_ptr; - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::container::dtl::make_unsigned::type size_type; - - public: - size_type len; // Message length - unsigned int priority;// Message priority - //!Returns the data buffer associated with this this message - void * data(){ return this+1; } // -}; - -//!This functor is the predicate to order stored messages by priority -template -class priority_functor -{ - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer >::type msg_hdr_ptr_t; - - public: - bool operator()(const msg_hdr_ptr_t &msg1, - const msg_hdr_ptr_t &msg2) const - { return msg1->priority < msg2->priority; } -}; - -//!This header is placed in the beginning of the shared memory and contains -//!the data to control the queue. This class initializes the shared memory -//!in the following way: in ascending memory address with proper alignment -//!fillings: -//! -//!-> mq_hdr_t: -//! Main control block that controls the rest of the elements -//! -//!-> offset_ptr index [max_num_msg] -//! An array of pointers with size "max_num_msg" called index. Each pointer -//! points to a preallocated message. Elements of this array are -//! reordered in runtime in the following way: -//! -//! IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined: -//! -//! When the current number of messages is "cur_num_msg", the array -//! is treated like a circular buffer. Starting from position "cur_first_msg" -//! "cur_num_msg" in a circular way, pointers point to inserted messages and the rest -//! point to free messages. Those "cur_num_msg" pointers are -//! ordered by the priority of the pointed message and by insertion order -//! if two messages have the same priority. So the next message to be -//! used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg] -//! and the first free message ready to be used in a "send" operation is -//! [cur_first_msg] if circular buffer is extended from front, -//! [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise. -//! -//! This transforms the index in a circular buffer with an embedded free -//! message queue. -//! -//! ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined): -//! -//! When the current number of messages is "cur_num_msg", the first -//! "cur_num_msg" pointers point to inserted messages and the rest -//! point to free messages. The first "cur_num_msg" pointers are -//! ordered by the priority of the pointed message and by insertion order -//! if two messages have the same priority. So the next message to be -//! used in a "receive" is pointed by index [cur_num_msg-1] and the first free -//! message ready to be used in a "send" operation is index [cur_num_msg]. -//! -//! This transforms the index in a fixed size priority queue with an embedded free -//! message queue. -//! -//!-> struct message_t -//! { -//! msg_hdr_t header; -//! char[max_msg_size] data; -//! } messages [max_num_msg]; -//! -//! An array of buffers of preallocated messages, each one prefixed with the -//! msg_hdr_t structure. Each of this message is pointed by one pointer of -//! the index structure. -template -class mq_hdr_t - : public ipcdetail::priority_functor -{ - typedef VoidPointer void_pointer; - typedef msg_hdr_t msg_header; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type msg_hdr_ptr_t; - typedef typename boost::intrusive::pointer_traits - ::difference_type difference_type; - typedef typename boost::container:: - dtl::make_unsigned::type size_type; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type msg_hdr_ptr_ptr_t; - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - - public: - //!Constructor. This object must be constructed in the beginning of the - //!shared memory of the size returned by the function "get_mem_size". - //!This constructor initializes the needed resources and creates - //!the internal structures like the priority index. This can throw. - mq_hdr_t(size_type max_num_msg, size_type max_msg_size) - : m_max_num_msg(max_num_msg), - m_max_msg_size(max_msg_size), - m_cur_num_msg(0) - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - ,m_cur_first_msg(0u) - ,m_blocked_senders(0u) - ,m_blocked_receivers(0u) - #endif - { this->initialize_memory(); } - - //!Returns true if the message queue is full - bool is_full() const - { return m_cur_num_msg == m_max_num_msg; } - - //!Returns true if the message queue is empty - bool is_empty() const - { return !m_cur_num_msg; } - - //!Frees the top priority message and saves it in the free message list - void free_top_msg() - { --m_cur_num_msg; } - - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - - typedef msg_hdr_ptr_t *iterator; - - size_type end_pos() const - { - const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg; - return space_until_bufend > m_cur_num_msg - ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend; - } - - //!Returns the inserted message with top priority - msg_header &top_msg() - { - size_type pos = this->end_pos(); - return *mp_index[difference_type(pos ? --pos : m_max_num_msg - 1)]; - } - - //!Returns the inserted message with bottom priority - msg_header &bottom_msg() - { return *mp_index[difference_type(m_cur_first_msg)]; } - - iterator inserted_ptr_begin() const - { return &mp_index[difference_type(m_cur_first_msg)]; } - - iterator inserted_ptr_end() const - { return &mp_index[difference_type(this->end_pos())]; } - - iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) - { - iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end()); - if(end < begin){ - iterator idx_end = &mp_index[difference_type(m_max_num_msg)]; - iterator ret = std::lower_bound(begin, idx_end, value, func); - if(idx_end == ret){ - iterator idx_beg = &mp_index[0]; - ret = std::lower_bound(idx_beg, end, value, func); - //sanity check, these cases should not call lower_bound (optimized out) - BOOST_ASSERT(ret != end); - BOOST_ASSERT(ret != begin); - return ret; - } - else{ - return ret; - } - } - else{ - return std::lower_bound(begin, end, value, func); - } - } - - msg_header & insert_at(iterator where) - { - iterator it_inserted_ptr_end = this->inserted_ptr_end(); - iterator it_inserted_ptr_beg = this->inserted_ptr_begin(); - if(where == it_inserted_ptr_beg){ - //unsigned integer guarantees underflow - m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; - --m_cur_first_msg; - ++m_cur_num_msg; - return *mp_index[difference_type(m_cur_first_msg)]; - } - else if(where == it_inserted_ptr_end){ - ++m_cur_num_msg; - return **it_inserted_ptr_end; - } - else{ - size_type pos = size_type(where - &mp_index[0]); - size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg); - //Check if it's more efficient to move back or move front - if(circ_pos < m_cur_num_msg/2){ - //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos - //indicates two step insertion - if(!pos){ - pos = m_max_num_msg; - where = &mp_index[difference_type(m_max_num_msg-1u)]; - } - else{ - --where; - } - const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos; - const size_type first_segment_beg = unique_segment ? m_cur_first_msg : 1u; - const size_type first_segment_end = pos; - const size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg; - const size_type second_segment_end = m_max_num_msg; - const msg_hdr_ptr_t backup = *(&mp_index[0] + (unique_segment ? first_segment_beg : second_segment_beg) - 1); - - //First segment - if(!unique_segment){ - std::copy( &mp_index[0] + second_segment_beg - , &mp_index[0] + second_segment_end - , &mp_index[0] + second_segment_beg - 1); - mp_index[difference_type(m_max_num_msg-1u)] = mp_index[0]; - } - std::copy( &mp_index[0] + first_segment_beg - , &mp_index[0] + first_segment_end - , &mp_index[0] + first_segment_beg - 1); - *where = backup; - m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; - --m_cur_first_msg; - ++m_cur_num_msg; - return **where; - } - else{ - //The queue can't be full so end_pos < m_cur_first_msg - //indicates two step insertion - const size_type pos_end = this->end_pos(); - const bool unique_segment = pos < pos_end; - const size_type first_segment_beg = pos; - const size_type first_segment_end = unique_segment ? pos_end : m_max_num_msg-1; - const size_type second_segment_beg = 0u; - const size_type second_segment_end = unique_segment ? 0u : pos_end; - const msg_hdr_ptr_t backup = *it_inserted_ptr_end; - - //First segment - if(!unique_segment){ - std::copy_backward( &mp_index[0] + second_segment_beg - , &mp_index[0] + second_segment_end - , &mp_index[0] + second_segment_end + 1u); - mp_index[0] = mp_index[difference_type(m_max_num_msg-1u)]; - } - std::copy_backward( &mp_index[0] + first_segment_beg - , &mp_index[0] + first_segment_end - , &mp_index[0] + first_segment_end + 1u); - *where = backup; - ++m_cur_num_msg; - return **where; - } - } - } - - #else //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - - typedef msg_hdr_ptr_t *iterator; - - //!Returns the inserted message with top priority - msg_header &top_msg() - { return *mp_index[difference_type(m_cur_num_msg-1u)]; } - - //!Returns the inserted message with bottom priority - msg_header &bottom_msg() - { return *mp_index[0]; } - - iterator inserted_ptr_begin() const - { return &mp_index[0]; } - - iterator inserted_ptr_end() const - { return &mp_index[difference_type(m_cur_num_msg)]; } - - iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) - { return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); } - - msg_header & insert_at(iterator pos) - { - const msg_hdr_ptr_t backup = *inserted_ptr_end(); - std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1); - *pos = backup; - ++m_cur_num_msg; - return **pos; - } - - #endif //BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - - //!Inserts the first free message in the priority queue - msg_header & queue_free_msg(unsigned int priority) - { - //Get priority queue's range - iterator it (inserted_ptr_begin()), it_end(inserted_ptr_end()); - //Optimize for non-priority usage - if(m_cur_num_msg && priority > this->bottom_msg().priority){ - //Check for higher priority than all stored messages - if(priority > this->top_msg().priority){ - it = it_end; - } - else{ - //Since we don't now which free message we will pick - //build a dummy header for searches - msg_header dummy_hdr; - dummy_hdr.priority = priority; - - //Get free msg - msg_hdr_ptr_t dummy_ptr(&dummy_hdr); - - //Check where the free message should be placed - it = this->lower_bound(dummy_ptr, static_cast&>(*this)); - } - } - //Insert the free message in the correct position - return this->insert_at(it); - } - - //!Returns the number of bytes needed to construct a message queue with - //!"max_num_size" maximum number of messages and "max_msg_size" maximum - //!message size. Never throws. - static size_type get_mem_size - (size_type max_msg_size, size_type max_num_msg) - { - const size_type - msg_hdr_align = ::boost::container::dtl::alignment_of::value, - index_align = ::boost::container::dtl::alignment_of::value, - r_hdr_size = ipcdetail::ct_rounded_size::value, - r_index_size = ipcdetail::get_rounded_size(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), - r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header); - return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + - open_create_impl_t::ManagedOpenOrCreateUserOffset; - } - - //!Initializes the memory structures to preallocate messages and constructs the - //!message index. Never throws. - void initialize_memory() - { - const size_type - msg_hdr_align = ::boost::container::dtl::alignment_of::value, - index_align = ::boost::container::dtl::alignment_of::value, - r_hdr_size = ipcdetail::ct_rounded_size::value, - r_index_size = ipcdetail::get_rounded_size(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), - r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header); - - //Pointer to the index - msg_hdr_ptr_t *index = move_detail::force_ptr - (reinterpret_cast(this)+r_hdr_size); - - //Pointer to the first message header - msg_header *msg_hdr = move_detail::force_ptr - (reinterpret_cast(this)+r_hdr_size+r_index_size); - - //Initialize the pointer to the index - mp_index = index; - - //Initialize the index so each slot points to a preallocated message - for(size_type i = 0; i < m_max_num_msg; ++i){ - index[i] = msg_hdr; - msg_hdr = move_detail::force_ptr - (reinterpret_cast(msg_hdr)+r_max_msg_size); - } - } - - public: - //Pointer to the index - msg_hdr_ptr_ptr_t mp_index; - //Maximum number of messages of the queue - const size_type m_max_num_msg; - //Maximum size of messages of the queue - const size_type m_max_msg_size; - //Current number of messages - size_type m_cur_num_msg; - //Mutex to protect data structures - interprocess_mutex m_mutex; - //Condition block receivers when there are no messages - interprocess_condition m_cond_recv; - //Condition block senders when the queue is full - interprocess_condition m_cond_send; - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - //Current start offset in the circular index - size_type m_cur_first_msg; - size_type m_blocked_senders; - size_type m_blocked_receivers; - #endif -}; - - -//!This is the atomic functor to be executed when creating or opening -//!shared memory. Never throws -template -class msg_queue_initialization_func_t -{ - public: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type char_ptr; - typedef typename boost::intrusive::pointer_traits:: - difference_type difference_type; - typedef typename boost::container::dtl:: - make_unsigned::type size_type; - - msg_queue_initialization_func_t(size_type maxmsg = 0, - size_type maxmsgsize = 0) - : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {} - - bool operator()(void *address, size_type, bool created) - { - char *mptr; - - if(created){ - mptr = reinterpret_cast(address); - //Construct the message queue header at the beginning - BOOST_TRY{ - new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END - } - return true; - } - - std::size_t get_min_size() const - { - return mq_hdr_t::get_mem_size(m_maxmsgsize, m_maxmsg) - - message_queue_t::open_create_impl_t::ManagedOpenOrCreateUserOffset; - } - - const size_type m_maxmsg; - const size_type m_maxmsgsize; -}; - -} //namespace ipcdetail { - -template -inline message_queue_t::~message_queue_t() -{} - -template -inline typename message_queue_t::size_type message_queue_t::get_mem_size - (size_type max_msg_size, size_type max_num_msg) -{ return ipcdetail::mq_hdr_t::get_mem_size(max_msg_size, max_num_msg); } - -template -inline message_queue_t::message_queue_t(create_only_t, - const char *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm) - //Create shared memory and execute functor atomically - : m_shmem(create_only, - name, - get_mem_size(max_msg_size, max_num_msg), - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), - perm) -{} - -template -inline message_queue_t::message_queue_t(open_or_create_t, - const char *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm) - //Create shared memory and execute functor atomically - : m_shmem(open_or_create, - name, - get_mem_size(max_msg_size, max_num_msg), - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), - perm) -{} - -template -inline message_queue_t::message_queue_t(open_only_t, const char *name) - //Create shared memory and execute functor atomically - : m_shmem(open_only, - name, - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t ()) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -inline message_queue_t::message_queue_t(create_only_t, - const wchar_t *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm) - //Create shared memory and execute functor atomically - : m_shmem(create_only, - name, - get_mem_size(max_msg_size, max_num_msg), - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), - perm) -{} - -template -inline message_queue_t::message_queue_t(open_or_create_t, - const wchar_t *name, - size_type max_num_msg, - size_type max_msg_size, - const permissions &perm) - //Create shared memory and execute functor atomically - : m_shmem(open_or_create, - name, - get_mem_size(max_msg_size, max_num_msg), - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), - perm) -{} - -template -inline message_queue_t::message_queue_t(open_only_t, const wchar_t *name) - //Create shared memory and execute functor atomically - : m_shmem(open_only, - name, - read_write, - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t ()) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -inline message_queue_t::message_queue_t(size_type max_num_msg, - size_type max_msg_size) - : m_shmem(get_mem_size(max_msg_size, max_num_msg), - static_cast(0), - //Prepare initialization functor - ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size)) -{} - -template -inline void message_queue_t::send - (const void *buffer, size_type buffer_size, unsigned int priority) -{ this->do_send(buffer, buffer_size, priority, 0); } - -template -inline bool message_queue_t::try_send - (const void *buffer, size_type buffer_size, unsigned int priority) -{ return this->do_send(buffer, buffer_size, priority, 0); } - -template -template -inline bool message_queue_t::timed_send - (const void *buffer, size_type buffer_size - ,unsigned int priority, const TimePoint &abs_time) -{ - if(ipcdetail::is_pos_infinity(abs_time)){ - this->send(buffer, buffer_size, priority); - return true; - } - return this->do_send(buffer, buffer_size, priority, abs_time); -} - -template -template -inline bool message_queue_t::do_send( - const void *buffer, size_type buffer_size, - unsigned int priority, const TimePoint &abs_time) -{ - ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - //Check if buffer is smaller than maximum allowed - if (buffer_size > p_hdr->m_max_msg_size) { - throw interprocess_exception(size_error); - } - - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - bool notify_blocked_receivers = false; - #endif - //--------------------------------------------- - scoped_lock lock(p_hdr->m_mutex); - //--------------------------------------------- - { - //If the queue is full execute blocking logic - if (p_hdr->is_full()) { - BOOST_TRY{ - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - ++p_hdr->m_blocked_senders; - #endif - switch(Block){ - case non_blocking : - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - --p_hdr->m_blocked_senders; - #endif - return false; - break; - - case blocking : - do{ - (void)do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_send, lock, abs_time); - } - while (p_hdr->is_full()); - break; - - case timed : - do{ - if(!do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_send, lock, abs_time)) { - if(p_hdr->is_full()){ - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - --p_hdr->m_blocked_senders; - #endif - return false; - } - break; - } - } - while (p_hdr->is_full()); - break; - default: - break; - } - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - --p_hdr->m_blocked_senders; - #endif - } - BOOST_CATCH(...){ - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - --p_hdr->m_blocked_senders; - #endif - BOOST_RETHROW; - } BOOST_CATCH_END - } - - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - notify_blocked_receivers = 0 != p_hdr->m_blocked_receivers; - #endif - //Insert the first free message in the priority queue - ipcdetail::msg_hdr_t &free_msg_hdr = p_hdr->queue_free_msg(priority); - - //Sanity check, free msgs are always cleaned when received - BOOST_ASSERT(free_msg_hdr.priority == 0); - BOOST_ASSERT(free_msg_hdr.len == 0); - - //Copy control data to the free message - free_msg_hdr.priority = priority; - free_msg_hdr.len = buffer_size; - - //Copy user buffer to the message - std::memcpy(free_msg_hdr.data(), buffer, buffer_size); - } // Lock end - - //Notify outside lock to avoid contention. This might produce some - //spurious wakeups, but it's usually far better than notifying inside. - //If this message changes the queue empty state, notify it to receivers - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - if (notify_blocked_receivers){ - p_hdr->m_cond_recv.notify_one(); - } - #else - p_hdr->m_cond_recv.notify_one(); - #endif - - return true; -} - -template -inline void message_queue_t::receive(void *buffer, size_type buffer_size, - size_type &recvd_size, unsigned int &priority) -{ this->do_receive(buffer, buffer_size, recvd_size, priority, 0); } - -template -inline bool - message_queue_t::try_receive(void *buffer, size_type buffer_size, - size_type &recvd_size, unsigned int &priority) -{ return this->do_receive(buffer, buffer_size, recvd_size, priority, 0); } - -template -template -inline bool - message_queue_t::timed_receive(void *buffer, size_type buffer_size, - size_type &recvd_size, unsigned int &priority, - const TimePoint &abs_time) -{ - if(ipcdetail::is_pos_infinity(abs_time)){ - this->receive(buffer, buffer_size, recvd_size, priority); - return true; - } - return this->do_receive(buffer, buffer_size, recvd_size, priority, abs_time); -} - -template -template -inline bool - message_queue_t::do_receive( - void *buffer, size_type buffer_size, - size_type &recvd_size, unsigned int &priority, - const TimePoint &abs_time) -{ - ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - //Check if buffer is big enough for any message - if (buffer_size < p_hdr->m_max_msg_size) { - throw interprocess_exception(size_error); - } - - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - bool notify_blocked_senders = false; - #endif - //--------------------------------------------- - scoped_lock lock(p_hdr->m_mutex); - //--------------------------------------------- - { - //If there are no messages execute blocking logic - if (p_hdr->is_empty()) { - BOOST_TRY{ - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - ++p_hdr->m_blocked_receivers; - #endif - switch(Block){ - case non_blocking : - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - --p_hdr->m_blocked_receivers; - #endif - return false; - break; - - case blocking : - do{ - (void)do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_recv, lock, abs_time); - } - while (p_hdr->is_empty()); - break; - - case timed : - do{ - if(!do_cond_wait(ipcdetail::bool_(), p_hdr->m_cond_recv, lock, abs_time)) { - if(p_hdr->is_empty()){ - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - --p_hdr->m_blocked_receivers; - #endif - return false; - } - break; - } - } - while (p_hdr->is_empty()); - break; - - //Paranoia check - default: - break; - } - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - --p_hdr->m_blocked_receivers; - #endif - } - BOOST_CATCH(...){ - #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) - --p_hdr->m_blocked_receivers; - #endif - BOOST_RETHROW; - } BOOST_CATCH_END - } - - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - notify_blocked_senders = 0 != p_hdr->m_blocked_senders; - #endif - - //There is at least one message ready to pick, get the top one - ipcdetail::msg_hdr_t &top_msg = p_hdr->top_msg(); - - //Get data from the message - recvd_size = top_msg.len; - priority = top_msg.priority; - - //Some cleanup to ease debugging - top_msg.len = 0; - top_msg.priority = 0; - - //Copy data to receiver's bufers - std::memcpy(buffer, top_msg.data(), recvd_size); - - //Free top message and put it in the free message list - p_hdr->free_top_msg(); - } //Lock end - - //Notify outside lock to avoid contention. This might produce some - //spurious wakeups, but it's usually far better than notifying inside. - //If this reception changes the queue full state, notify senders - #ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX - if (notify_blocked_senders){ - p_hdr->m_cond_send.notify_one(); - } - #else - p_hdr->m_cond_send.notify_one(); - #endif - - return true; -} - -template -inline typename message_queue_t::size_type message_queue_t::get_max_msg() const -{ - ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - return p_hdr ? p_hdr->m_max_num_msg : 0; } - -template -inline typename message_queue_t::size_type message_queue_t::get_max_msg_size() const -{ - ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - return p_hdr ? p_hdr->m_max_msg_size : 0; -} - -template -inline typename message_queue_t::size_type message_queue_t::get_num_msg() const -{ - ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - if(p_hdr){ - //--------------------------------------------- - scoped_lock lock(p_hdr->m_mutex); - //--------------------------------------------- - return p_hdr->m_cur_num_msg; - } - - return 0; -} - -template -inline bool message_queue_t::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -inline bool message_queue_t::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif - -#else - -//!Typedef for a default message queue -//!to be used between processes -typedef message_queue_t > message_queue; - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -}} //namespace boost{ namespace interprocess{ - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP diff --git a/extern/boost/boost/interprocess/managed_external_buffer.hpp b/extern/boost/boost/interprocess/managed_external_buffer.hpp deleted file mode 100644 index 0cf2d4d2b49..00000000000 --- a/extern/boost/boost/interprocess/managed_external_buffer.hpp +++ /dev/null @@ -1,143 +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_MANAGED_EXTERNAL_BUFFER_HPP -#define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include -#include - -//!\file -//!Describes a named user memory allocation user class. - -namespace boost { -namespace interprocess { - -//!A basic user memory named object creation class. Inherits all -//!basic functionality from -//!basic_managed_memory_impl*/ -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_external_buffer - : public ipcdetail::basic_managed_memory_impl -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef ipcdetail::basic_managed_memory_impl - base_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef typename base_t::size_type size_type; - - //!Default constructor. Does nothing. - //!Useful in combination with move semantics - basic_managed_external_buffer() BOOST_NOEXCEPT - {} - - //!Creates and places the segment manager. This can throw - //!The external memory supplied by the user shall be aligned to the maximum value between - //!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built - //!inside that memory. - basic_managed_external_buffer - (create_only_t, void *addr, size_type size) - { - //Check if alignment is correct - BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u))))); - if(!base_t::create_impl(addr, size)){ - throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor"); - } - } - - //!Creates and places the segment manager. This can throw - //!The external memory supplied by the user shall be aligned to the maximum value between - //!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built - //!inside that memory. - basic_managed_external_buffer - (open_only_t, void *addr, size_type size) - { - //Check if alignment is correct - BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u))))); - if(!base_t::open_impl(addr, size)){ - throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor"); - } - } - - //!Moves the ownership of "moved"'s managed memory to *this. Does not throw - basic_managed_external_buffer(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT - { - this->swap(moved); - } - - //!Moves the ownership of "moved"'s managed memory to *this. Does not throw - basic_managed_external_buffer &operator=(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT - { - basic_managed_external_buffer tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - void grow(size_type extra_bytes) - { base_t::grow(extra_bytes); } - - //!Swaps the ownership of the managed heap memories managed by *this and other. - //!Never throws. - void swap(basic_managed_external_buffer &other) BOOST_NOEXCEPT - { base_t::swap(other); } -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_external_buffer -//!of narrow characters -typedef basic_managed_external_buffer - - ,iset_index> -managed_external_buffer; - -//!Typedef for a default basic_managed_external_buffer -//!of wide characters -typedef basic_managed_external_buffer - - ,iset_index> -wmanaged_external_buffer; - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP - diff --git a/extern/boost/boost/interprocess/managed_heap_memory.hpp b/extern/boost/boost/interprocess/managed_heap_memory.hpp deleted file mode 100644 index 52b917acba9..00000000000 --- a/extern/boost/boost/interprocess/managed_heap_memory.hpp +++ /dev/null @@ -1,172 +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_MANAGED_HEAP_MEMORY_HPP -#define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include -#include - -//!\file -//!Describes a named heap memory allocation user class. - -namespace boost { -namespace interprocess { - -//!A basic heap memory named object creation class. Initializes the -//!heap memory segment. Inherits all basic functionality from -//!basic_managed_memory_impl*/ -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_heap_memory - : public ipcdetail::basic_managed_memory_impl -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - typedef ipcdetail::basic_managed_memory_impl - base_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - typedef typename base_t::size_type size_type; - - //!Default constructor. Does nothing. - //!Useful in combination with move semantics - basic_managed_heap_memory() BOOST_NOEXCEPT - {} - - //!Destructor. Liberates the heap memory holding the managed data. - //!Never throws. - ~basic_managed_heap_memory() - { this->priv_close(); } - - //!Creates heap memory and initializes the segment manager. - //!This can throw. - basic_managed_heap_memory(size_type size) - : m_heapmem(size, char(0)) - { - if(!base_t::create_impl(&m_heapmem[0], size)){ - this->priv_close(); - throw interprocess_exception("Could not initialize heap in basic_managed_heap_memory constructor"); - } - } - - //!Moves the ownership of "moved"'s managed memory to *this. Does not throw - basic_managed_heap_memory(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT - { this->swap(moved); } - - //!Moves the ownership of "moved"'s managed memory to *this. Does not throw - basic_managed_heap_memory &operator=(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT - { - basic_managed_heap_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Tries to resize internal heap memory so that - //!we have room for more objects. - //!WARNING: If memory is reallocated, all the objects will - //!be binary-copied to the new buffer. To be able to use - //!this function, all pointers constructed in this buffer - //!must be offset pointers. Otherwise, the result is undefined. - //!Returns true if the growth has been successful, so you will - //!have some extra bytes to allocate new objects. If returns - //!false, the heap allocation has failed. - bool grow(size_type extra_bytes) - { - //If memory is reallocated, data will - //be automatically copied - BOOST_TRY{ - m_heapmem.resize(m_heapmem.size()+extra_bytes); - } - BOOST_CATCH(...){ - return false; - } - BOOST_CATCH_END - - //Grow always works - base_t::close_impl(); - base_t::open_impl(&m_heapmem[0], m_heapmem.size()); - base_t::grow(extra_bytes); - return true; - } - - //!Swaps the ownership of the managed heap memories managed by *this and other. - //!Never throws. - void swap(basic_managed_heap_memory &other) BOOST_NOEXCEPT - { - base_t::swap(other); - m_heapmem.swap(other.m_heapmem); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - //!Frees resources. Never throws. - void priv_close() - { - base_t::destroy_impl(); - std::vector().swap(m_heapmem); - } - - std::vector m_heapmem; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_heap_memory -//!of narrow characters -typedef basic_managed_heap_memory - - ,iset_index> -managed_heap_memory; - -//!Typedef for a default basic_managed_heap_memory -//!of wide characters -typedef basic_managed_heap_memory - - ,iset_index> -wmanaged_heap_memory; - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP - diff --git a/extern/boost/boost/interprocess/managed_mapped_file.hpp b/extern/boost/boost/interprocess/managed_mapped_file.hpp deleted file mode 100644 index daca6adaa0d..00000000000 --- a/extern/boost/boost/interprocess/managed_mapped_file.hpp +++ /dev/null @@ -1,370 +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_MANAGED_MAPPED_FILE_HPP -#define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -struct mfile_open_or_create -{ - static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of - < segment_manager - < CharType - , AllocationAlgorithm - , IndexType> - >::value; - static const std::size_t final_segment_manager_alignment - = segment_manager_alignment > AllocationAlgorithm::Alignment - ? segment_manager_alignment : AllocationAlgorithm::Alignment; - - typedef ipcdetail::managed_open_or_create_impl - < file_wrapper - , final_segment_manager_alignment - , true - , false> type; -}; - -} //namespace ipcdetail { - -//!A basic mapped file named object creation class. Initializes the -//!mapped file. Inherits all basic functionality from -//!basic_managed_memory_impl -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_mapped_file - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - : public ipcdetail::basic_managed_memory_impl - < CharType, AllocationAlgorithm, IndexType - , ipcdetail::mfile_open_or_create - ::type::ManagedOpenOrCreateUserOffset> - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - public: - typedef ipcdetail::basic_managed_memory_impl - - ::type::ManagedOpenOrCreateUserOffset> base_t; - typedef ipcdetail::file_wrapper device_type; - - private: - - typedef ipcdetail::create_open_func create_open_func_t; - - basic_managed_mapped_file *get_this_pointer() - { return this; } - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_mapped_file) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - - //!Unsigned integral type enough to represent - //!the size of a basic_managed_mapped_file. - typedef typename BOOST_INTERPROCESS_IMPDEF(base_t::size_type) size_type; - - //!Creates mapped file and creates and places the segment manager. - //!This can throw. - basic_managed_mapped_file() BOOST_NOEXCEPT - {} - - //!Creates mapped file and creates and places the segment manager. - //!This can throw. - basic_managed_mapped_file(create_only_t, const char *name, - size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_mfile(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates mapped file and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - basic_managed_mapped_file (open_or_create_t, - const char *name, size_type size, - const void *addr = 0, const permissions &perm = permissions()) - : m_mfile(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created mapped file and its segment manager. - //!This can throw. - basic_managed_mapped_file (open_only_t, const char* name, - const void *addr = 0) - : m_mfile(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created mapped file and its segment manager - //!in copy_on_write mode. - //!This can throw. - basic_managed_mapped_file (open_copy_on_write_t, const char* name, - const void *addr = 0) - : m_mfile(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created mapped file and its segment manager - //!in read-only mode. - //!This can throw. - basic_managed_mapped_file (open_read_only_t, const char* name, - const void *addr = 0) - : m_mfile(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates mapped file and creates and places the segment manager. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_mapped_file(create_only_t, const wchar_t *name, - size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_mfile(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates mapped file and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_mapped_file (open_or_create_t, - const wchar_t *name, size_type size, - const void *addr = 0, const permissions &perm = permissions()) - : m_mfile(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created mapped file and its segment manager. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_mapped_file (open_only_t, const wchar_t* name, - const void *addr = 0) - : m_mfile(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created mapped file and its segment manager - //!in copy_on_write mode. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_mapped_file (open_copy_on_write_t, const wchar_t* name, - const void *addr = 0) - : m_mfile(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created mapped file and its segment manager - //!in read-only mode. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_mapped_file (open_read_only_t, const wchar_t* name, - const void *addr = 0) - : m_mfile(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT - { - this->swap(moved); - } - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_mapped_file &operator=(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT - { - basic_managed_mapped_file tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~basic_managed_mapped_file() - {} - - //!Swaps the ownership of the managed mapped memories managed by *this and other. - //!Never throws. - void swap(basic_managed_mapped_file &other) BOOST_NOEXCEPT - { - base_t::swap(other); - m_mfile.swap(other.m_mfile); - } - - //!Flushes cached data to file. - //!Never throws - bool flush() - { return m_mfile.flush(); } - - //!Tries to resize mapped file so that we have room for - //!more objects. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - static bool grow(const char *filename, size_type extra_bytes) - { - return base_t::template grow - (filename, extra_bytes); - } - - //!Tries to resize mapped file to minimized the size of the file. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - static bool shrink_to_fit(const char *filename) - { - return base_t::template shrink_to_fit - (filename); - } - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to resize mapped file so that we have room for - //!more objects. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - static bool grow(const wchar_t *filename, size_type extra_bytes) - { - return base_t::template grow - (filename, extra_bytes); - } - - //!Tries to resize mapped file to minimized the size of the file. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - static bool shrink_to_fit(const wchar_t *filename) - { - return base_t::template shrink_to_fit - (filename); - } - - #endif - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find (char_ptr_holder_t name) - { - if(m_mfile.get_mapped_region().get_mode() == read_only){ - return base_t::template find_no_lock(name); - } - else{ - return base_t::template find(name); - } - } - - private: - typename ipcdetail::mfile_open_or_create - ::type m_mfile; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_mapped_file -//!of narrow characters -typedef basic_managed_mapped_file - - ,iset_index> -managed_mapped_file; - -//!Typedef for a default basic_managed_mapped_file -//!of wide characters -typedef basic_managed_mapped_file - - ,iset_index> -wmanaged_mapped_file; - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP diff --git a/extern/boost/boost/interprocess/managed_shared_memory.hpp b/extern/boost/boost/interprocess/managed_shared_memory.hpp deleted file mode 100644 index 4e77c2a01e0..00000000000 --- a/extern/boost/boost/interprocess/managed_shared_memory.hpp +++ /dev/null @@ -1,388 +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_MANAGED_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include - -namespace boost { -namespace interprocess { - -namespace ipcdetail { - -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -struct shmem_open_or_create -{ - static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of - < segment_manager - < CharType - , AllocationAlgorithm - , IndexType> - >::value; - static const std::size_t final_segment_manager_alignment - = segment_manager_alignment > AllocationAlgorithm::Alignment - ? segment_manager_alignment : AllocationAlgorithm::Alignment; - - typedef ipcdetail::managed_open_or_create_impl - < shared_memory_object - , final_segment_manager_alignment - , true - , false> type; -}; - -} //namespace ipcdetail { - -//!A basic shared memory named object creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from -//!basic_managed_memory_impl*/ -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_shared_memory - : public ipcdetail::basic_managed_memory_impl - < CharType, AllocationAlgorithm, IndexType - , ipcdetail::shmem_open_or_create::type::ManagedOpenOrCreateUserOffset> - , private ipcdetail::shmem_open_or_create::type -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef typename ipcdetail::shmem_open_or_create - < CharType - , AllocationAlgorithm - , IndexType>::type base2_t; - typedef ipcdetail::basic_managed_memory_impl - base_t; - - typedef ipcdetail::create_open_func create_open_func_t; - - basic_managed_shared_memory *get_this_pointer() - { return this; } - - public: - typedef shared_memory_object device_type; - typedef typename base_t::size_type size_type; - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~basic_managed_shared_memory() - {} - - //!Default constructor. Does nothing. - //!Useful in combination with move semantics - basic_managed_shared_memory() - {} - - //!Creates shared memory and creates and places the segment manager. - //!This can throw. - basic_managed_shared_memory(create_only_t, const char *name, - size_type size, const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates shared memory and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - basic_managed_shared_memory (open_or_create_t, - const char *name, size_type size, - const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created shared memory and its segment manager. - //!in copy_on_write mode. - //!This can throw. - basic_managed_shared_memory (open_copy_on_write_t, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!in read-only mode. - //!This can throw. - basic_managed_shared_memory (open_read_only_t, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!This can throw. - basic_managed_shared_memory (open_only_t, const char* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates shared memory and creates and places the segment manager. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_shared_memory(create_only_t, const wchar_t *name, - size_type size, const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates shared memory and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_shared_memory (open_or_create_t, - const wchar_t *name, size_type size, - const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created shared memory and its segment manager. - //!in copy_on_write mode. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_shared_memory (open_copy_on_write_t, const wchar_t* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!in read-only mode. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_shared_memory (open_read_only_t, const wchar_t* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!This can throw. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - basic_managed_shared_memory (open_only_t, const wchar_t* name, - const void *addr = 0) - : base_t() - , base2_t(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved) - { - basic_managed_shared_memory tmp; - this->swap(moved); - tmp.swap(moved); - } - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_shared_memory &operator=(BOOST_RV_REF(basic_managed_shared_memory) moved) - { - basic_managed_shared_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps the ownership of the managed shared memories managed by *this and other. - //!Never throws. - void swap(basic_managed_shared_memory &other) - { - base_t::swap(other); - base2_t::swap(other); - } - - //!Tries to resize the managed shared memory object so that we have - //!room for more objects. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - static bool grow(const char *shmname, size_type extra_bytes) - { - return base_t::template grow - (shmname, extra_bytes); - } - - //!Tries to resize the managed shared memory to minimized the size of the file. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - static bool shrink_to_fit(const char *shmname) - { - return base_t::template shrink_to_fit - (shmname); - } - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to resize the managed shared memory object so that we have - //!room for more objects. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - static bool grow(const wchar_t *shmname, size_type extra_bytes) - { - return base_t::template grow - (shmname, extra_bytes); - } - - //!Tries to resize the managed shared memory to minimized the size of the file. - //! - //!This function is not synchronized so no other thread or process should - //!be reading or writing the file - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - static bool shrink_to_fit(const wchar_t *shmname) - { - return base_t::template shrink_to_fit - (shmname); - } - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find (char_ptr_holder_t name) - { - if(base2_t::get_mapped_region().get_mode() == read_only){ - return base_t::template find_no_lock(name); - } - else{ - return base_t::template find(name); - } - } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_shared_memory -//!of narrow characters -typedef basic_managed_shared_memory - - ,iset_index> -managed_shared_memory; - -//!Typedef for a default basic_managed_shared_memory -//!of wide characters -typedef basic_managed_shared_memory - - ,iset_index> -wmanaged_shared_memory; - -//!Typedef for a default basic_managed_shared_memory -//!of narrow characters to be placed in a fixed address -typedef basic_managed_shared_memory - - ,iset_index> -fixed_managed_shared_memory; - -//!Typedef for a default basic_managed_shared_memory -//!of narrow characters to be placed in a fixed address -typedef basic_managed_shared_memory - - ,iset_index> -wfixed_managed_shared_memory; - - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP - diff --git a/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp b/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp deleted file mode 100644 index 07997b52d61..00000000000 --- a/extern/boost/boost/interprocess/managed_windows_shared_memory.hpp +++ /dev/null @@ -1,288 +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_MANAGED_WINDOWS_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include -#include - -namespace boost { -namespace interprocess { - -namespace ipcdetail { - -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -struct wshmem_open_or_create -{ - static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of - < segment_manager - < CharType - , AllocationAlgorithm - , IndexType> - >::value; - static const std::size_t final_segment_manager_alignment - = segment_manager_alignment > AllocationAlgorithm::Alignment - ? segment_manager_alignment : AllocationAlgorithm::Alignment; - - typedef ipcdetail::managed_open_or_create_impl - < windows_shared_memory - , final_segment_manager_alignment - , false - , false> type; -}; - - -} //namespace ipcdetail { - -//!A basic managed windows shared memory creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from -//!basic_managed_memory_impl -//!Unlike basic_managed_shared_memory, it has -//!no kernel persistence and the shared memory is destroyed -//!when all processes destroy all their windows_shared_memory -//!objects and mapped regions for the same shared memory -//!or the processes end/crash. -//! -//!Warning: basic_managed_windows_shared_memory and -//!basic_managed_shared_memory can't communicate between them. -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_windows_shared_memory - : public ipcdetail::basic_managed_memory_impl - < CharType, AllocationAlgorithm, IndexType - , ipcdetail::wshmem_open_or_create - ::type::ManagedOpenOrCreateUserOffset> -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef ipcdetail::basic_managed_memory_impl - < CharType, AllocationAlgorithm, IndexType - , ipcdetail::wshmem_open_or_create - ::type::ManagedOpenOrCreateUserOffset> base_t; - typedef ipcdetail::create_open_func create_open_func_t; - - basic_managed_windows_shared_memory *get_this_pointer() - { return this; } - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_windows_shared_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - typedef typename base_t::size_type size_type; - - //!Default constructor. Does nothing. - //!Useful in combination with move semantics - basic_managed_windows_shared_memory() BOOST_NOEXCEPT - {} - - //!Creates shared memory and creates and places the segment manager. - //!This can throw. - basic_managed_windows_shared_memory - (create_only_t, const char *name, - size_type size, const void *addr = 0, const permissions &perm = permissions()) - : m_wshm(create_only, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates shared memory and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - basic_managed_windows_shared_memory - (open_or_create_t, - const char *name, size_type size, - const void *addr = 0, - const permissions &perm = permissions()) - : m_wshm(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created shared memory and its segment manager. - //!This can throw. - basic_managed_windows_shared_memory - (open_only_t, const char* name, const void *addr = 0) - : m_wshm(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager - //!in copy_on_write mode. - //!This can throw. - basic_managed_windows_shared_memory - (open_copy_on_write_t, const char* name, const void *addr = 0) - : m_wshm(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager - //!in read-only mode. - //!This can throw. - basic_managed_windows_shared_memory - (open_read_only_t, const char* name, const void *addr = 0) - : base_t() - , m_wshm(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) - {} - - //!Creates shared memory and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - basic_managed_windows_shared_memory - (open_or_create_t, - const wchar_t *name, size_type size, - const void *addr = 0, - const permissions &perm = permissions()) - : m_wshm(open_or_create, name, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created shared memory and its segment manager. - //!This can throw. - basic_managed_windows_shared_memory - (open_only_t, const wchar_t* name, const void *addr = 0) - : m_wshm(open_only, name, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager - //!in copy_on_write mode. - //!This can throw. - basic_managed_windows_shared_memory - (open_copy_on_write_t, const wchar_t* name, const void *addr = 0) - : m_wshm(open_only, name, copy_on_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager - //!in read-only mode. - //!This can throw. - basic_managed_windows_shared_memory - (open_read_only_t, const wchar_t* name, const void *addr = 0) - : base_t() - , m_wshm(open_only, name, read_only, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) - {} - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_windows_shared_memory - (BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT - { this->swap(moved); } - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_windows_shared_memory &operator=(BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT - { - basic_managed_windows_shared_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. All mapped regions are still valid after - //!destruction. When all mapped regions and basic_managed_windows_shared_memory - //!objects referring the shared memory are destroyed, the - //!operating system will destroy the shared memory. - ~basic_managed_windows_shared_memory() - {} - - //!Swaps the ownership of the managed mapped memories managed by *this and other. - //!Never throws. - void swap(basic_managed_windows_shared_memory &other) BOOST_NOEXCEPT - { - base_t::swap(other); - m_wshm.swap(other.m_wshm); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find (char_ptr_holder_t name) - { - if(m_wshm.get_mapped_region().get_mode() == read_only){ - return base_t::template find_no_lock(name); - } - else{ - return base_t::template find(name); - } - } - - private: - typename ipcdetail::wshmem_open_or_create - ::type m_wshm; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_windows_shared_memory -//!of narrow characters -typedef basic_managed_windows_shared_memory - - ,iset_index> -managed_windows_shared_memory; - -//!Typedef for a default basic_managed_windows_shared_memory -//!of wide characters -typedef basic_managed_windows_shared_memory - - ,iset_index> -wmanaged_windows_shared_memory; - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp b/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp deleted file mode 100644 index 3c51294e79b..00000000000 --- a/extern/boost/boost/interprocess/managed_xsi_shared_memory.hpp +++ /dev/null @@ -1,251 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_MANAGED_XSI_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) -#error "This header can't be used in operating systems without XSI (System V) shared memory support" -#endif - -#include -#include -#include -#include -//These includes needed to fulfill default template parameters of -//predeclarations in interprocess_fwd.hpp -#include -#include -#include - -namespace boost { - -namespace interprocess { - -namespace ipcdetail { - -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -struct xsishmem_open_or_create -{ - static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of - < segment_manager - < CharType - , AllocationAlgorithm - , IndexType> - >::value; - static const std::size_t final_segment_manager_alignment - = segment_manager_alignment > AllocationAlgorithm::Alignment - ? segment_manager_alignment : AllocationAlgorithm::Alignment; - - typedef ipcdetail::managed_open_or_create_impl - < xsi_shared_memory_file_wrapper - , final_segment_manager_alignment - , false - , true> type; -}; - - -} //namespace ipcdetail { - -//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the -//!shared memory segment. Inherits all basic functionality from -//!basic_managed_memory_impl -template - < - class CharType, - class AllocationAlgorithm, - template class IndexType - > -class basic_managed_xsi_shared_memory - : public ipcdetail::basic_managed_memory_impl - - ::type::ManagedOpenOrCreateUserOffset> - , private ipcdetail::xsishmem_open_or_create - ::type -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - public: - typedef xsi_shared_memory_file_wrapper device_type; - - public: - typedef typename ipcdetail::xsishmem_open_or_create - ::type base2_t; - typedef ipcdetail::basic_managed_memory_impl - base_t; - - typedef ipcdetail::create_open_func create_open_func_t; - - basic_managed_xsi_shared_memory *get_this_pointer() - { return this; } - - private: - typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: //functions - typedef typename base_t::size_type size_type; - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~basic_managed_xsi_shared_memory() - {} - - //!Default constructor. Does nothing. - //!Useful in combination with move semantics - basic_managed_xsi_shared_memory() BOOST_NOEXCEPT - {} - - //!Creates shared memory and creates and places the segment manager. - //!This can throw. - basic_managed_xsi_shared_memory(create_only_t, const xsi_key &key, - std::size_t size, const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(create_only, key, size, read_write, addr, - create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) - {} - - //!Creates shared memory and creates and places the segment manager if - //!segment was not created. If segment was created it connects to the - //!segment. - //!This can throw. - basic_managed_xsi_shared_memory (open_or_create_t, - const xsi_key &key, std::size_t size, - const void *addr = 0, const permissions& perm = permissions()) - : base_t() - , base2_t(open_or_create, key, size, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpenOrCreate), perm) - {} - - //!Connects to a created shared memory and its segment manager. - //!in read-only mode. - //!This can throw. - basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key, - const void *addr = 0) - : base_t() - , base2_t(open_only, key, read_only, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Connects to a created shared memory and its segment manager. - //!This can throw. - basic_managed_xsi_shared_memory (open_only_t, const xsi_key &key, - const void *addr = 0) - : base_t() - , base2_t(open_only, key, read_write, addr, - create_open_func_t(get_this_pointer(), - ipcdetail::DoOpen)) - {} - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_xsi_shared_memory(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT - { - basic_managed_xsi_shared_memory tmp; - this->swap(moved); - tmp.swap(moved); - } - - //!Moves the ownership of "moved"'s managed memory to *this. - //!Does not throw - basic_managed_xsi_shared_memory &operator=(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT - { - basic_managed_xsi_shared_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps the ownership of the managed shared memories managed by *this and other. - //!Never throws. - void swap(basic_managed_xsi_shared_memory &other) BOOST_NOEXCEPT - { - base_t::swap(other); - base2_t::swap(other); - } - - //!Erases a XSI shared memory object identified by shmid - //!from the system. - //!Returns false on error. Never throws - static bool remove(int shmid) - { return device_type::remove(shmid); } - - int get_shmid() const BOOST_NOEXCEPT - { return base2_t::get_device().get_shmid(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Tries to find a previous named allocation address. Returns a memory - //!buffer and the object count. If not found returned pointer is 0. - //!Never throws. - template - std::pair find (char_ptr_holder_t name) - { - if(base2_t::get_mapped_region().get_mode() == read_only){ - return base_t::template find_no_lock(name); - } - else{ - return base_t::template find(name); - } - } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!Typedef for a default basic_managed_xsi_shared_memory -//!of narrow characters -typedef basic_managed_xsi_shared_memory - - ,iset_index> -managed_xsi_shared_memory; - -//!Typedef for a default basic_managed_xsi_shared_memory -//!of wide characters -typedef basic_managed_xsi_shared_memory - - ,iset_index> -wmanaged_xsi_shared_memory; - -#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP - diff --git a/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp deleted file mode 100644 index c036ce94903..00000000000 --- a/extern/boost/boost/interprocess/mem_algo/detail/mem_algo_common.hpp +++ /dev/null @@ -1,599 +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_MEM_ALGO_COMMON_HPP -#define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess -#include -#include -// interprocess/detail -#include -#include -#include -#include -// container/detail -#include -#include -// move -#include -// move/detail -#include -// other boost -#include -#include - -//!\file -//!Implements common operations for memory algorithms. - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template -class basic_multiallocation_chain - : public boost::container::dtl:: - basic_multiallocation_chain -{ - BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) - typedef boost::container::dtl:: - basic_multiallocation_chain base_t; - public: - - basic_multiallocation_chain() - : base_t() - {} - - basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) - : base_t(::boost::move(static_cast(other))) - {} - - basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) - { - this->base_t::operator=(::boost::move(static_cast(other))); - return *this; - } - - void *pop_front() - { - return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front()); - } -}; - - -//!This class implements several allocation functions shared by different algorithms -//!(aligned allocation, multiple allocation...). -template -class memory_algorithm_common -{ - public: - typedef typename MemoryAlgorithm::void_pointer void_pointer; - typedef typename MemoryAlgorithm::block_ctrl block_ctrl; - typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; - typedef memory_algorithm_common this_type; - typedef typename MemoryAlgorithm::size_type size_type; - - static const size_type Alignment = MemoryAlgorithm::Alignment; - static const size_type MinBlockUnits = MemoryAlgorithm::MinBlockUnits; - static const size_type AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes; - static const size_type AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits; - static const size_type BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes; - static const size_type BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits; - static const size_type UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk; - - static void assert_alignment(const void *ptr) - { assert_alignment((std::size_t)ptr); } - - static void assert_alignment(size_type uint_ptr) - { - (void)uint_ptr; - BOOST_ASSERT(uint_ptr % Alignment == 0); - } - - static bool check_alignment(const void *ptr) - { return (((std::size_t)ptr) % Alignment == 0); } - - static size_type ceil_units(size_type size) - { return get_rounded_size(size, Alignment)/Alignment; } - - static size_type floor_units(size_type size) - { return size/Alignment; } - - static size_type multiple_of_units(size_type size) - { return get_rounded_size(size, Alignment); } - - static void allocate_many - (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) - { - return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain); - } - - static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) - { - return this_type::priv_deallocate_many(memory_algo, chain); - } - - static bool calculate_lcm_and_needs_backwards_lcmed - (size_type backwards_multiple, size_type received_size, size_type size_to_achieve, - size_type &lcm_out, size_type &needs_backwards_lcmed_out) - { - // Now calculate lcm_val - size_type max = backwards_multiple; - size_type min = Alignment; - size_type needs_backwards; - size_type needs_backwards_lcmed; - size_type lcm_val; - size_type current_forward; - //Swap if necessary - if(max < min){ - size_type tmp = min; - min = max; - max = tmp; - } - //Check if it's power of two - if((backwards_multiple & (backwards_multiple-1)) == 0){ - if(0 != (size_to_achieve & ((backwards_multiple-1)))){ - return false; - } - - lcm_val = max; - //If we want to use minbytes data to get a buffer between maxbytes - //and minbytes if maxbytes can't be achieved, calculate the - //biggest of all possibilities - current_forward = get_truncated_size_po2(received_size, backwards_multiple); - needs_backwards = size_to_achieve - current_forward; - BOOST_ASSERT((needs_backwards % backwards_multiple) == 0); - needs_backwards_lcmed = get_rounded_size_po2(needs_backwards, lcm_val); - lcm_out = lcm_val; - needs_backwards_lcmed_out = needs_backwards_lcmed; - return true; - } - //Check if it's multiple of alignment - else if((backwards_multiple & (Alignment - 1u)) == 0){ - lcm_val = backwards_multiple; - current_forward = get_truncated_size(received_size, backwards_multiple); - //No need to round needs_backwards because backwards_multiple == lcm_val - needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; - BOOST_ASSERT((needs_backwards_lcmed & (Alignment - 1u)) == 0); - lcm_out = lcm_val; - needs_backwards_lcmed_out = needs_backwards_lcmed; - return true; - } - //Check if it's multiple of the half of the alignmment - else if((backwards_multiple & ((Alignment/2u) - 1u)) == 0){ - lcm_val = backwards_multiple*2u; - current_forward = get_truncated_size(received_size, backwards_multiple); - needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; - if(0 != (needs_backwards_lcmed & (Alignment-1))) - //while(0 != (needs_backwards_lcmed & (Alignment-1))) - needs_backwards_lcmed += backwards_multiple; - BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0); - lcm_out = lcm_val; - needs_backwards_lcmed_out = needs_backwards_lcmed; - return true; - } - //Check if it's multiple of the quarter of the alignmment - else if((backwards_multiple & ((Alignment/4u) - 1u)) == 0){ - size_type remainder; - lcm_val = backwards_multiple*4u; - current_forward = get_truncated_size(received_size, backwards_multiple); - needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; - //while(0 != (needs_backwards_lcmed & (Alignment-1))) - //needs_backwards_lcmed += backwards_multiple; - if(0 != (remainder = ((needs_backwards_lcmed & (Alignment-1))>>(Alignment/8u)))){ - if(backwards_multiple & Alignment/2u){ - needs_backwards_lcmed += (remainder)*backwards_multiple; - } - else{ - needs_backwards_lcmed += (4-remainder)*backwards_multiple; - } - } - BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0); - lcm_out = lcm_val; - needs_backwards_lcmed_out = needs_backwards_lcmed; - return true; - } - else{ - lcm_val = lcm(max, min); - } - //If we want to use minbytes data to get a buffer between maxbytes - //and minbytes if maxbytes can't be achieved, calculate the - //biggest of all possibilities - current_forward = get_truncated_size(received_size, backwards_multiple); - needs_backwards = size_to_achieve - current_forward; - BOOST_ASSERT((needs_backwards % backwards_multiple) == 0); - needs_backwards_lcmed = get_rounded_size(needs_backwards, lcm_val); - lcm_out = lcm_val; - needs_backwards_lcmed_out = needs_backwards_lcmed; - return true; - } - - static void allocate_many - ( MemoryAlgorithm *memory_algo - , const size_type *elem_sizes - , size_type n_elements - , size_type sizeof_element - , multiallocation_chain &chain) - { - this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain); - } - - static void* allocate_aligned - (MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment) - { - - //Ensure power of 2 - if ((alignment & (alignment - size_type(1u))) != 0){ - //Alignment is not power of two - BOOST_ASSERT((alignment & (alignment - size_type(1u))) == 0); - return 0; - } - - size_type real_size = nbytes; - if(alignment <= Alignment){ - void *ignore_reuse = 0; - return memory_algo->priv_allocate - (boost::interprocess::allocate_new, nbytes, real_size, ignore_reuse); - } - - if(nbytes > UsableByPreviousChunk) - nbytes -= UsableByPreviousChunk; - - //We can find a aligned portion if we allocate a block that has alignment - //nbytes + alignment bytes or more. - size_type minimum_allocation = max_value - (nbytes + alignment, size_type(MinBlockUnits*Alignment)); - //Since we will split that block, we must request a bit more memory - //if the alignment is near the beginning of the buffer, because otherwise, - //there is no space for a new block before the alignment. - // - // ____ Aligned here - // | - // ----------------------------------------------------- - // | MBU | - // ----------------------------------------------------- - size_type request = - minimum_allocation + (2*MinBlockUnits*Alignment - AllocatedCtrlBytes - //prevsize - UsableByPreviousChunk - ); - - //Now allocate the buffer - real_size = request; - void *ignore_reuse = 0; - void *buffer = memory_algo->priv_allocate(boost::interprocess::allocate_new, request, real_size, ignore_reuse); - if(!buffer){ - return 0; - } - else if ((((std::size_t)(buffer)) % alignment) == 0){ - //If we are lucky and the buffer is aligned, just split it and - //return the high part - block_ctrl *first = memory_algo->priv_get_block(buffer); - size_type old_size = first->m_size; - const size_type first_min_units = - 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 = move_detail::force_ptr - (reinterpret_cast(first) + Alignment*first_min_units); - 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); - memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second)); - } - return buffer; - } - - //Buffer not aligned, find the aligned part. - // - // ____ Aligned here - // | - // ----------------------------------------------------- - // | MBU +more | ACB | - // ----------------------------------------------------- - char *pos = reinterpret_cast - (reinterpret_cast(static_cast(buffer) + - //This is the minimum size of (2) - (MinBlockUnits*Alignment - AllocatedCtrlBytes) + - //This is the next MBU for the aligned memory - AllocatedCtrlBytes + - //This is the alignment trick - alignment - 1) & -alignment); - - //Now obtain the address of the blocks - block_ctrl *first = memory_algo->priv_get_block(buffer); - block_ctrl *second = memory_algo->priv_get_block(pos); - BOOST_ASSERT(pos <= (reinterpret_cast(first) + first->m_size*Alignment)); - BOOST_ASSERT(first->m_size >= 2*MinBlockUnits); - BOOST_ASSERT((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <= - (reinterpret_cast(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(size_type(reinterpret_cast(second) - reinterpret_cast(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 - // - // __"second" block - // | __Aligned here - // | | __"third" block - // -----------|-----|-----|------------------------------ - // | MBU +more | ACB | (3) | BCU | - // ----------------------------------------------------- - //This size will be the minimum size to be able to create a - //new block in the end. - const size_type second_min_units = max_value(size_type(MinBlockUnits), - ceil_units(nbytes) + AllocatedCtrlUnits ); - - //Check if we can create a new block (of size MinBlockUnits) in the end of the segment - if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){ - //Now obtain the address of the end block - block_ctrl *third = new (reinterpret_cast(second) + Alignment*second_min_units)block_ctrl; - 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) & block_ctrl::size_mask; - BOOST_ASSERT(second->m_size >= MinBlockUnits); - memory_algo->priv_mark_new_allocated_block(second); - } - - memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(first)); - return memory_algo->priv_get_user_buffer(second); - } - - static bool try_shrink - (MemoryAlgorithm *memory_algo, void *ptr - ,const size_type max_size, size_type &received_size) - { - size_type const preferred_size = received_size; - (void)memory_algo; - //Obtain the real block - block_ctrl *block = memory_algo->priv_get_block(ptr); - size_type old_block_units = (size_type)block->m_size; - - //The block must be marked as allocated - BOOST_ASSERT(memory_algo->priv_is_allocated_block(block)); - - //Check if alignment and block size are right - assert_alignment(ptr); - - //Put this to a safe value - received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; - - //Now translate it to Alignment units - const size_type max_user_units = floor_units(max_size - UsableByPreviousChunk); - const size_type preferred_user_units = ceil_units(preferred_size - UsableByPreviousChunk); - - //Check if rounded max and preferred are possible correct - if(max_user_units < preferred_user_units) - return false; - - //Check if the block is smaller than the requested minimum - size_type old_user_units = old_block_units - AllocatedCtrlUnits; - - if(old_user_units < preferred_user_units) - return false; - - //If the block is smaller than the requested minimum - if(old_user_units == preferred_user_units) - return true; - - size_type shrunk_user_units = - ((BlockCtrlUnits - AllocatedCtrlUnits) >= preferred_user_units) - ? (BlockCtrlUnits - AllocatedCtrlUnits) - : preferred_user_units; - - //Some parameter checks - if(max_user_units < shrunk_user_units) - return false; - - //We must be able to create at least a new empty block - if((old_user_units - shrunk_user_units) < BlockCtrlUnits ){ - return false; - } - - //Update new size - received_size = shrunk_user_units*Alignment + UsableByPreviousChunk; - return true; - } - - static bool shrink - (MemoryAlgorithm *memory_algo, void *ptr - ,const size_type max_size, size_type &received_size) - { - size_type const preferred_size = received_size; - //Obtain the real block - block_ctrl *block = memory_algo->priv_get_block(ptr); - size_type old_block_units = (size_type)block->m_size; - - if(!try_shrink(memory_algo, ptr, max_size, received_size)){ - return false; - } - - //Check if the old size was just the shrunk size (no splitting) - if((old_block_units - AllocatedCtrlUnits) == ceil_units(preferred_size - UsableByPreviousChunk)) - return true; - - //Now we can just rewrite the size of the old buffer - 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 = move_detail::force_ptr - (reinterpret_cast(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) & 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); - memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(new_block)); - return true; - } - - private: - static void priv_allocate_many - ( MemoryAlgorithm *memory_algo - , const size_type *elem_sizes - , size_type n_elements - , size_type sizeof_element - , multiallocation_chain &chain) - { - //Note: sizeof_element == 0 indicates that we want to - //allocate n_elements of the same size "*elem_sizes" - - //Calculate the total size of all requests - size_type total_request_units = 0; - size_type elem_units = 0; - const size_type ptr_size_units = memory_algo->priv_get_total_units(sizeof(void_pointer)); - if(!sizeof_element){ - elem_units = memory_algo->priv_get_total_units(*elem_sizes); - elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; - total_request_units = n_elements*elem_units; - } - else{ - for(size_type i = 0; i < n_elements; ++i){ - if(multiplication_overflows(elem_sizes[i], sizeof_element)){ - total_request_units = 0; - break; - } - elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element); - elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; - if(sum_overflows(total_request_units, elem_units)){ - total_request_units = 0; - break; - } - total_request_units += elem_units; - } - } - - if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){ - size_type low_idx = 0; - while(low_idx < n_elements){ - size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type min_allocation = (!sizeof_element) - ? elem_units - : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - - size_type received_size = total_bytes; - void *ignore_reuse = 0; - void *ret = memory_algo->priv_allocate - (boost::interprocess::allocate_new, min_allocation, received_size, ignore_reuse); - if(!ret){ - break; - } - - block_ctrl *block = memory_algo->priv_get_block(ret); - size_type received_units = (size_type)block->m_size; - char *block_address = reinterpret_cast(block); - - size_type total_used_units = 0; - while(total_used_units < received_units){ - if(sizeof_element){ - elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; - } - if(total_used_units + elem_units > received_units) - break; - total_request_units -= elem_units; - //This is the position where the new block must be created - block_ctrl *new_block = move_detail::force_ptr(block_address); - assert_alignment(new_block); - - //The last block should take all the remaining space - if((low_idx + 1) == n_elements || - (total_used_units + elem_units + - ((!sizeof_element) - ? elem_units - : 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) & block_ctrl::size_mask; - memory_algo->priv_mark_new_allocated_block(new_block); - - //If the remaining units are bigger than needed and we can - //split it obtaining a new free memory block do it. - if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ - size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type shrunk_received = shrunk_request; - bool shrink_ok = shrink - (memory_algo - ,memory_algo->priv_get_user_buffer(new_block) - ,shrunk_request - ,shrunk_received); - (void)shrink_ok; - //Shrink must always succeed with passed parameters - BOOST_ASSERT(shrink_ok); - //Some sanity checks - BOOST_ASSERT(shrunk_request == shrunk_received); - BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); - //"new_block->m_size" must have been reduced to elem_units by "shrink" - BOOST_ASSERT(new_block->m_size == elem_units); - //Now update the total received units with the reduction - received_units = elem_units + total_used_units; - } - } - else{ - new_block->m_size = elem_units & block_ctrl::size_mask; - memory_algo->priv_mark_new_allocated_block(new_block); - } - - block_address += new_block->m_size*Alignment; - total_used_units += (size_type)new_block->m_size; - //Check we have enough room to overwrite the intrusive pointer - BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); - void_pointer p = ::new(memory_algo->priv_get_user_buffer(new_block), boost_container_new_t())void_pointer(0); - chain.push_back(p); - ++low_idx; - } - //Sanity check - BOOST_ASSERT(total_used_units == received_units); - } - - if(low_idx != n_elements){ - priv_deallocate_many(memory_algo, chain); - } - } - } - - static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) - { - while(!chain.empty()){ - memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front())); - } - } -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP diff --git a/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp deleted file mode 100644 index 2c909acfe96..00000000000 --- a/extern/boost/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ /dev/null @@ -1,1107 +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_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP -#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include //make_unsigned, alignment_of -#include -#include -#include -#include - -//!\file -//!Describes sequential fit algorithm used to allocate objects in shared memory. -//!This class is intended as a base class for single segment and multi-segment -//!implementations. - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -//!This class implements the simple sequential fit algorithm with a simply -//!linked list of free buffers. -//!This class is intended as a base class for single segment and multi-segment -//!implementations. -template -class simple_seq_fit_impl -{ - //Non-copyable - simple_seq_fit_impl(); - simple_seq_fit_impl(const simple_seq_fit_impl &); - simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type char_ptr; - - public: - - //!Shared interprocess_mutex family used for the rest of the Interprocess framework - typedef MutexFamily mutex_family; - //!Pointer type to be used with the rest of the Interprocess framework - typedef VoidPointer void_pointer; - typedef boost::container::dtl:: - basic_multiallocation_chain multiallocation_chain; - - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::container::dtl::make_unsigned::type size_type; - - - private: - class block_ctrl; - friend class block_ctrl; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type block_ctrl_ptr; - - //!Block control structure - class block_ctrl - { - public: - static const size_type size_mask = size_type(-1); - //!Offset pointer to the next block. - block_ctrl_ptr m_next; - //!This block's memory size (including block_ctrl - //!header) in BasicSize units - size_type m_size; - - size_type get_user_bytes() const - { return this->m_size*Alignment - BlockCtrlBytes; } - - size_type get_total_bytes() const - { return this->m_size*Alignment; } - }; - - //!Shared interprocess_mutex to protect memory allocate/deallocate - typedef typename MutexFamily::mutex_type interprocess_mutex; - - //!This struct includes needed data and derives from - //!interprocess_mutex to allow EBO when using null interprocess_mutex - struct header_t : public interprocess_mutex - { - //!Pointer to the first free block - block_ctrl m_root; - //!Allocated bytes for internal checking - size_type m_allocated; - //!The size of the memory segment - size_type m_size; - //!The extra size required by the segment - size_type m_extra_hdr_bytes; - } m_header; - - friend class ipcdetail::memory_algorithm_common; - - typedef ipcdetail::memory_algorithm_common algo_impl_t; - - public: - //!Constructor. "size" is the total size of the managed memory segment, - //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) - //!offset that the allocator should not use at all. - simple_seq_fit_impl (size_type size, size_type extra_hdr_bytes); - - //!Destructor - ~simple_seq_fit_impl(); - - //!Obtains the minimum size needed by the algorithm - static size_type get_min_size (size_type extra_hdr_bytes); - - //Functions for single segment management - - //!Allocates bytes, returns 0 if there is not more memory - void* allocate (size_type nbytes); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Multiple element allocation, same size - void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); - } - - //!Multiple element allocation, different size - void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); - } - - //!Multiple element deallocation - void deallocate_many(multiallocation_chain &chain); - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Deallocates previously allocated bytes - void deallocate (void *addr); - - //!Returns the size of the memory segment - size_type get_size() const; - - //!Returns the number of free bytes of the memory segment - size_type get_free_memory() const; - - //!Increases managed memory in extra_size bytes more - void grow(size_type extra_size); - - //!Decreases managed memory as much as possible - void shrink_to_fit(); - - //!Returns true if all allocated memory has been deallocated - bool all_memory_deallocated(); - - //!Makes an internal sanity check and returns true if success - bool check_sanity(); - - //!Initializes to zero all the memory that's not in use. - //!This function is normally used for security reasons. - void zero_free_memory(); - - template - T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse); - - void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object = 1); - - //!Returns the size of the buffer previously allocated pointed by ptr - size_type size(const void *ptr) const; - - //!Allocates aligned bytes, returns 0 if there is not more memory. - //!Alignment must be power of 2 - void* allocate_aligned (size_type nbytes, size_type alignment); - - private: - - //!Obtains the pointer returned to the user from the block control - static void *priv_get_user_buffer(const block_ctrl *block); - - //!Obtains the block control structure of the user buffer - static block_ctrl *priv_get_block(const void *ptr); - - //!Real allocation algorithm with min allocation option - void * priv_allocate(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type &prefer_in_recvd_out_size, void *&reuse_ptr); - - void * priv_allocation_command(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type &prefer_in_recvd_out_size - ,void *&reuse_ptr - ,size_type sizeof_object); - - //!Returns the number of total units that a user buffer - //!of "userbytes" bytes really occupies (including header) - static size_type priv_get_total_units(size_type userbytes); - - static size_type priv_first_block_offset(const void *this_ptr, size_type extra_hdr_bytes); - size_type priv_block_end_offset() const; - - //!Returns next block if it's free. - //!Returns 0 if next block is not free. - block_ctrl *priv_next_block_if_free(block_ctrl *ptr); - - //!Check if this block is free (not allocated) - bool priv_is_allocated_block(block_ctrl *ptr); - - //!Returns previous block's if it's free. - //!Returns 0 if previous block is not free. - std::pair priv_prev_block_if_free(block_ctrl *ptr); - - //!Real expand function implementation - bool priv_expand(void *ptr, size_type min_size, size_type &prefer_in_recvd_out_size); - - //!Real expand to both sides implementation - void* priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size, size_type &prefer_in_recvd_out_size - ,void *reuse_ptr - ,bool only_preferred_backwards); - - //!Real private aligned allocation function - //void* priv_allocate_aligned (size_type nbytes, size_type alignment); - - //!Checks if block has enough memory and splits/unlinks the block - //!returning the address to the users - void* priv_check_and_allocate(size_type units - ,block_ctrl* prev - ,block_ctrl* block - ,size_type &received_size); - //!Real deallocation algorithm - void priv_deallocate(void *addr); - - //!Makes a new memory portion available for allocation - void priv_add_segment(void *addr, size_type size); - - void priv_mark_new_allocated_block(block_ctrl *block); - - public: - static const size_type Alignment = ::boost::container::dtl::alignment_of - < ::boost::container::dtl::max_align_t>::value; - private: - static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size::value; - static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; - static const size_type MinBlockUnits = BlockCtrlUnits; - static const size_type MinBlockSize = MinBlockUnits*Alignment; - static const size_type AllocatedCtrlBytes = BlockCtrlBytes; - static const size_type AllocatedCtrlUnits = BlockCtrlUnits; - static const size_type UsableByPreviousChunk = 0; - - public: - static const size_type PayloadPerAllocation = BlockCtrlBytes; -}; - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl - ::priv_first_block_offset(const void *this_ptr, size_type extra_hdr_bytes) -{ - //First align "this" pointer - size_type uint_this = (std::size_t)this_ptr; - size_type uint_aligned_this = uint_this/Alignment*Alignment; - size_type this_disalignment = (uint_this - uint_aligned_this); - size_type block1_off = - ipcdetail::get_rounded_size(sizeof(simple_seq_fit_impl) + extra_hdr_bytes + this_disalignment, Alignment) - - this_disalignment; - algo_impl_t::assert_alignment(this_disalignment + block1_off); - return block1_off; -} - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl - ::priv_block_end_offset() const -{ - //First align "this" pointer - size_type uint_this = (std::size_t)this; - size_type uint_aligned_this = uint_this/Alignment*Alignment; - size_type this_disalignment = (uint_this - uint_aligned_this); - size_type old_end = - ipcdetail::get_truncated_size(m_header.m_size + this_disalignment, Alignment) - - this_disalignment; - algo_impl_t::assert_alignment(old_end + this_disalignment); - return old_end; -} - -template -inline simple_seq_fit_impl:: - simple_seq_fit_impl(size_type segment_size, size_type extra_hdr_bytes) -{ - //Initialize sizes and counters - m_header.m_allocated = 0; - m_header.m_size = segment_size; - m_header.m_extra_hdr_bytes = extra_hdr_bytes; - - //Initialize pointers - size_type block1_off = priv_first_block_offset(this, extra_hdr_bytes); - - m_header.m_root.m_next = move_detail::force_ptr - ((reinterpret_cast(this) + block1_off)); - algo_impl_t::assert_alignment(ipcdetail::to_raw_pointer(m_header.m_root.m_next)); - m_header.m_root.m_next->m_size = (segment_size - block1_off)/Alignment; - m_header.m_root.m_next->m_next = &m_header.m_root; -} - -template -inline simple_seq_fit_impl::~simple_seq_fit_impl() -{ - //There is a memory leak! -// BOOST_ASSERT(m_header.m_allocated == 0); -// BOOST_ASSERT(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); -} - -template -inline void simple_seq_fit_impl::grow(size_type extra_size) -{ - //Old highest address block's end offset - size_type old_end = this->priv_block_end_offset(); - - //Update managed buffer's size - m_header.m_size += extra_size; - - //We need at least MinBlockSize blocks to create a new block - if((m_header.m_size - old_end) < MinBlockSize){ - return; - } - - //We'll create a new free block with extra_size bytes - - block_ctrl *new_block = move_detail::force_ptr - (reinterpret_cast(this) + old_end); - - algo_impl_t::assert_alignment(new_block); - new_block->m_next = 0; - new_block->m_size = (m_header.m_size - old_end)/Alignment; - m_header.m_allocated += new_block->m_size*Alignment; - this->priv_deallocate(priv_get_user_buffer(new_block)); -} - -template -void simple_seq_fit_impl::shrink_to_fit() -{ - //Get the root and the first memory block - block_ctrl *prev = &m_header.m_root; - block_ctrl *last = &m_header.m_root; - block_ctrl *block = ipcdetail::to_raw_pointer(last->m_next); - block_ctrl *root = &m_header.m_root; - - //No free block? - if(block == root) return; - - //Iterate through the free block list - while(block != root){ - prev = last; - last = block; - block = ipcdetail::to_raw_pointer(block->m_next); - } - - char *last_free_end_address = reinterpret_cast(last) + last->m_size*Alignment; - if(last_free_end_address != (reinterpret_cast(this) + priv_block_end_offset())){ - //there is an allocated block in the end of this block - //so no shrinking is possible - return; - } - - //Check if have only 1 big free block - void *unique_block = 0; - if(!m_header.m_allocated){ - BOOST_ASSERT(prev == root); - size_type ignore_recvd = 0; - void *ignore_reuse = 0; - unique_block = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); - if(!unique_block) - return; - last = ipcdetail::to_raw_pointer(m_header.m_root.m_next); - BOOST_ASSERT(last_free_end_address == (reinterpret_cast(last) + last->m_size*Alignment)); - } - size_type last_units = last->m_size; - - size_type received_size; - void *addr = priv_check_and_allocate(last_units, prev, last, received_size); - (void)addr; - BOOST_ASSERT(addr); - BOOST_ASSERT(received_size == last_units*Alignment - AllocatedCtrlBytes); - - //Shrink it - m_header.m_size /= Alignment; - m_header.m_size -= last->m_size; - m_header.m_size *= Alignment; - m_header.m_allocated -= last->m_size*Alignment; - - if(unique_block) - priv_deallocate(unique_block); -} - -template -inline void simple_seq_fit_impl:: - priv_mark_new_allocated_block(block_ctrl *new_block) -{ - new_block->m_next = 0; -} - -template -inline -typename simple_seq_fit_impl::block_ctrl * - simple_seq_fit_impl::priv_get_block(const void *ptr) -{ - return const_cast(move_detail::force_ptr - (reinterpret_cast(ptr) - AllocatedCtrlBytes)); -} - -template -inline -void *simple_seq_fit_impl:: - priv_get_user_buffer(const typename simple_seq_fit_impl::block_ctrl *block) -{ - return const_cast(reinterpret_cast(block) + AllocatedCtrlBytes); -} - -template -inline void simple_seq_fit_impl::priv_add_segment(void *addr, size_type segment_size) -{ - algo_impl_t::assert_alignment(addr); - //Check size - BOOST_ASSERT(!(segment_size < MinBlockSize)); - if(segment_size < MinBlockSize) - return; - //Construct big block using the new segment - block_ctrl *new_block = static_cast(addr); - new_block->m_size = segment_size/Alignment; - new_block->m_next = 0; - //Simulate this block was previously allocated - m_header.m_allocated += new_block->m_size*Alignment; - //Return block and insert it in the free block list - this->priv_deallocate(priv_get_user_buffer(new_block)); -} - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl::get_size() const - { return m_header.m_size; } - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl::get_free_memory() const -{ - return m_header.m_size - m_header.m_allocated - - algo_impl_t::multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes); -} - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl:: - get_min_size (size_type extra_hdr_bytes) -{ - return ipcdetail::get_rounded_size((size_type)sizeof(simple_seq_fit_impl),Alignment) + - ipcdetail::get_rounded_size(extra_hdr_bytes,Alignment) - + MinBlockSize; -} - -template -inline bool simple_seq_fit_impl:: - all_memory_deallocated() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return m_header.m_allocated == 0 && - ipcdetail::to_raw_pointer(m_header.m_root.m_next->m_next) == &m_header.m_root; -} - -template -inline void simple_seq_fit_impl::zero_free_memory() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - block_ctrl *block = ipcdetail::to_raw_pointer(m_header.m_root.m_next); - - //Iterate through all free portions - do{ - //Just clear user the memory part reserved for the user - std::memset( priv_get_user_buffer(block) - , 0 - , block->get_user_bytes()); - block = ipcdetail::to_raw_pointer(block->m_next); - } - while(block != &m_header.m_root); -} - -template -inline bool simple_seq_fit_impl:: - check_sanity() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - block_ctrl *block = ipcdetail::to_raw_pointer(m_header.m_root.m_next); - - size_type free_memory = 0; - - //Iterate through all blocks obtaining their size - while(block != &m_header.m_root){ - algo_impl_t::assert_alignment(block); - if(!algo_impl_t::check_alignment(block)) - return false; - //Free blocks's next must be always valid - block_ctrl *next = ipcdetail::to_raw_pointer(block->m_next); - if(!next){ - return false; - } - free_memory += block->m_size*Alignment; - block = next; - } - - //Check allocated bytes are less than size - if(m_header.m_allocated > m_header.m_size){ - return false; - } - - //Check free bytes are less than size - if(free_memory > m_header.m_size){ - return false; - } - return true; -} - -template -inline void* simple_seq_fit_impl:: - allocate(size_type nbytes) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - size_type ignore_recvd = nbytes; - void *ignore_reuse = 0; - return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); -} - -template -inline void* simple_seq_fit_impl:: - allocate_aligned(size_type nbytes, size_type alignment) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return algo_impl_t:: - allocate_aligned(this, nbytes, alignment); -} - -template -template -inline T* simple_seq_fit_impl:: - allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse_ptr) -{ - void *raw_reuse = reuse_ptr; - void * const ret = priv_allocation_command - (command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); - BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::dtl::alignment_of::value)); - reuse_ptr = static_cast(raw_reuse); - return static_cast(ret); -} - -template -inline void* simple_seq_fit_impl:: - raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) -{ - size_type const preferred_objects = prefer_in_recvd_out_size; - if(!sizeof_object){ - return reuse_ptr = 0, static_cast(0); - } - if(command & boost::interprocess::try_shrink_in_place){ - if(!reuse_ptr) return static_cast(0); - prefer_in_recvd_out_size = preferred_objects*sizeof_object; - bool success = algo_impl_t::try_shrink - ( this, reuse_ptr, limit_objects*sizeof_object, prefer_in_recvd_out_size); - prefer_in_recvd_out_size /= sizeof_object; - return success ? reuse_ptr : 0; - } - else{ - return priv_allocation_command - (command, limit_objects, prefer_in_recvd_out_size, reuse_ptr, sizeof_object); - } -} - -template -inline void* simple_seq_fit_impl:: - priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - command &= ~boost::interprocess::expand_bwd; - if(!command){ - return reuse_ptr = 0, static_cast(0); - } - - size_type max_count = m_header.m_size/sizeof_object; - if(limit_size > max_count || preferred_size > max_count){ - return reuse_ptr = 0, static_cast(0); - } - size_type l_size = limit_size*sizeof_object; - size_type r_size = preferred_size*sizeof_object; - void *ret = 0; - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - ret = priv_allocate(command, l_size, r_size, reuse_ptr); - } - prefer_in_recvd_out_size = r_size/sizeof_object; - return ret; -} - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl::size(const void *ptr) const -{ - //We need no synchronization since this block is not going - //to be modified - //Obtain the real size of the block - const block_ctrl *block = static_cast(priv_get_block(ptr)); - return block->get_user_bytes(); -} - -template -void* simple_seq_fit_impl:: - priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type &prefer_in_recvd_out_size - ,void *reuse_ptr - ,bool only_preferred_backwards) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - typedef std::pair prev_block_t; - block_ctrl *reuse = priv_get_block(reuse_ptr); - prefer_in_recvd_out_size = 0; - - if(this->size(reuse_ptr) > min_size){ - prefer_in_recvd_out_size = this->size(reuse_ptr); - return reuse_ptr; - } - - if(command & boost::interprocess::expand_fwd){ - if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) - return reuse_ptr; - } - else{ - prefer_in_recvd_out_size = this->size(reuse_ptr); - } - if(command & boost::interprocess::expand_bwd){ - size_type extra_forward = !prefer_in_recvd_out_size ? 0 : prefer_in_recvd_out_size + BlockCtrlBytes; - prev_block_t prev_pair = priv_prev_block_if_free(reuse); - block_ctrl *prev = prev_pair.second; - if(!prev){ - return 0; - } - - size_type needs_backwards = - ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); - - if(!only_preferred_backwards){ - max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) - ,min_value(prev->get_user_bytes(), needs_backwards)); - } - - //Check if previous block has enough size - if((prev->get_user_bytes()) >= needs_backwards){ - //Now take all next space. This will succeed - if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, prefer_in_recvd_out_size)){ - BOOST_ASSERT(0); - } - - //We need a minimum size to split the previous one - if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ - block_ctrl *new_block = move_detail::force_ptr - (reinterpret_cast(reuse) - needs_backwards - BlockCtrlBytes); - - new_block->m_next = 0; - new_block->m_size = - BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment; - prev->m_size = - (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits; - prefer_in_recvd_out_size = needs_backwards + extra_forward; - m_header.m_allocated += needs_backwards + BlockCtrlBytes; - return priv_get_user_buffer(new_block); - } - else{ - //Just merge the whole previous block - block_ctrl *prev_2_block = prev_pair.first; - //Update received size and allocation - prefer_in_recvd_out_size = extra_forward + prev->get_user_bytes(); - m_header.m_allocated += prev->get_total_bytes(); - //Now unlink it from previous block - prev_2_block->m_next = prev->m_next; - prev->m_size = reuse->m_size + prev->m_size; - prev->m_next = 0; - priv_get_user_buffer(prev); - } - } - } - return 0; -} - -template -inline void simple_seq_fit_impl:: - deallocate_many(typename simple_seq_fit_impl::multiallocation_chain &chain) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - while(!chain.empty()){ - this->priv_deallocate(to_raw_pointer(chain.pop_front())); - } -} - -template -inline typename simple_seq_fit_impl::size_type -simple_seq_fit_impl:: - priv_get_total_units(size_type userbytes) -{ - size_type s = ipcdetail::get_rounded_size(userbytes, Alignment)/Alignment; - if(!s) ++s; - return BlockCtrlUnits + s; -} - -template -void * simple_seq_fit_impl:: - priv_allocate(boost::interprocess::allocation_type command - ,size_type limit_size, size_type &prefer_in_recvd_out_size, void *&reuse_ptr) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - if(command & boost::interprocess::shrink_in_place){ - if(!reuse_ptr) return static_cast(0); - bool success = algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size); - return success ? reuse_ptr : 0; - } - prefer_in_recvd_out_size = 0; - - if(limit_size > preferred_size){ - return reuse_ptr = 0, static_cast(0); - } - - //Number of units to request (including block_ctrl header) - size_type nunits = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlUnits; - - //Get the root and the first memory block - block_ctrl *prev = &m_header.m_root; - block_ctrl *block = ipcdetail::to_raw_pointer(prev->m_next); - block_ctrl *root = &m_header.m_root; - block_ctrl *biggest_block = 0; - block_ctrl *prev_biggest_block = 0; - size_type biggest_size = 0; - - //Expand in place - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - void *ret = priv_expand_both_sides(command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, true); - if(ret){ - algo_impl_t::assert_alignment(ret); - return ret; - } - } - - if(command & boost::interprocess::allocate_new){ - prefer_in_recvd_out_size = 0; - while(block != root){ - //Update biggest block pointers - if(block->m_size > biggest_size){ - prev_biggest_block = prev; - biggest_size = block->m_size; - biggest_block = block; - } - algo_impl_t::assert_alignment(block); - void *addr = this->priv_check_and_allocate(nunits, prev, block, prefer_in_recvd_out_size); - if(addr){ - algo_impl_t::assert_alignment(addr); - return reuse_ptr = 0, addr; - } - //Bad luck, let's check next block - prev = block; - block = ipcdetail::to_raw_pointer(block->m_next); - } - - //Bad luck finding preferred_size, now if we have any biggest_block - //try with this block - if(biggest_block){ - size_type limit_units = ipcdetail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlUnits; - if(biggest_block->m_size < limit_units){ - return reuse_ptr = 0, static_cast(0); - } - void *ret = this->priv_check_and_allocate - (biggest_block->m_size, prev_biggest_block, biggest_block, prefer_in_recvd_out_size = biggest_block->m_size*Alignment - BlockCtrlUnits); - BOOST_ASSERT(ret != 0); - algo_impl_t::assert_alignment(ret); - return reuse_ptr = 0, ret; - } - } - //Now try to expand both sides with min size - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - void *ret = priv_expand_both_sides (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false); - algo_impl_t::assert_alignment(ret); - return ret; - } - return reuse_ptr = 0, static_cast(0); -} - -template inline -bool simple_seq_fit_impl::priv_is_allocated_block - (typename simple_seq_fit_impl::block_ctrl *block) -{ return block->m_next == 0; } - -template -inline typename simple_seq_fit_impl::block_ctrl * - simple_seq_fit_impl:: - priv_next_block_if_free - (typename simple_seq_fit_impl::block_ctrl *ptr) -{ - //Take the address where the next block should go - block_ctrl *next_block = move_detail::force_ptr - (reinterpret_cast(ptr) + ptr->m_size*Alignment); - - //Check if the adjacent block is in the managed segment - char *this_char_ptr = reinterpret_cast(this); - char *next_char_ptr = reinterpret_cast(next_block); - size_type distance = (size_type)(next_char_ptr - this_char_ptr)/Alignment; - - if(distance >= (m_header.m_size/Alignment)){ - //"next_block" does not exist so we can't expand "block" - return 0; - } - - if(!next_block->m_next) - return 0; - - return next_block; -} - -template -inline - std::pair::block_ctrl * - ,typename simple_seq_fit_impl::block_ctrl *> - simple_seq_fit_impl:: - priv_prev_block_if_free - (typename simple_seq_fit_impl::block_ctrl *ptr) -{ - typedef std::pair prev_pair_t; - //Take the address where the previous block should go - block_ctrl *root = &m_header.m_root; - block_ctrl *prev_2_block = root; - block_ctrl *prev_block = ipcdetail::to_raw_pointer(root->m_next); - - while((reinterpret_cast(prev_block) + prev_block->m_size*Alignment) - != reinterpret_cast(ptr) - && prev_block != root){ - prev_2_block = prev_block; - prev_block = ipcdetail::to_raw_pointer(prev_block->m_next); - } - - if(prev_block == root || !prev_block->m_next) - return prev_pair_t(static_cast(0), static_cast(0)); - - //Check if the previous block is in the managed segment - char *this_char_ptr = reinterpret_cast(this); - char *prev_char_ptr = reinterpret_cast(prev_block); - size_type distance = (size_type)(prev_char_ptr - this_char_ptr)/Alignment; - - if(distance >= (m_header.m_size/Alignment)){ - //"previous_block" does not exist so we can't expand "block" - return prev_pair_t(static_cast(0), static_cast(0)); - } - return prev_pair_t(prev_2_block, prev_block); -} - - -template -inline bool simple_seq_fit_impl:: - priv_expand (void *ptr, size_type min_size, size_type &received_size) -{ - size_type preferred_size = received_size; - //Obtain the real size of the block - block_ctrl *block = move_detail::force_ptr(priv_get_block(ptr)); - size_type old_block_size = block->m_size; - - //All used blocks' next is marked with 0 so check it - BOOST_ASSERT(block->m_next == 0); - - //Put this to a safe value - received_size = old_block_size*Alignment - BlockCtrlBytes; - - //Now translate it to Alignment units - min_size = ipcdetail::get_rounded_size(min_size, Alignment)/Alignment; - preferred_size = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment; - - //Some parameter checks - if(min_size > preferred_size) - return false; - - size_type data_size = old_block_size - BlockCtrlUnits; - - if(data_size >= min_size) - return true; - - block_ctrl *next_block = priv_next_block_if_free(block); - if(!next_block){ - return false; - } - - //Is "block" + "next_block" big enough? - size_type merged_size = old_block_size + next_block->m_size; - - //Now we can expand this block further than before - received_size = merged_size*Alignment - BlockCtrlBytes; - - if(merged_size < (min_size + BlockCtrlUnits)){ - return false; - } - - //We can fill expand. Merge both blocks, - block->m_next = next_block->m_next; - block->m_size = merged_size; - - //Find the previous free block of next_block - block_ctrl *prev = &m_header.m_root; - while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ - prev = ipcdetail::to_raw_pointer(prev->m_next); - } - - //Now insert merged block in the free list - //This allows reusing allocation logic in this function - m_header.m_allocated -= old_block_size*Alignment; - prev->m_next = block; - - //Now use check and allocate to do the allocation logic - preferred_size += BlockCtrlUnits; - size_type nunits = preferred_size < merged_size ? preferred_size : merged_size; - - //This must success since nunits is less than merged_size! - if(!this->priv_check_and_allocate (nunits, prev, block, received_size)){ - //Something very ugly is happening here. This is a bug - //or there is memory corruption - BOOST_ASSERT(0); - return false; - } - return true; -} - -template inline -void* simple_seq_fit_impl::priv_check_and_allocate - (size_type nunits - ,typename simple_seq_fit_impl::block_ctrl* prev - ,typename simple_seq_fit_impl::block_ctrl* block - ,size_type &received_size) -{ - size_type upper_nunits = nunits + BlockCtrlUnits; - bool found = false; - - if (block->m_size > upper_nunits){ - //This block is bigger than needed, split it in - //two blocks, the first's size will be "units" - //the second's size will be "block->m_size-units" - size_type total_size = block->m_size; - block->m_size = nunits; - - block_ctrl *new_block = move_detail::force_ptr - (reinterpret_cast(block) + Alignment*nunits); - new_block->m_size = total_size - nunits; - new_block->m_next = block->m_next; - prev->m_next = new_block; - found = true; - } - else if (block->m_size >= nunits){ - //This block has exactly the right size with an extra - //unusable extra bytes. - prev->m_next = block->m_next; - found = true; - } - - if(found){ - //We need block_ctrl for deallocation stuff, so - //return memory user can overwrite - m_header.m_allocated += block->m_size*Alignment; - received_size = block->get_user_bytes(); - //Mark the block as allocated - block->m_next = 0; - //Check alignment - algo_impl_t::assert_alignment(block); - return priv_get_user_buffer(block); - } - return 0; -} - -template -void simple_seq_fit_impl::deallocate(void* addr) -{ - if(!addr) return; - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return this->priv_deallocate(addr); -} - -template -void simple_seq_fit_impl::priv_deallocate(void* addr) -{ - if(!addr) return; - - //Let's get free block list. List is always sorted - //by memory address to allow block merging. - //Pointer next always points to the first - //(lower address) block - block_ctrl * prev = &m_header.m_root; - block_ctrl * pos = ipcdetail::to_raw_pointer(m_header.m_root.m_next); - block_ctrl * block = move_detail::force_ptr(priv_get_block(addr)); - - //All used blocks' next is marked with 0 so check it - BOOST_ASSERT(block->m_next == 0); - - //Check if alignment and block size are right - algo_impl_t::assert_alignment(addr); - - size_type total_size = Alignment*block->m_size; - BOOST_ASSERT(m_header.m_allocated >= total_size); - - //Update used memory count - m_header.m_allocated -= total_size; - - //Let's find the previous and the next block of the block to deallocate - //This ordering comparison must be done with original pointers - //types since their mapping to raw pointers can be different - //in each process - while((ipcdetail::to_raw_pointer(pos) != &m_header.m_root) && (block > pos)){ - prev = pos; - pos = ipcdetail::to_raw_pointer(pos->m_next); - } - - //Try to combine with upper block - char *block_char_ptr = reinterpret_cast(ipcdetail::to_raw_pointer(block)); - - if ((block_char_ptr + Alignment*block->m_size) == - reinterpret_cast(ipcdetail::to_raw_pointer(pos))){ - block->m_size += pos->m_size; - block->m_next = pos->m_next; - } - else{ - block->m_next = pos; - } - - //Try to combine with lower block - if ((reinterpret_cast(ipcdetail::to_raw_pointer(prev)) - + Alignment*prev->m_size) == - block_char_ptr){ - - - prev->m_size += block->m_size; - prev->m_next = block->m_next; - } - else{ - prev->m_next = block; - } -} - -} //namespace ipcdetail { - -} //namespace interprocess { - -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP - diff --git a/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp deleted file mode 100644 index d1dd9d12ff7..00000000000 --- a/extern/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ /dev/null @@ -1,1359 +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_MEM_ALGO_RBTREE_BEST_FIT_HPP -#define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -// interprocess -#include -#include -#include -#include -#include -#include -// interprocess/detail -#include -#include -#include -#include -// container -#include -// container/detail -#include -// move/detail -#include //make_unsigned, alignment_of -#include //make_unsigned, alignment_of -// intrusive -#include -#include -// other boost -#include -#include -// std -#include -#include - -//#define BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP -//to maintain ABI compatible with the original version -//ABI had to be updated to fix compatibility issues when -//sharing shared memory between 32 adn 64 bit processes. - -//!\file -//!Describes a best-fit algorithm based in an intrusive red-black tree used to allocate -//!objects in shared memory. This class is intended as a base class for single segment -//!and multi-segment implementations. - -namespace boost { -namespace interprocess { - -//!This class implements an algorithm that stores the free nodes in a red-black tree -//!to have logarithmic search/insert times. -template -class rbtree_best_fit -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - rbtree_best_fit(); - rbtree_best_fit(const rbtree_best_fit &); - rbtree_best_fit &operator=(const rbtree_best_fit &); - - private: - struct block_ctrl; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type block_ctrl_ptr; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type char_ptr; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Shared mutex family used for the rest of the Interprocess framework - typedef MutexFamily mutex_family; - //!Pointer type to be used with the rest of the Interprocess framework - typedef VoidPointer void_pointer; - typedef ipcdetail::basic_multiallocation_chain multiallocation_chain; - - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::container::dtl::make_unsigned::type size_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - private: - - typedef typename bi::make_set_base_hook - < bi::void_pointer - , bi::optimize_size - , bi::link_mode >::type TreeHook; - - struct SizeHolder - { - static const size_type size_mask = size_type(-1) >> 2; - //!This block's memory size (including block_ctrl - //!header) in Alignment units - size_type m_prev_size; - size_type m_size : sizeof(size_type)*CHAR_BIT - 2; - size_type m_prev_allocated : 1; - size_type m_allocated : 1; - }; - - //!Block control structure - struct block_ctrl - : public SizeHolder, public TreeHook - { - block_ctrl() - { this->m_size = 0; this->m_allocated = 0, this->m_prev_allocated = 0; } - - friend bool operator<(const block_ctrl &a, const block_ctrl &b) - { return a.m_size < b.m_size; } - friend bool operator==(const block_ctrl &a, const block_ctrl &b) - { return a.m_size == b.m_size; } - }; - - struct size_block_ctrl_compare - { - bool operator()(size_type size, const block_ctrl &block) const - { return size < block.m_size; } - - bool operator()(const block_ctrl &block, size_type size) const - { return block.m_size < size; } - }; - - //!Shared mutex to protect memory allocate/deallocate - typedef typename MutexFamily::mutex_type mutex_type; - typedef typename bi::make_multiset - >::type Imultiset; - - typedef typename Imultiset::iterator imultiset_iterator; - typedef typename Imultiset::const_iterator imultiset_const_iterator; - - //!This struct includes needed data and derives from - //!mutex_type to allow EBO when using null mutex_type - struct header_t : public mutex_type - { - Imultiset m_imultiset; - - //!The extra size required by the segment - size_type m_extra_hdr_bytes; - //!Allocated bytes for internal checking - size_type m_allocated; - //!The size of the memory segment - size_type m_size; - } m_header; - - friend class ipcdetail::memory_algorithm_common; - - typedef ipcdetail::memory_algorithm_common algo_impl_t; - - public: - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Constructor. "size" is the total size of the managed memory segment, - //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(rbtree_best_fit) - //!offset that the allocator should not use at all. - rbtree_best_fit (size_type size, size_type extra_hdr_bytes); - - //!Destructor. - ~rbtree_best_fit(); - - //!Obtains the minimum size needed by the algorithm - static size_type get_min_size (size_type extra_hdr_bytes); - - //Functions for single segment management - - //!Allocates bytes, returns 0 if there is not more memory - void* allocate (size_type nbytes); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Experimental. Dont' use - - //!Multiple element allocation, same size - void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); - } - - //!Multiple element allocation, different size - void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); - } - - //!Multiple element allocation, different size - void deallocate_many(multiallocation_chain &chain); - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Deallocates previously allocated bytes - void deallocate (void *addr); - - //!Returns the size of the memory segment - size_type get_size() const; - - //!Returns the number of free bytes of the segment - size_type get_free_memory() const; - - //!Initializes to zero all the memory that's not in use. - //!This function is normally used for security reasons. - void zero_free_memory(); - - //!Increases managed memory in - //!extra_size bytes more - void grow(size_type extra_size); - - //!Decreases managed memory as much as possible - void shrink_to_fit(); - - //!Returns true if all allocated memory has been deallocated - bool all_memory_deallocated(); - - //!Makes an internal sanity check - //!and returns true if success - bool check_sanity(); - - template - T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse); - - void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_object, - size_type &prefer_in_recvd_out_size, - void *&reuse_ptr, size_type sizeof_object = 1); - - //!Returns the size of the buffer previously allocated pointed by ptr - size_type size(const void *ptr) const; - - //!Allocates aligned bytes, returns 0 if there is not more memory. - //!Alignment must be power of 2 - void* allocate_aligned (size_type nbytes, size_type alignment); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - static size_type priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes); - - block_ctrl *priv_first_block(); - - block_ctrl *priv_end_block(); - - void* priv_allocation_command(boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object); - - - //!Real allocation algorithm with min allocation option - void * priv_allocate( boost::interprocess::allocation_type command - , size_type limit_size, size_type &prefer_in_recvd_out_size - , void *&reuse_ptr, size_type backwards_multiple = 1); - - //!Obtains the block control structure of the user buffer - static block_ctrl *priv_get_block(const void *ptr); - - //!Obtains the pointer returned to the user from the block control - static void *priv_get_user_buffer(const block_ctrl *block); - - //!Returns the number of total units that a user buffer - //!of "userbytes" bytes really occupies (including header) - static size_type priv_get_total_units(size_type userbytes); - - //!Real expand function implementation - bool priv_expand(void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size); - - //!Real expand to both sides implementation - void* priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type &prefer_in_recvd_out_size - ,void *reuse_ptr - ,bool only_preferred_backwards - ,size_type backwards_multiple); - - //!Returns true if the previous block is allocated - bool priv_is_prev_allocated(block_ctrl *ptr); - - //!Get a pointer of the "end" block from the first block of the segment - static block_ctrl * priv_end_block(block_ctrl *first_segment_block); - - //!Get a pointer of the "first" block from the end block of the segment - static block_ctrl * priv_first_block(block_ctrl *end_segment_block); - - //!Get poitner of the previous block (previous block must be free) - static block_ctrl * priv_prev_block(block_ctrl *ptr); - - //!Get the size in the tail of the previous block - static block_ctrl * priv_next_block(block_ctrl *ptr); - - //!Check if this block is free (not allocated) - bool priv_is_allocated_block(block_ctrl *ptr); - - //!Marks the block as allocated - void priv_mark_as_allocated_block(block_ctrl *ptr); - - //!Marks the block as allocated - void priv_mark_new_allocated_block(block_ctrl *ptr) - { return priv_mark_as_allocated_block(ptr); } - - //!Marks the block as allocated - void priv_mark_as_free_block(block_ctrl *ptr); - - //!Checks if block has enough memory and splits/unlinks the block - //!returning the address to the users - void* priv_check_and_allocate(size_type units - ,block_ctrl* block - ,size_type &received_size); - //!Real deallocation algorithm - void priv_deallocate(void *addr); - - //!Makes a new memory portion available for allocation - void priv_add_segment(void *addr, size_type size); - - public: - - static const size_type Alignment = !MemAlignment - ? size_type(::boost::container::dtl::alignment_of - < ::boost::container::dtl::max_align_t>::value) - : size_type(MemAlignment) - ; - - private: - //Due to embedded bits in size, Alignment must be at least 4 - BOOST_STATIC_ASSERT((Alignment >= 4)); - //Due to rbtree size optimizations, Alignment must have at least pointer alignment - BOOST_STATIC_ASSERT((Alignment >= ::boost::container::dtl::alignment_of::value)); - static const size_type AlignmentMask = (Alignment - 1); - static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size::value; - static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; - static const size_type AllocatedCtrlBytes = ipcdetail::ct_rounded_size::value; - static const size_type AllocatedCtrlUnits = AllocatedCtrlBytes/Alignment; - static const size_type EndCtrlBlockBytes = ipcdetail::ct_rounded_size::value; - static const size_type EndCtrlBlockUnits = EndCtrlBlockBytes/Alignment; - static const size_type MinBlockUnits = BlockCtrlUnits; - static const size_type UsableByPreviousChunk = sizeof(size_type); - - //Make sure the maximum alignment is power of two - BOOST_STATIC_ASSERT((0 == (Alignment & (Alignment - size_type(1u))))); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - static const size_type PayloadPerAllocation = AllocatedCtrlBytes - UsableByPreviousChunk; -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -inline typename rbtree_best_fit::size_type - rbtree_best_fit - ::priv_first_block_offset_from_this(const void *this_ptr, size_type extra_hdr_bytes) -{ - size_type uint_this = (std::size_t)this_ptr; - size_type main_hdr_end = uint_this + sizeof(rbtree_best_fit) + extra_hdr_bytes; - size_type aligned_main_hdr_end = ipcdetail::get_rounded_size(main_hdr_end, Alignment); - size_type block1_off = aligned_main_hdr_end - uint_this; - algo_impl_t::assert_alignment(aligned_main_hdr_end); - algo_impl_t::assert_alignment(uint_this + block1_off); - return block1_off; -} - -template -void rbtree_best_fit:: - priv_add_segment(void *addr, size_type segment_size) -{ - //Check alignment - algo_impl_t::check_alignment(addr); - //Check size - BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes)); - - //Initialize the first big block and the "end" node - block_ctrl *first_big_block = ::new(addr, boost_container_new_t()) block_ctrl; - first_big_block->m_size = (segment_size/Alignment - EndCtrlBlockUnits) & block_ctrl::size_mask; - BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits); - - //The "end" node is just a node of size 0 with the "end" bit set - SizeHolder *end_block = - ::new(reinterpret_cast(addr) + first_big_block->m_size*Alignment, boost_container_new_t()) SizeHolder; - - //This will overwrite the prev part of the "end" node - priv_mark_as_free_block (first_big_block); - #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - first_big_block->m_prev_size = end_block->m_size = - size_type(reinterpret_cast(first_big_block) - reinterpret_cast(end_block))/Alignmen) & block_ctrl::size_mask; - #else - first_big_block->m_prev_size = end_block->m_size = - size_type(reinterpret_cast(end_block) - reinterpret_cast(first_big_block))/Alignment & block_ctrl::size_mask; - #endif - end_block->m_allocated = 1; - first_big_block->m_prev_allocated = 1; - - BOOST_ASSERT(priv_next_block(first_big_block) == end_block); - BOOST_ASSERT(priv_prev_block((block_ctrl*)end_block) == first_big_block); - BOOST_ASSERT(priv_first_block() == first_big_block); - BOOST_ASSERT(priv_end_block() == end_block); - - //Some check to validate the algorithm, since it makes some assumptions - //to optimize the space wasted in bookkeeping: - - //Check that the sizes of the header are placed before the rbtree - BOOST_ASSERT(static_cast(static_cast(first_big_block)) - < static_cast(static_cast(first_big_block))); - //Insert it in the intrusive containers - m_header.m_imultiset.insert(*first_big_block); -} - -template -inline typename rbtree_best_fit::block_ctrl * - rbtree_best_fit - ::priv_first_block() -{ - const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); - return move_detail::force_ptr(reinterpret_cast(this) + block1_off); -} - -template -inline typename rbtree_best_fit::block_ctrl * - rbtree_best_fit - ::priv_end_block() -{ - const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); - const size_type original_first_block_size = (m_header.m_size - block1_off)/Alignment - EndCtrlBlockUnits; - block_ctrl *end_block = move_detail::force_ptr - (reinterpret_cast(this) + block1_off + original_first_block_size*Alignment); - return end_block; -} - -template -inline rbtree_best_fit:: - rbtree_best_fit(size_type segment_size, size_type extra_hdr_bytes) -{ - //Initialize the header - m_header.m_allocated = 0; - m_header.m_size = segment_size; - m_header.m_extra_hdr_bytes = extra_hdr_bytes; - - //Now write calculate the offset of the first big block that will - //cover the whole segment - BOOST_ASSERT(get_min_size(extra_hdr_bytes) <= segment_size); - size_type block1_off = priv_first_block_offset_from_this(this, extra_hdr_bytes); - priv_add_segment(reinterpret_cast(this) + block1_off, segment_size - block1_off); -} - -template -inline rbtree_best_fit::~rbtree_best_fit() -{ - //There is a memory leak! -// BOOST_ASSERT(m_header.m_allocated == 0); -// BOOST_ASSERT(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); -} - -template -void rbtree_best_fit::grow(size_type extra_size) -{ - //Get the address of the first block - block_ctrl *first_block = priv_first_block(); - block_ctrl *old_end_block = priv_end_block(); - size_type old_border_offset = (size_type)(reinterpret_cast(old_end_block) - - reinterpret_cast(this)) + EndCtrlBlockBytes; - - //Update managed buffer's size - m_header.m_size += extra_size; - - //We need at least MinBlockUnits blocks to create a new block - if((m_header.m_size - old_border_offset) < MinBlockUnits){ - return; - } - - //Now create a new block between the old end and the new end - size_type align_offset = (m_header.m_size - old_border_offset)/Alignment; - block_ctrl *new_end_block = move_detail::force_ptr - (reinterpret_cast(old_end_block) + align_offset*Alignment); - - //the last and first block are special: - //new_end_block->m_size & first_block->m_prev_size store the absolute value - //between them - new_end_block->m_allocated = 1; - #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - new_end_block->m_size = size_type(reinterpret_cast(first_block) - - reinterpret_cast(new_end_block))/Alignment & block_ctrl::size_mask; - #else - new_end_block->m_size = size_type(reinterpret_cast(new_end_block) - - reinterpret_cast(first_block))/Alignment & block_ctrl::size_mask; - #endif - first_block->m_prev_size = new_end_block->m_size; - first_block->m_prev_allocated = 1; - BOOST_ASSERT(new_end_block == priv_end_block()); - - //The old end block is the new block - block_ctrl *new_block = old_end_block; - new_block->m_size = size_type(reinterpret_cast(new_end_block) - - reinterpret_cast(new_block))/Alignment & block_ctrl::size_mask; - BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); - priv_mark_as_allocated_block(new_block); - BOOST_ASSERT(priv_next_block(new_block) == new_end_block); - - m_header.m_allocated += (size_type)new_block->m_size*Alignment; - - //Now deallocate the newly created block - this->priv_deallocate(priv_get_user_buffer(new_block)); -} - -template -void rbtree_best_fit::shrink_to_fit() -{ - //Get the address of the first block - block_ctrl *first_block = priv_first_block(); - algo_impl_t::assert_alignment(first_block); - - //block_ctrl *old_end_block = priv_end_block(first_block); - block_ctrl *old_end_block = priv_end_block(); - algo_impl_t::assert_alignment(old_end_block); - size_type old_end_block_size = old_end_block->m_size; - - void *unique_buffer = 0; - block_ctrl *last_block; - //Check if no memory is allocated between the first and last block - if(priv_next_block(first_block) == old_end_block){ - //If so check if we can allocate memory - size_type ignore_recvd = 0; - void *ignore_reuse = 0; - unique_buffer = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); - //If not, return, we can't shrink - if(!unique_buffer) - return; - //If we can, mark the position just after the new allocation as the new end - algo_impl_t::assert_alignment(unique_buffer); - block_ctrl *unique_block = priv_get_block(unique_buffer); - BOOST_ASSERT(priv_is_allocated_block(unique_block)); - algo_impl_t::assert_alignment(unique_block); - last_block = priv_next_block(unique_block); - BOOST_ASSERT(!priv_is_allocated_block(last_block)); - algo_impl_t::assert_alignment(last_block); - } - else{ - //If memory is allocated, check if the last block is allocated - if(priv_is_prev_allocated(old_end_block)) - return; - //If not, mark last block after the free block - last_block = priv_prev_block(old_end_block); - } - - size_type last_block_size = last_block->m_size; - - //Erase block from the free tree, since we will erase it - m_header.m_imultiset.erase(Imultiset::s_iterator_to(*last_block)); - - size_type shrunk_border_offset = (size_type)(reinterpret_cast(last_block) - - reinterpret_cast(this)) + EndCtrlBlockBytes; - - block_ctrl *new_end_block = last_block; - algo_impl_t::assert_alignment(new_end_block); - - //Write new end block attributes - #ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP - new_end_block->m_size = - size_type(reinterpret_cast(first_block) - reinterpret_cast(new_end_block))/Alignment & block_ctrl::size_mask; - first_block->m_prev_size = new_end_block->m_size; - #else - new_end_block->m_size = - size_type(reinterpret_cast(new_end_block) - reinterpret_cast(first_block))/Alignment & block_ctrl::size_mask; - first_block->m_prev_size = new_end_block->m_size; - #endif - - new_end_block->m_allocated = 1; - (void)last_block_size; - (void)old_end_block_size; - BOOST_ASSERT(new_end_block->m_size == (old_end_block_size - last_block_size)); - - //Update managed buffer's size - m_header.m_size = shrunk_border_offset & block_ctrl::size_mask; - BOOST_ASSERT(priv_end_block() == new_end_block); - if(unique_buffer) - priv_deallocate(unique_buffer); -} - -template -inline typename rbtree_best_fit::size_type -rbtree_best_fit::get_size() const -{ return m_header.m_size; } - -template -typename rbtree_best_fit::size_type -rbtree_best_fit::get_free_memory() const -{ - return m_header.m_size - m_header.m_allocated - - priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); -} - -template -typename rbtree_best_fit::size_type -rbtree_best_fit:: - get_min_size (size_type extra_hdr_bytes) -{ - return (algo_impl_t::ceil_units(sizeof(rbtree_best_fit)) + - algo_impl_t::ceil_units(extra_hdr_bytes) + - MinBlockUnits + EndCtrlBlockUnits)*Alignment; -} - -template -inline bool rbtree_best_fit:: - all_memory_deallocated() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - size_type block1_off = - priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); - - return m_header.m_allocated == 0 && - m_header.m_imultiset.begin() != m_header.m_imultiset.end() && - (++m_header.m_imultiset.begin()) == m_header.m_imultiset.end() - && m_header.m_imultiset.begin()->m_size == - (m_header.m_size - block1_off - EndCtrlBlockBytes)/Alignment; -} - -template -bool rbtree_best_fit:: - check_sanity() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); - - size_type free_memory = 0; - - //Iterate through all blocks obtaining their size - for(; ib != ie; ++ib){ - free_memory += (size_type)ib->m_size*Alignment; - if(!algo_impl_t::check_alignment(&*ib)) - return false; - } - - //Check allocated bytes are less than size - if(m_header.m_allocated > m_header.m_size){ - return false; - } - - size_type block1_off = - priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes); - - //Check free bytes are less than size - if(free_memory > (m_header.m_size - block1_off)){ - return false; - } - return true; -} - -template -inline void* rbtree_best_fit:: - allocate(size_type nbytes) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - size_type ignore_recvd = nbytes; - void *ignore_reuse = 0; - return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); -} - -template -inline void* rbtree_best_fit:: - allocate_aligned(size_type nbytes, size_type alignment) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return algo_impl_t::allocate_aligned(this, nbytes, alignment); -} - -template -template -inline T* rbtree_best_fit:: - allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse) -{ - void* raw_reuse = reuse; - void* const ret = priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); - reuse = static_cast(raw_reuse); - BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::dtl::alignment_of::value)); - return static_cast(ret); -} - -template -inline void* rbtree_best_fit:: - raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type &prefer_in_recvd_out_objects, void *&reuse_ptr, size_type sizeof_object) -{ - size_type const preferred_objects = prefer_in_recvd_out_objects; - if(!sizeof_object) - return reuse_ptr = 0, static_cast(0); - if(command & boost::interprocess::try_shrink_in_place){ - if(!reuse_ptr) return static_cast(0); - const bool success = algo_impl_t::try_shrink - ( this, reuse_ptr, limit_objects*sizeof_object - , prefer_in_recvd_out_objects = preferred_objects*sizeof_object); - prefer_in_recvd_out_objects /= sizeof_object; - return success ? reuse_ptr : 0; - } - else{ - return priv_allocation_command - (command, limit_objects, prefer_in_recvd_out_objects, reuse_ptr, sizeof_object); - } -} - - -template -inline void* rbtree_best_fit:: - priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, - void *&reuse_ptr, size_type sizeof_object) -{ - void* ret; - size_type const preferred_size = prefer_in_recvd_out_size; - size_type const max_count = m_header.m_size/sizeof_object; - if(limit_size > max_count || preferred_size > max_count){ - return reuse_ptr = 0, static_cast(0); - } - size_type l_size = limit_size*sizeof_object; - size_type p_size = preferred_size*sizeof_object; - size_type r_size; - { - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - ret = priv_allocate(command, l_size, r_size = p_size, reuse_ptr, sizeof_object); - } - prefer_in_recvd_out_size = r_size/sizeof_object; - return ret; -} - -template -typename rbtree_best_fit::size_type -rbtree_best_fit:: - size(const void *ptr) const -{ - //We need no synchronization since this block's size is not going - //to be modified by anyone else - //Obtain the real size of the block - return ((size_type)priv_get_block(ptr)->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; -} - -template -inline void rbtree_best_fit::zero_free_memory() -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); - - //Iterate through all blocks obtaining their size - while(ib != ie){ - //Just clear user the memory part reserved for the user - volatile char *ptr = reinterpret_cast(&*ib) + BlockCtrlBytes; - size_type s = (size_type)ib->m_size*Alignment - BlockCtrlBytes; - while(s--){ - *ptr++ = 0; - } - - //This surprisingly is optimized out by Visual C++ 7.1 in release mode! - //std::memset( reinterpret_cast(&*ib) + BlockCtrlBytes - // , 0 - // , ib->m_size*Alignment - BlockCtrlBytes); - ++ib; - } -} - -template -void* rbtree_best_fit:: - priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type &prefer_in_recvd_out_size - ,void *reuse_ptr - ,bool only_preferred_backwards - ,size_type backwards_multiple) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - algo_impl_t::assert_alignment(reuse_ptr); - if(command & boost::interprocess::expand_fwd){ - if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) - return reuse_ptr; - } - else{ - prefer_in_recvd_out_size = this->size(reuse_ptr); - if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) - return reuse_ptr; - } - - if(backwards_multiple){ - BOOST_ASSERT(0 == (min_size % backwards_multiple)); - BOOST_ASSERT(0 == (preferred_size % backwards_multiple)); - } - - if(command & boost::interprocess::expand_bwd){ - //Obtain the real size of the block - block_ctrl *reuse = priv_get_block(reuse_ptr); - - //Sanity check - algo_impl_t::assert_alignment(reuse); - - block_ctrl *prev_block; - - //If the previous block is not free, there is nothing to do - if(priv_is_prev_allocated(reuse)){ - return 0; - } - - prev_block = priv_prev_block(reuse); - BOOST_ASSERT(!priv_is_allocated_block(prev_block)); - - //Some sanity checks - BOOST_ASSERT(prev_block->m_size == reuse->m_prev_size); - algo_impl_t::assert_alignment(prev_block); - - size_type needs_backwards_aligned; - size_type lcm; - if(!algo_impl_t::calculate_lcm_and_needs_backwards_lcmed - ( backwards_multiple - , prefer_in_recvd_out_size - , only_preferred_backwards ? preferred_size : min_size - , lcm, needs_backwards_aligned)){ - return 0; - } - - //Check if previous block has enough size - if(size_type(prev_block->m_size*Alignment) >= needs_backwards_aligned){ - //Now take all next space. This will succeed - if(command & boost::interprocess::expand_fwd){ - size_type received_size2; - if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, received_size2 = prefer_in_recvd_out_size)){ - BOOST_ASSERT(0); - } - BOOST_ASSERT(prefer_in_recvd_out_size == received_size2); - } - //We need a minimum size to split the previous one - if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){ - block_ctrl *new_block = move_detail::force_ptr - (reinterpret_cast(reuse) - needs_backwards_aligned); - - //Free old previous buffer - new_block->m_size = - (AllocatedCtrlUnits + (needs_backwards_aligned + (prefer_in_recvd_out_size - UsableByPreviousChunk))/Alignment) & block_ctrl::size_mask; - BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); - priv_mark_as_allocated_block(new_block); - - prev_block->m_size = size_type(reinterpret_cast(new_block) - - reinterpret_cast(prev_block))/Alignment & block_ctrl::size_mask; - BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); - priv_mark_as_free_block(prev_block); - - //Update the old previous block in the free blocks tree - //If the new size fulfills tree invariants do nothing, - //otherwise erase() + insert() - { - imultiset_iterator prev_block_it(Imultiset::s_iterator_to(*prev_block)); - imultiset_iterator was_smaller_it(prev_block_it); - if(prev_block_it != m_header.m_imultiset.begin() && - (--(was_smaller_it = prev_block_it))->m_size > prev_block->m_size){ - m_header.m_imultiset.erase(prev_block_it); - m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *prev_block); - } - } - - prefer_in_recvd_out_size = needs_backwards_aligned + prefer_in_recvd_out_size; - m_header.m_allocated += needs_backwards_aligned; - - //Check alignment - algo_impl_t::assert_alignment(new_block); - - //If the backwards expansion has remaining bytes in the - //first bytes, fill them with a pattern - void *p = priv_get_user_buffer(new_block); - void *user_ptr = reinterpret_cast(p); - BOOST_ASSERT(size_type(static_cast(reuse_ptr) - static_cast(user_ptr)) % backwards_multiple == 0); - algo_impl_t::assert_alignment(user_ptr); - return user_ptr; - } - //Check if there is no place to create a new block and - //the whole new block is multiple of the backwards expansion multiple - else if(prev_block->m_size >= needs_backwards_aligned/Alignment && - 0 == ((prev_block->m_size*Alignment) % lcm)) { - //Erase old previous block, since we will change it - m_header.m_imultiset.erase(Imultiset::s_iterator_to(*prev_block)); - - //Just merge the whole previous block - //prev_block->m_size*Alignment is multiple of lcm (and backwards_multiple) - prefer_in_recvd_out_size = prefer_in_recvd_out_size + (size_type)prev_block->m_size*Alignment; - - m_header.m_allocated += (size_type)prev_block->m_size*Alignment; - //Now update sizes - prev_block->m_size = size_type(prev_block->m_size + reuse->m_size) & block_ctrl::size_mask; - BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits); - priv_mark_as_allocated_block(prev_block); - - //If the backwards expansion has remaining bytes in the - //first bytes, fill them with a pattern - void *user_ptr = priv_get_user_buffer(prev_block); - BOOST_ASSERT(size_type(static_cast(reuse_ptr) - static_cast(user_ptr)) % backwards_multiple == 0); - algo_impl_t::assert_alignment(user_ptr); - return user_ptr; - } - else{ - //Alignment issues - } - } - } - return 0; -} - -template -inline void rbtree_best_fit:: - deallocate_many(typename rbtree_best_fit::multiallocation_chain &chain) -{ - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - algo_impl_t::deallocate_many(this, chain); -} - -template -void * rbtree_best_fit:: - priv_allocate(boost::interprocess::allocation_type command - ,size_type limit_size - ,size_type &prefer_in_recvd_out_size - ,void *&reuse_ptr - ,size_type backwards_multiple) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - if(command & boost::interprocess::shrink_in_place){ - if(!reuse_ptr) return static_cast(0); - bool success = - algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size = preferred_size); - return success ? reuse_ptr : 0; - } - - prefer_in_recvd_out_size = 0; - - if(limit_size > preferred_size) - return reuse_ptr = 0, static_cast(0); - - //Number of units to request (including block_ctrl header) - size_type preferred_units = priv_get_total_units(preferred_size); - - //Number of units to request (including block_ctrl header) - size_type limit_units = priv_get_total_units(limit_size); - - //Expand in place - prefer_in_recvd_out_size = preferred_size; - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - void *ret = priv_expand_both_sides - (command, limit_size, prefer_in_recvd_out_size, reuse_ptr, true, backwards_multiple); - if(ret) - return ret; - } - - if(command & boost::interprocess::allocate_new){ - size_block_ctrl_compare comp; - imultiset_iterator it(m_header.m_imultiset.lower_bound(preferred_units, comp)); - - if(it != m_header.m_imultiset.end()){ - return reuse_ptr = 0, this->priv_check_and_allocate - (preferred_units, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); - } - - if(it != m_header.m_imultiset.begin()&& - (--it)->m_size >= limit_units){ - return reuse_ptr = 0, this->priv_check_and_allocate - (it->m_size, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); - } - } - - - //Now try to expand both sides with min size - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - return priv_expand_both_sides - (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false, backwards_multiple); - } - return reuse_ptr = 0, static_cast(0); -} - -template -inline -typename rbtree_best_fit::block_ctrl * - rbtree_best_fit::priv_get_block(const void *ptr) -{ - return const_cast - (move_detail::force_ptr - (reinterpret_cast(ptr) - AllocatedCtrlBytes)); -} - -template -inline -void *rbtree_best_fit:: - priv_get_user_buffer(const typename rbtree_best_fit::block_ctrl *block) -{ return const_cast(reinterpret_cast(block) + AllocatedCtrlBytes); } - -template -inline typename rbtree_best_fit::size_type -rbtree_best_fit:: - priv_get_total_units(size_type userbytes) -{ - if(userbytes < UsableByPreviousChunk) - userbytes = UsableByPreviousChunk; - size_type units = ipcdetail::get_rounded_size(userbytes - UsableByPreviousChunk, Alignment)/Alignment + AllocatedCtrlUnits; - if(units < BlockCtrlUnits) units = BlockCtrlUnits; - return units; -} - -template -bool rbtree_best_fit:: - priv_expand (void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size) -{ - size_type const preferred_size = prefer_in_recvd_out_size; - //Obtain the real size of the block - block_ctrl *block = priv_get_block(ptr); - size_type old_block_units = block->m_size; - - //The block must be marked as allocated and the sizes must be equal - BOOST_ASSERT(priv_is_allocated_block(block)); - - //Put this to a safe value - prefer_in_recvd_out_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; - if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) - return true; - - //Now translate it to Alignment units - const size_type min_user_units = algo_impl_t::ceil_units(min_size - UsableByPreviousChunk); - const size_type preferred_user_units = algo_impl_t::ceil_units(preferred_size - UsableByPreviousChunk); - - //Some parameter checks - BOOST_ASSERT(min_user_units <= preferred_user_units); - - block_ctrl *next_block; - - if(priv_is_allocated_block(next_block = priv_next_block(block))){ - return prefer_in_recvd_out_size >= min_size; - } - algo_impl_t::assert_alignment(next_block); - - //Is "block" + "next_block" big enough? - const size_type merged_units = old_block_units + (size_type)next_block->m_size; - - //Now get the expansion size - const size_type merged_user_units = merged_units - AllocatedCtrlUnits; - - if(merged_user_units < min_user_units){ - prefer_in_recvd_out_size = merged_units*Alignment - UsableByPreviousChunk; - return false; - } - - //Now get the maximum size the user can allocate - size_type intended_user_units = (merged_user_units < preferred_user_units) ? - merged_user_units : preferred_user_units; - - //These are total units of the merged block (supposing the next block can be split) - const size_type intended_units = AllocatedCtrlUnits + intended_user_units; - - //Check if we can split the next one in two parts - if((merged_units - intended_units) >= BlockCtrlUnits){ - //This block is bigger than needed, split it in - //two blocks, the first one will be merged and - //the second's size will be the remaining space - BOOST_ASSERT(next_block->m_size == priv_next_block(next_block)->m_prev_size); - const size_type rem_units = merged_units - intended_units; - - //Check if we we need to update the old next block in the free blocks tree - //If the new size fulfills tree invariants, we just need to replace the node - //(the block start has been displaced), otherwise erase() + insert(). - // - //This fixup must be done in two parts, because the new next block might - //overwrite the tree hook of the old next block. So we first erase the - //old if needed and we'll insert the new one after creating the new next - imultiset_iterator old_next_block_it(Imultiset::s_iterator_to(*next_block)); - m_header.m_imultiset.erase(old_next_block_it); - - //This is the remaining block - block_ctrl *rem_block = - ::new(reinterpret_cast(block) + intended_units*Alignment, boost_container_new_t()) block_ctrl; - rem_block->m_size = rem_units & block_ctrl::size_mask; - algo_impl_t::assert_alignment(rem_block); - BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); - priv_mark_as_free_block(rem_block); - m_header.m_imultiset.insert(*rem_block); - - //Write the new length - block->m_size = (intended_user_units + AllocatedCtrlUnits) & block_ctrl::size_mask; - BOOST_ASSERT(block->m_size >= BlockCtrlUnits); - m_header.m_allocated += (intended_units - old_block_units)*Alignment; - } - //There is no free space to create a new node: just merge both blocks - else{ - //Now we have to update the data in the tree - m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block)); - - //Write the new length - block->m_size = merged_units & block_ctrl::size_mask; - BOOST_ASSERT(block->m_size >= BlockCtrlUnits); - m_header.m_allocated += (merged_units - old_block_units)*Alignment; - } - priv_mark_as_allocated_block(block); - prefer_in_recvd_out_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; - return true; -} - -template inline -typename rbtree_best_fit::block_ctrl * - rbtree_best_fit::priv_prev_block - (typename rbtree_best_fit::block_ctrl *ptr) -{ - BOOST_ASSERT(!ptr->m_prev_allocated); - return move_detail::force_ptr - (reinterpret_cast(ptr) - ptr->m_prev_size*Alignment); -} - - - -template inline -typename rbtree_best_fit::block_ctrl * - rbtree_best_fit::priv_end_block - (typename rbtree_best_fit::block_ctrl *first_segment_block) -{ - //The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute - //distance with the end block - BOOST_ASSERT(first_segment_block->m_prev_allocated); - block_ctrl *end_block = move_detail::force_ptr - (reinterpret_cast(first_segment_block) + first_segment_block->m_prev_size*Alignment); - (void)end_block; - BOOST_ASSERT(end_block->m_allocated == 1); - BOOST_ASSERT(end_block->m_size == first_segment_block->m_prev_size); - BOOST_ASSERT(end_block > first_segment_block); - return end_block; -} - -template inline -typename rbtree_best_fit::block_ctrl * - rbtree_best_fit::priv_first_block - (typename rbtree_best_fit::block_ctrl *end_segment_block) -{ - //The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute - //distance with the end block - BOOST_ASSERT(end_segment_block->m_allocated); - block_ctrl *first_block = move_detail::force_ptr - (reinterpret_cast(end_segment_block) - end_segment_block->m_size*Alignment); - (void)first_block; - BOOST_ASSERT(first_block->m_prev_allocated == 1); - BOOST_ASSERT(first_block->m_prev_size == end_segment_block->m_size); - BOOST_ASSERT(end_segment_block > first_block); - return first_block; -} - - -template inline -typename rbtree_best_fit::block_ctrl * - rbtree_best_fit::priv_next_block - (typename rbtree_best_fit::block_ctrl *ptr) -{ - return move_detail::force_ptr - (reinterpret_cast(ptr) + ptr->m_size*Alignment); -} - -template inline -bool rbtree_best_fit::priv_is_allocated_block - (typename rbtree_best_fit::block_ctrl *block) -{ - bool allocated = block->m_allocated != 0; - #ifndef NDEBUG - if(block != priv_end_block()){ - block_ctrl *next_block = move_detail::force_ptr - (reinterpret_cast(block) + block->m_size*Alignment); - bool next_block_prev_allocated = next_block->m_prev_allocated != 0; - (void)next_block_prev_allocated; - BOOST_ASSERT(allocated == next_block_prev_allocated); - } - #endif - return allocated; -} - -template inline -bool rbtree_best_fit::priv_is_prev_allocated - (typename rbtree_best_fit::block_ctrl *block) -{ - if(block->m_prev_allocated){ - return true; - } - else{ - #ifndef NDEBUG - if(block != priv_first_block()){ - block_ctrl *prev = priv_prev_block(block); - (void)prev; - BOOST_ASSERT(!prev->m_allocated); - BOOST_ASSERT(prev->m_size == block->m_prev_size); - } - #endif - return false; - } -} - -template inline -void rbtree_best_fit::priv_mark_as_allocated_block - (typename rbtree_best_fit::block_ctrl *block) -{ - block->m_allocated = 1; - move_detail::force_ptr - (reinterpret_cast(block)+ block->m_size*Alignment)->m_prev_allocated = 1; -} - -template inline -void rbtree_best_fit::priv_mark_as_free_block - (typename rbtree_best_fit::block_ctrl *block) -{ - block->m_allocated = 0; - block_ctrl *next_block = priv_next_block(block); - next_block->m_prev_allocated = 0; - next_block->m_prev_size = block->m_size; -} - -template inline -void* rbtree_best_fit::priv_check_and_allocate - (size_type nunits - ,typename rbtree_best_fit::block_ctrl* block - ,size_type &received_size) -{ - size_type upper_nunits = nunits + BlockCtrlUnits; - imultiset_iterator it_old = Imultiset::s_iterator_to(*block); - algo_impl_t::assert_alignment(block); - - if (block->m_size >= upper_nunits){ - //This block is bigger than needed, split it in - //two blocks, the first's size will be "units" and - //the second's size "block->m_size-units" - size_type block_old_size = block->m_size; - block->m_size = nunits & block_ctrl::size_mask; - BOOST_ASSERT(block->m_size >= BlockCtrlUnits); - - //This is the remaining block - block_ctrl *rem_block = - ::new(reinterpret_cast(block) + Alignment*nunits, boost_container_new_t()) block_ctrl; - algo_impl_t::assert_alignment(rem_block); - rem_block->m_size = (block_old_size - nunits) & block_ctrl::size_mask; - BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); - priv_mark_as_free_block(rem_block); - - //Now we have to update the data in the tree. - //Use the position of the erased one as a hint - m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block); - } - else if (block->m_size >= nunits){ - m_header.m_imultiset.erase(it_old); - } - else{ - BOOST_ASSERT(0); - return 0; - } - //We need block_ctrl for deallocation stuff, so - //return memory user can overwrite - m_header.m_allocated += (size_type)block->m_size*Alignment; - received_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; - - //Mark the block as allocated - priv_mark_as_allocated_block(block); - - //Clear the memory occupied by the tree hook, since this won't be - //cleared with zero_free_memory - TreeHook *t = static_cast(block); - //Just clear the memory part reserved for the user - std::size_t tree_hook_offset_in_block = std::size_t((char*)t - (char*)block); - //volatile char *ptr = - char *ptr = reinterpret_cast(block)+tree_hook_offset_in_block; - const std::size_t s = BlockCtrlBytes - tree_hook_offset_in_block; - std::memset(ptr, 0, s); - this->priv_next_block(block)->m_prev_size = 0; - return priv_get_user_buffer(block); -} - -template -void rbtree_best_fit::deallocate(void* addr) -{ - if(!addr) return; - //----------------------- - boost::interprocess::scoped_lock guard(m_header); - //----------------------- - return this->priv_deallocate(addr); -} - -template -void rbtree_best_fit::priv_deallocate(void* addr) -{ - if(!addr) return; - - block_ctrl *block = priv_get_block(addr); - - //The blocks must be marked as allocated and the sizes must be equal - BOOST_ASSERT(priv_is_allocated_block(block)); - - //Check if alignment and block size are right - algo_impl_t::assert_alignment(addr); - - size_type block_old_size = Alignment*(size_type)block->m_size; - BOOST_ASSERT(m_header.m_allocated >= block_old_size); - - //Update used memory count - m_header.m_allocated -= block_old_size; - - //The block to insert in the tree - block_ctrl *block_to_insert = block; - - //Get the next block - block_ctrl *const next_block = priv_next_block(block); - const bool merge_with_prev = !priv_is_prev_allocated(block); - const bool merge_with_next = !priv_is_allocated_block(next_block); - - //Merge logic. First just update block sizes, then fix free blocks tree - if(merge_with_prev || merge_with_next){ - //Merge if the previous is free - if(merge_with_prev){ - //Get the previous block - block_to_insert = priv_prev_block(block); - block_to_insert->m_size = size_type(block_to_insert->m_size + block->m_size) & block_ctrl::size_mask; - BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); - m_header.m_imultiset.erase(Imultiset::s_iterator_to(*block_to_insert)); - } - //Merge if the next is free - if(merge_with_next){ - block_to_insert->m_size = size_type(block_to_insert->m_size + next_block->m_size) & block_ctrl::size_mask; - BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits); - const imultiset_iterator next_it = Imultiset::s_iterator_to(*next_block); - m_header.m_imultiset.erase(next_it); - } - } - priv_mark_as_free_block(block_to_insert); - m_header.m_imultiset.insert(*block_to_insert); -} - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP diff --git a/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp b/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp deleted file mode 100644 index 69813f41bca..00000000000 --- a/extern/boost/boost/interprocess/mem_algo/simple_seq_fit.hpp +++ /dev/null @@ -1,62 +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_SIMPLE_SEQ_FIT_HPP -#define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include - -//!\file -//!Describes sequential fit algorithm used to allocate objects in shared memory. - -namespace boost { -namespace interprocess { - -//!This class implements the simple sequential fit algorithm with a simply -//!linked list of free buffers. -template -class simple_seq_fit - : public ipcdetail::simple_seq_fit_impl -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef ipcdetail::simple_seq_fit_impl base_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef typename base_t::size_type size_type; - - //!Constructor. "size" is the total size of the managed memory segment, - //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit) - //!offset that the allocator should not use at all.*/ - simple_seq_fit(size_type segment_size, size_type extra_hdr_bytes) - : base_t(segment_size, extra_hdr_bytes){} -}; - -} //namespace interprocess { - -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP - diff --git a/extern/boost/boost/interprocess/offset_ptr.hpp b/extern/boost/boost/interprocess/offset_ptr.hpp deleted file mode 100644 index 5619ec30774..00000000000 --- a/extern/boost/boost/interprocess/offset_ptr.hpp +++ /dev/null @@ -1,776 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (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/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP -#define BOOST_INTERPROCESS_OFFSET_PTR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include //alignment_of, aligned_storage -#include -#include -#include - -#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - - -//!\file -//!Describes a smart pointer that stores the offset between this pointer and -//!target pointee, called offset_ptr. - -namespace boost { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -//Predeclarations -template -struct has_trivial_destructor; - -#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail { - - template - union offset_ptr_internal - { - BOOST_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t)); - BOOST_STATIC_ASSERT(boost::is_integral::value && boost::is_unsigned::value); - - explicit offset_ptr_internal(OffsetType off) - : m_offset(off) - {} - - OffsetType m_offset; //Distance between this object and pointee address - - typename ::boost::container::dtl::aligned_storage - < sizeof(OffsetType)//for offset_type_alignment m_offset will be enough - , (OffsetAlignment == offset_type_alignment) ? 1u : OffsetAlignment - >::type alignment_helper; - }; - - //Note: using the address of a local variable to point to another address - //is not standard conforming and this can be optimized-away by the compiler. - //Non-inlining is a method to remain illegal but correct - - //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline - //this code without breaking the library - - //////////////////////////////////////////////////////////////////////// - // - // offset_ptr_to_raw_pointer - // - //////////////////////////////////////////////////////////////////////// - #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR - template - BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset) - { - typedef pointer_offset_caster caster_t; - #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR - if(offset == 1){ - return 0; - } - else{ - return caster_t(caster_t(this_ptr).offset() + offset).pointer(); - } - #else - OffsetType mask = offset == 1; - --mask; - OffsetType target_offset = caster_t(this_ptr).offset() + offset; - target_offset &= mask; - return caster_t(target_offset).pointer(); - #endif - } - - //////////////////////////////////////////////////////////////////////// - // - // offset_ptr_to_offset - // - //////////////////////////////////////////////////////////////////////// - #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF - template - BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) - { - typedef pointer_offset_caster caster_t; - #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF - //offset == 1 && ptr != 0 is not legal for this pointer - if(!ptr){ - return 1; - } - else{ - OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset(); - BOOST_ASSERT(offset != 1); - return offset; - } - #else - //const OffsetType other = -OffsetType(ptr != 0); - //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other; - //return offset + OffsetType(!other); - // - OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset(); - --offset; - OffsetType mask = ptr == 0; - --mask; - offset &= mask; - return ++offset; - #endif - } - - //////////////////////////////////////////////////////////////////////// - // - // offset_ptr_to_offset_from_other - // - //////////////////////////////////////////////////////////////////////// - #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER - template - BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other - (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset) - { - typedef pointer_offset_caster caster_t; - #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER - if(other_offset == 1){ - return 1; - } - else{ - OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset; - BOOST_ASSERT(offset != 1); - return offset; - } - #else - OffsetType mask = other_offset == 1; - --mask; - OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); - offset &= mask; - return offset + other_offset; - - //OffsetType mask = -OffsetType(other_offset != 1); - //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); - //offset &= mask; - //return offset + other_offset; - #endif - } - - //////////////////////////////////////////////////////////////////////// - // - // Let's assume cast to void and cv cast don't change any target address - // - //////////////////////////////////////////////////////////////////////// - template - struct offset_ptr_maintains_address - { - static const bool value = ipcdetail::is_cv_same::value - || ipcdetail::is_cv_same::value - || ipcdetail::is_cv_same::value - ; - }; - - template - struct enable_if_convertible_equal_address - : enable_if_c< ::boost::is_convertible::value - && offset_ptr_maintains_address::value - , Ret> - {}; - - template - struct enable_if_convertible_unequal_address - : enable_if_c< ::boost::is_convertible::value - && !offset_ptr_maintains_address::value - , Ret> - {}; - -} //namespace ipcdetail { -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!A smart pointer that stores the offset between the pointer and the -//!object it points to. This allows special properties, since -//!the pointer is independent from the address of the pointee, if the -//!pointer and the pointee are still separated by the same offset. This feature -//!converts offset_ptr in a smart pointer that can be placed in shared memory and -//!memory mapped files mapped at different addresses in every process. -//! -//! \tparam PointedType The type of the pointee. -//! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer -//! \tparam OffsetType An unsigned integer type that can represent the -//! distance between two pointers reinterpret_cast-ed as unsigned integers. This type -//! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate -//! between 32 and 64 bit processes using 64 bit offsets. -//! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary -//! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets. -//! -//!Note: offset_ptr uses implementation defined properties, present in most platforms, for -//!performance reasons: -//! - Assumes that OffsetType representation of nullptr is (OffsetType)zero. -//! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent -//! to incrementing the pointer and then converting it back to OffsetType. -template -class offset_ptr -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef offset_ptr self_t; - void unspecified_bool_type_func() const {} - typedef void (self_t::*unspecified_bool_type)() const; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef PointedType element_type; - typedef PointedType * pointer; - typedef typename ipcdetail:: - add_reference::type reference; - typedef typename ipcdetail:: - remove_volatile::type - >::type value_type; - typedef DifferenceType difference_type; - typedef std::random_access_iterator_tag iterator_category; - typedef OffsetType offset_type; - - public: //Public Functions - - //!Default constructor (null pointer). - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr() BOOST_NOEXCEPT - : internal(1) - {} - - //!Constructor from raw pointer (allows "0" pointer conversion). - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(ptr, this)) - {} - - //!Constructor from other pointer. - //!Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr - , typename ipcdetail::enable_if< ::boost::is_convertible >::type * = 0) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr), this)) - {} - - //!Constructor from other offset_ptr - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)) - {} - - //!Constructor from other offset_ptr. Only takes part in overload resolution - //!if T2* is convertible to PointedType*. Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - , typename ipcdetail::enable_if_convertible_equal_address::type* = 0 - #endif - ) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())) - {} - - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr - , typename ipcdetail::enable_if_convertible_unequal_address::type* = 0) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) - {} - - #endif - - //!Constructor from other offset_ptr. Only takes part in overload resolution - //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr &ptr - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - , typename ipcdetail::enable_if_c< - !::boost::is_convertible::value && ::boost::is_constructible::value - >::type * = 0 - #endif - ) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) - {} - - //!Emulates static_cast operator. - //!Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this)) - {} - - //!Emulates const_cast operator. - //!Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this)) - {} - - //!Emulates dynamic_cast operator. - //!Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this)) - {} - - //!Emulates reinterpret_cast operator. - //!Never throws. - template - BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT - : internal(ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this)) - {} - - //!Obtains raw pointer from offset. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT - { return static_cast(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); } - - BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT - { return this->internal.m_offset; } - - //!Pointer-like -> operator. It can return 0 pointer. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT - { return this->get(); } - - //!Dereferencing operator, if it is a null offset_ptr behavior - //! is undefined. Never throws. - BOOST_INTERPROCESS_FORCEINLINE reference operator* () const BOOST_NOEXCEPT - { - pointer p = this->get(); - reference r = *p; - return r; - } - - //!Indexing operator. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE reference operator[](difference_type idx) const BOOST_NOEXCEPT - { return this->get()[idx]; } - - //!Assignment from pointer (saves extra conversion). - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT - { - this->internal.m_offset = ipcdetail::offset_ptr_to_offset(from, this); - return *this; - } - - //!Assignment from other offset_ptr. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT - { - this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset); - return *this; - } - - //!Assignment from related offset_ptr. If pointers of pointee types - //! are assignable, offset_ptrs will be assignable. Never throws. - template BOOST_INTERPROCESS_FORCEINLINE - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typename ipcdetail::enable_if_c - < ::boost::is_convertible::value, offset_ptr&>::type - #else - offset_ptr& - #endif - operator= (const offset_ptr &ptr) BOOST_NOEXCEPT - { - this->assign(ptr, ipcdetail::bool_::value>()); - return *this; - } - - public: - - //!offset_ptr += difference_type. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT - { this->inc_offset(offset * difference_type(sizeof(PointedType))); return *this; } - - //!offset_ptr -= difference_type. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT - { this->dec_offset(offset * difference_type(sizeof(PointedType))); return *this; } - - //!++offset_ptr. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT - { this->inc_offset(difference_type(sizeof(PointedType))); return *this; } - - //!offset_ptr++. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator++ (int) BOOST_NOEXCEPT - { - offset_ptr tmp(*this); - this->inc_offset(sizeof (PointedType)); - return tmp; - } - - //!--offset_ptr. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator-- (void) BOOST_NOEXCEPT - { this->dec_offset(sizeof (PointedType)); return *this; } - - //!offset_ptr--. - //!Never throws. - BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator-- (int) BOOST_NOEXCEPT - { - offset_ptr tmp(*this); - this->dec_offset(sizeof (PointedType)); - return tmp; - } - - //!safe bool conversion operator. - //!Never throws. - #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const BOOST_NOEXCEPT - { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; } - #else - explicit operator bool() const BOOST_NOEXCEPT - { return this->internal.m_offset != 1; } - #endif - - //!Not operator. Not needed in theory, but improves portability. - //!Never throws - BOOST_INTERPROCESS_FORCEINLINE bool operator! () const BOOST_NOEXCEPT - { return this->internal.m_offset == 1; } - - //!Compatibility with pointer_traits - //! - #if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - template - struct rebind - { typedef offset_ptr other; }; - #else - template - using rebind = offset_ptr; - #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - typedef offset_ptr other; - #endif //BOOST_INTERPROCESS_DOXYGEN_INVOKED - #endif - - //!Compatibility with pointer_traits - //! - BOOST_INTERPROCESS_FORCEINLINE static offset_ptr pointer_to(reference r) BOOST_NOEXCEPT - { return offset_ptr(&r); } - - //!difference_type + offset_ptr - //!operation - BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(difference_type diff, offset_ptr right) BOOST_NOEXCEPT - { right += diff; return right; } - - //!offset_ptr + difference_type - //!operation - BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(offset_ptr left, difference_type diff) BOOST_NOEXCEPT - { left += diff; return left; } - - //!offset_ptr - diff - //!operation - BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(offset_ptr left, difference_type diff) BOOST_NOEXCEPT - { left -= diff; return left; } - - //!offset_ptr - diff - //!operation - BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(difference_type diff, offset_ptr right) BOOST_NOEXCEPT - { right -= diff; return right; } - - //!offset_ptr - offset_ptr - //!operation - BOOST_INTERPROCESS_FORCEINLINE friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) BOOST_NOEXCEPT - { return difference_type(pt.get()- pt2.get()); } - - //Comparison - BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() == pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() != pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() < pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() <= pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() > pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1.get() >= pt2.get(); } - - //Comparison to raw ptr to support literal 0 - BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 == pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 != pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 < pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 <= pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 > pt2.get(); } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT - { return pt1 >= pt2.get(); } - - //Comparison - BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() == pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() != pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() < pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() <= pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() > pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT - { return pt1.get() >= pt2; } - - BOOST_INTERPROCESS_FORCEINLINE friend void swap(offset_ptr &left, offset_ptr &right) BOOST_NOEXCEPT - { - pointer ptr = right.get(); - right = left; - left = ptr; - } - - private: - template - BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT - { //no need to pointer adjustment - this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()); - } - - template - BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT - { //we must convert to raw before calculating the offset - this->internal.m_offset = ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - BOOST_INTERPROCESS_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT - { internal.m_offset += OffsetType(bytes); } - - BOOST_INTERPROCESS_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT - { internal.m_offset -= OffsetType(bytes); } - - ipcdetail::offset_ptr_internal internal; - - public: - BOOST_INTERPROCESS_FORCEINLINE const OffsetType &priv_offset() const BOOST_NOEXCEPT - { return internal.m_offset; } - - BOOST_INTERPROCESS_FORCEINLINE OffsetType &priv_offset() BOOST_NOEXCEPT - { return internal.m_offset; } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!operator<< -//!for offset ptr -template -inline std::basic_ostream & operator<< - (std::basic_ostream & os, offset_ptr const & p) -{ return os << p.get_offset(); } - -//!operator>> -//!for offset ptr -template -inline std::basic_istream & operator>> - (std::basic_istream & is, offset_ptr & p) -{ return is >> p.get_offset(); } - -//!Simulation of static_cast between pointers. Never throws. -template -BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr - static_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT -{ - return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::static_cast_tag()); -} - -//!Simulation of const_cast between pointers. Never throws. -template -BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr - const_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT -{ - return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::const_cast_tag()); -} - -//!Simulation of dynamic_cast between pointers. Never throws. -template -BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr - dynamic_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT -{ - return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); -} - -//!Simulation of reinterpret_cast between pointers. Never throws. -template -BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr - reinterpret_pointer_cast(const boost::interprocess::offset_ptr & r) BOOST_NOEXCEPT -{ - return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); -} - -} //namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -///has_trivial_destructor<> == true_type specialization for optimizations -template -struct has_trivial_destructor< ::boost::interprocess::offset_ptr > -{ - static const bool value = true; -}; - -namespace move_detail { - -///has_trivial_destructor<> == true_type specialization for optimizations -template -struct is_trivially_destructible< ::boost::interprocess::offset_ptr > -{ - static const bool value = true; -}; - -} //namespace move_detail { - -namespace interprocess { - -//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. -//!Never throws. -template -BOOST_INTERPROCESS_FORCEINLINE T * to_raw_pointer(boost::interprocess::offset_ptr const & p) BOOST_NOEXCEPT -{ return ipcdetail::to_raw_pointer(p); } - -} //namespace interprocess - - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -} //namespace boost { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -namespace boost{ - -//This is to support embedding a bit in the pointer -//for intrusive containers, saving space -namespace intrusive { - -//Predeclaration to avoid including header -template -struct max_pointer_plus_bits; - -template -struct max_pointer_plus_bits, OffsetAlignment> -{ - //The offset ptr can embed one bit less than the alignment since it - //uses offset == 1 to store the null pointer. - static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros::value - 1; -}; - -//Predeclaration -template -struct pointer_plus_bits; - -template -struct pointer_plus_bits, NumBits> -{ - typedef boost::interprocess::offset_ptr pointer; - //Bits are stored in the lower bits of the pointer except the LSB, - //because this bit is used to represent the null pointer. - static const O Mask = ((static_cast(1) << NumBits) - static_cast(1)) << 1; - BOOST_STATIC_ASSERT(0 ==(Mask&1)); - - //We must ALWAYS take argument "n" by reference as a copy of a null pointer - //with a bit (e.g. offset == 3) would be incorrectly copied and interpreted as non-null. - - BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT - { - pointer p; - O const tmp_off = n.priv_offset() & ~Mask; - p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off); - return p; - } - - BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT - { - BOOST_ASSERT(0 == (get_bits)(p)); - O const stored_bits = n.priv_offset() & Mask; - n = p; - n.priv_offset() |= stored_bits; - } - - BOOST_INTERPROCESS_FORCEINLINE static std::size_t get_bits(const pointer &n) BOOST_NOEXCEPT - { - return std::size_t((n.priv_offset() & Mask) >> 1u); - } - - BOOST_INTERPROCESS_FORCEINLINE static void set_bits(pointer &n, std::size_t const b) BOOST_NOEXCEPT - { - BOOST_ASSERT(b < (std::size_t(1) << NumBits)); - O tmp = n.priv_offset(); - tmp &= ~Mask; - tmp |= O(b << 1u); - n.priv_offset() = tmp; - } -}; - -} //namespace intrusive - -//Predeclaration -template -struct pointer_to_other; - -//Backwards compatibility with pointer_to_other -template -struct pointer_to_other - < ::boost::interprocess::offset_ptr, U > -{ - typedef ::boost::interprocess::offset_ptr type; -}; - -} //namespace boost{ -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -#include - -#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) -#pragma GCC diagnostic pop -#endif - -#endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP diff --git a/extern/boost/boost/interprocess/segment_manager.hpp b/extern/boost/boost/interprocess/segment_manager.hpp deleted file mode 100644 index d292c505b77..00000000000 --- a/extern/boost/boost/interprocess/segment_manager.hpp +++ /dev/null @@ -1,1357 +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_SEGMENT_MANAGER_HPP -#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// container/detail -#include -#include -// std -#include //std::size_t -#include -#include -#ifndef BOOST_NO_EXCEPTIONS -#include -#endif -#include - -//!\file -//!Describes the object placed in a memory segment that provides -//!named object allocation capabilities for single-segment and -//!multi-segment allocations. - -namespace boost{ -namespace interprocess{ - -//!This object is the public base class of segment manager. -//!This class only depends on the memory allocation algorithm -//!and implements all the allocation features not related -//!to named or unique objects. -//! -//!Storing a reference to segment_manager forces -//!the holder class to be dependent on index types and character types. -//!When such dependence is not desirable and only anonymous and raw -//!allocations are needed, segment_manager_base is the correct answer. -template -class segment_manager_base - : private MemoryAlgorithm -{ - public: - typedef segment_manager_base segment_manager_base_type; - typedef typename MemoryAlgorithm::void_pointer void_pointer; - typedef typename MemoryAlgorithm::mutex_family mutex_family; - typedef MemoryAlgorithm memory_algorithm; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Experimental. Don't use - typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; - typedef typename MemoryAlgorithm::difference_type difference_type; - typedef typename MemoryAlgorithm::size_type size_type; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!This constant indicates the payload size - //!associated with each allocation of the memory algorithm - static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation; - - //!Constructor of the segment_manager_base - //! - //!"size" is the size of the memory segment where - //!the basic segment manager is being constructed. - //! - //!"reserved_bytes" is the number of bytes - //!after the end of the memory algorithm object itself - //!that the memory algorithm will exclude from - //!dynamic allocation - //! - //!Can throw - segment_manager_base(size_type sz, size_type reserved_bytes) - : MemoryAlgorithm(sz, reserved_bytes) - { - BOOST_ASSERT((sizeof(segment_manager_base) == sizeof(MemoryAlgorithm))); - } - - //!Returns the size of the memory - //!segment - size_type get_size() const - { return MemoryAlgorithm::get_size(); } - - //!Returns the number of free bytes of the memory - //!segment - size_type get_free_memory() const - { return MemoryAlgorithm::get_free_memory(); } - - //!Obtains the minimum size needed by - //!the segment manager - static size_type get_min_size (size_type size) - { return MemoryAlgorithm::get_min_size(size); } - - //!Allocates nbytes bytes. This function is only used in - //!single-segment management. Never throws - void * allocate (size_type nbytes, const std::nothrow_t &) - { return MemoryAlgorithm::allocate(nbytes); } - - //!Returns a reference to the internal memory algorithm. - //!This function is useful for custom memory algorithms that - //!need additional configuration options after construction. Never throws. - //!This function should be only used by advanced users. - MemoryAlgorithm &get_memory_algorithm() - { return static_cast(*this); } - - //!Returns a const reference to the internal memory algorithm. - //!This function is useful for custom memory algorithms that - //!need additional configuration options after construction. Never throws. - //!This function should be only used by advanced users. - const MemoryAlgorithm &get_memory_algorithm() const - { return static_cast(*this); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Experimental. Dont' use. - //!Allocates n_elements of elem_bytes bytes. - //!Throws bad_alloc on failure. chain.size() is not increased on failure. - void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) - { - size_type prev_size = chain.size(); - MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); - if(!elem_bytes || chain.size() == prev_size){ - throw bad_alloc(); - } - } - - //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. - //!Throws bad_alloc on failure. chain.size() is not increased on failure. - void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { - size_type prev_size = chain.size(); - MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain); - if(!sizeof_element || chain.size() == prev_size){ - throw bad_alloc(); - } - } - - //!Allocates n_elements of elem_bytes bytes. - //!Non-throwing version. chain.size() is not increased on failure. - void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) - { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); } - - //!Allocates n_elements, each one of - //!element_lengths[i]*sizeof_element bytes. - //!Non-throwing version. chain.size() is not increased on failure. - void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) - { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); } - - //!Deallocates all elements contained in chain. - //!Never throws. - void deallocate_many(multiallocation_chain &chain) - { MemoryAlgorithm::deallocate_many(chain); } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc - //!on failure - void * allocate(size_type nbytes) - { - void * ret = MemoryAlgorithm::allocate(nbytes); - if(!ret) - throw bad_alloc(); - return ret; - } - - //!Allocates nbytes bytes. This function is only used in - //!single-segment management. Never throws - void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &) - { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); } - - //!Allocates nbytes bytes. This function is only used in - //!single-segment management. Throws bad_alloc when fails - void * allocate_aligned(size_type nbytes, size_type alignment) - { - void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment); - if(!ret) - throw bad_alloc(); - return ret; - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - template - T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type &prefer_in_recvd_out_size, T *&reuse) - { - T *ret = MemoryAlgorithm::allocation_command - (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse); - if(!(command & boost::interprocess::nothrow_allocation) && !ret) - throw bad_alloc(); - return ret; - } - - void *raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1) - { - void *ret = MemoryAlgorithm::raw_allocation_command - ( command | boost::interprocess::nothrow_allocation, limit_objects, - prefer_in_recvd_out_size, reuse, sizeof_object); - if(!(command & boost::interprocess::nothrow_allocation) && !ret) - throw bad_alloc(); - return ret; - } - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Deallocates the bytes allocated with allocate/allocate_many() - //!pointed by addr - void deallocate (void *addr) - { MemoryAlgorithm::deallocate(addr); } - - //!Increases managed memory in extra_size bytes more. This only works - //!with single-segment management. - void grow(size_type extra_size) - { MemoryAlgorithm::grow(extra_size); } - - //!Decreases managed memory to the minimum. This only works - //!with single-segment management. - void shrink_to_fit() - { MemoryAlgorithm::shrink_to_fit(); } - - //!Returns the result of "all_memory_deallocated()" function - //!of the used memory algorithm - bool all_memory_deallocated() - { return MemoryAlgorithm::all_memory_deallocated(); } - - //!Returns the result of "check_sanity()" function - //!of the used memory algorithm - bool check_sanity() - { return MemoryAlgorithm::check_sanity(); } - - //!Writes to zero free memory (memory not yet allocated) - //!of the memory algorithm - void zero_free_memory() - { MemoryAlgorithm::zero_free_memory(); } - - //!Returns the size of the buffer previously allocated pointed by ptr - size_type size(const void *ptr) const - { return MemoryAlgorithm::size(ptr); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - protected: - void * prot_anonymous_construct - (size_type num, bool dothrow, ipcdetail::in_place_interface &table) - { - typedef ipcdetail::block_header block_header_t; - block_header_t block_info ( size_type(table.size*num) - , size_type(table.alignment) - , anonymous_type - , 1 - , 0); - - //Allocate memory - void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get()); - - //Check if there is enough memory - if(!ptr_struct){ - if(dothrow){ - throw bad_alloc(); - } - else{ - return 0; - } - } - - //Build scoped ptr to avoid leaks with constructor exception - ipcdetail::mem_algo_deallocator mem(ptr_struct, *this); - - //Now construct the header - block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info); - void *ptr = 0; //avoid gcc warning - ptr = hdr->value(); - - //Now call constructors - table.construct_n(ptr, num); - - //All constructors successful, we don't want erase memory - mem.release(); - return ptr; - } - - //!Calls the destructor and makes an anonymous deallocate - void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table) - { - - //Get control data from associated with this object - typedef ipcdetail::block_header block_header_t; - block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment); - - //------------------------------- - //scoped_lock guard(m_header); - //------------------------------- - - if(ctrl_data->alloc_type() != anonymous_type){ - //This is not an anonymous object, the pointer is wrong! - BOOST_ASSERT(0); - } - - //Call destructors and free memory - //Build scoped ptr to avoid leaks with destructor exception - table.destroy_n(const_cast(object), ctrl_data->m_value_bytes/table.size); - this->deallocate(ctrl_data); - } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!This object is placed in the beginning of memory segment and -//!implements the allocation (named or anonymous) of portions -//!of the segment. This object contains two indexes that -//!maintain an association between a name and a portion of the segment. -//! -//!The first index contains the mappings for normal named objects using the -//!char type specified in the template parameter. -//! -//!The second index contains the association for unique instances. The key will -//!be the const char * returned from type_info.name() function for the unique -//!type to be constructed. -//! -//!segment_manager inherits publicly -//!from segment_manager_base and inherits from it -//!many public functions related to anonymous object and raw memory allocation. -//!See segment_manager_base reference to know about those functions. -template class IndexType> -class segment_manager - : public segment_manager_base -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - segment_manager(); - segment_manager(const segment_manager &); - segment_manager &operator=(const segment_manager &); - typedef segment_manager_base segment_manager_base_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef MemoryAlgorithm memory_algorithm; - typedef typename segment_manager_base_t::void_pointer void_pointer; - typedef typename segment_manager_base_t::size_type size_type; - typedef typename segment_manager_base_t::difference_type difference_type; - typedef CharType char_type; - - typedef segment_manager_base segment_manager_base_type; - - static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef ipcdetail::block_header block_header_t; - typedef ipcdetail::index_config index_config_named; - typedef ipcdetail::index_config index_config_unique; - typedef IndexType index_type; - typedef ipcdetail::bool_::value > is_intrusive_t; - typedef ipcdetail::bool_::value> is_node_index_t; - - public: - typedef IndexType named_index_t; - typedef IndexType unique_index_t; - typedef ipcdetail::char_ptr_holder char_ptr_holder_t; - typedef ipcdetail::segment_manager_iterator_transform - ::value> named_transform; - - typedef ipcdetail::segment_manager_iterator_transform - ::value> unique_transform; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - typedef typename segment_manager_base_t::mutex_family mutex_family; - - typedef transform_iterator - const_named_iterator; - typedef transform_iterator - const_unique_iterator; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Constructor proxy object definition helper class - template - struct construct_proxy - { - typedef ipcdetail::named_proxy type; - }; - - //!Constructor proxy object definition helper class - template - struct construct_iter_proxy - { - typedef ipcdetail::named_proxy type; - }; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Constructor of the segment manager - //!"size" is the size of the memory segment where - //!the segment manager is being constructed. - //!Can throw - explicit segment_manager(size_type segment_size) - : segment_manager_base_t(segment_size, priv_get_reserved_bytes()) - , m_header(static_cast(get_this_pointer())) - { - (void) anonymous_instance; (void) unique_instance; - //Check EBO is applied, it's required - const void * const this_addr = this; - const void *const segm_addr = static_cast(this); - (void)this_addr; (void)segm_addr; - BOOST_ASSERT( this_addr == segm_addr); - const std::size_t void_ptr_alignment = boost::move_detail::alignment_of::value; (void)void_ptr_alignment; - BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of::value)); - } - - //!Tries to find a previous named/unique allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. - template - std::pair find (char_ptr_holder_t name) - { return this->priv_find_impl(name, true); } - - //!Tries to find a previous named/unique allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. This search is not mutex-protected! - //!Use it only inside atomic_func() calls, where the internal mutex - //!is guaranteed to be locked. - template - std::pair find_no_lock (char_ptr_holder_t name) - { return this->priv_find_impl(name, false); } - - //!Returns throwing "construct" proxy - //!object - template - typename construct_proxy::type - construct(char_ptr_holder_t name) - { return typename construct_proxy::type (this, name, false, true); } - - //!Returns throwing "search or construct" proxy - //!object - template - typename construct_proxy::type find_or_construct(char_ptr_holder_t name) - { return typename construct_proxy::type (this, name, true, true); } - - //!Returns no throwing "construct" proxy - //!object - template - typename construct_proxy::type - construct(char_ptr_holder_t name, const std::nothrow_t &) - { return typename construct_proxy::type (this, name, false, false); } - - //!Returns no throwing "search or construct" - //!proxy object - template - typename construct_proxy::type - find_or_construct(char_ptr_holder_t name, const std::nothrow_t &) - { return typename construct_proxy::type (this, name, true, false); } - - //!Returns throwing "construct from iterators" proxy object - template - typename construct_iter_proxy::type - construct_it(char_ptr_holder_t name) - { return typename construct_iter_proxy::type (this, name, false, true); } - - //!Returns throwing "search or construct from iterators" - //!proxy object - template - typename construct_iter_proxy::type - find_or_construct_it(char_ptr_holder_t name) - { return typename construct_iter_proxy::type (this, name, true, true); } - - //!Returns no throwing "construct from iterators" - //!proxy object - template - typename construct_iter_proxy::type - construct_it(char_ptr_holder_t name, const std::nothrow_t &) - { return typename construct_iter_proxy::type (this, name, false, false); } - - //!Returns no throwing "search or construct from iterators" - //!proxy object - template - typename construct_iter_proxy::type - find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &) - { return typename construct_iter_proxy::type (this, name, true, false); } - - //!Calls object function blocking recursive interprocess_mutex and guarantees that - //!no new named_alloc or destroy will be executed by any process while - //!executing the object function call - template - void atomic_func(Func &f) - { scoped_lock guard(m_header); f(); } - - //!Tries to calls a functor guaranteeing that no new construction, search or - //!destruction will be executed by any process while executing the object - //!function call. If the atomic function can't be immediatelly executed - //!because the internal mutex is already locked, returns false. - //!If the functor throws, this function throws. - template - bool try_atomic_func(Func &f) - { - scoped_lock guard(m_header, try_to_lock); - if(guard){ - f(); - return true; - } - else{ - return false; - } - } - - //!Destroys a previously created named/unique instance. - //!Returns false if the object was not present. - template - bool destroy(char_ptr_holder_t name) - { - BOOST_ASSERT(!name.is_anonymous()); - ipcdetail::placement_destroy dtor; - - if(name.is_unique()){ - return this->priv_generic_named_destroy - ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t()); - } - else{ - return this->priv_generic_named_destroy - ( name.get(), m_header.m_named_index, dtor, is_intrusive_t()); - } - } - - //!Destroys an anonymous, unique or named object - //!using its address - template - void destroy_ptr(const T *p) - { - //If T is void transform it to char - typedef typename ipcdetail::char_if_void::type data_t; - ipcdetail::placement_destroy dtor; - priv_destroy_ptr(p, dtor); - } - - //!Returns the name of an object created with construct/find_or_construct - //!functions. Does not throw - template - static const CharType *get_instance_name(const T *ptr) - { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); } - - //!Returns the length of an object created with construct/find_or_construct - //!functions. Does not throw. - template - static size_type get_instance_length(const T *ptr) - { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); } - - //!Returns is the the name of an object created with construct/find_or_construct - //!functions. Does not throw - template - static instance_type get_instance_type(const T *ptr) - { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); } - - //!Preallocates needed index resources to optimize the - //!creation of "num" named objects in the managed memory segment. - //!Can throw boost::interprocess::bad_alloc if there is no enough memory. - void reserve_named_objects(size_type num) - { - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - m_header.m_named_index.reserve(num); - } - - //!Preallocates needed index resources to optimize the - //!creation of "num" unique objects in the managed memory segment. - //!Can throw boost::interprocess::bad_alloc if there is no enough memory. - void reserve_unique_objects(size_type num) - { - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - m_header.m_unique_index.reserve(num); - } - - //!Calls shrink_to_fit in both named and unique object indexes - //!to try to free unused memory from those indexes. - void shrink_to_fit_indexes() - { - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - m_header.m_named_index.shrink_to_fit(); - m_header.m_unique_index.shrink_to_fit(); - } - - //!Returns the number of named objects stored in - //!the segment. - size_type get_num_named_objects() - { - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - return m_header.m_named_index.size(); - } - - //!Returns the number of unique objects stored in - //!the segment. - size_type get_num_unique_objects() - { - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - return m_header.m_unique_index.size(); - } - - //!Obtains the minimum size needed by the - //!segment manager - static size_type get_min_size() - { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); } - - //!Returns a constant iterator to the beginning of the information about - //!the named allocations performed in this segment manager - const_named_iterator named_begin() const - { - return (make_transform_iterator) - (m_header.m_named_index.begin(), named_transform()); - } - - //!Returns a constant iterator to the end of the information about - //!the named allocations performed in this segment manager - const_named_iterator named_end() const - { - return (make_transform_iterator) - (m_header.m_named_index.end(), named_transform()); - } - - //!Returns a constant iterator to the beginning of the information about - //!the unique allocations performed in this segment manager - const_unique_iterator unique_begin() const - { - return (make_transform_iterator) - (m_header.m_unique_index.begin(), unique_transform()); - } - - //!Returns a constant iterator to the end of the information about - //!the unique allocations performed in this segment manager - const_unique_iterator unique_end() const - { - return (make_transform_iterator) - (m_header.m_unique_index.end(), unique_transform()); - } - - //!This is the default allocator to allocate types T - //!from this managed segment - template - struct allocator - { - typedef boost::interprocess::allocator type; - }; - - //!Returns an instance of the default allocator for type T - //!initialized that allocates memory from this segment manager. - template - typename allocator::type - get_allocator() - { return typename allocator::type(this); } - - //!This is the default deleter to delete types T - //!from this managed segment. - template - struct deleter - { - typedef boost::interprocess::deleter type; - }; - - //!Returns an instance of the default deleter for type T - //!that will delete an object constructed in this segment manager. - template - typename deleter::type - get_deleter() - { return typename deleter::type(this); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Generic named/anonymous new function. Offers all the possibilities, - //!such as throwing, search before creating, and the constructor is - //!encapsulated in an object function. - template - T *generic_construct(const CharType *name, - size_type num, - bool try2find, - bool dothrow, - ipcdetail::in_place_interface &table) - { - return static_cast - (priv_generic_construct(name, num, try2find, dothrow, table)); - } - - private: - //!Tries to find a previous named allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. - template - std::pair priv_find_impl (const CharType* name, bool lock) - { - //The name can't be null, no anonymous object can be found by name - BOOST_ASSERT(name != 0); - ipcdetail::placement_destroy table; - size_type sz; - void *ret; - - if(name == reinterpret_cast(-1)){ - ret = priv_generic_find (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock); - } - else{ - ret = priv_generic_find (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock); - } - return std::pair(static_cast(ret), sz); - } - - //!Tries to find a previous unique allocation. Returns the address - //!and the object count. On failure the first member of the - //!returned pair is 0. - template - std::pair priv_find_impl (const ipcdetail::unique_instance_t* name, bool lock) - { - ipcdetail::placement_destroy table; - size_type size; - void *ret = priv_generic_find(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock); - return std::pair(static_cast(ret), size); - } - - void *priv_generic_construct - (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table) - { - void *ret; - //Security overflow check - if(num > ((std::size_t)-1)/table.size){ - if(dothrow) - throw bad_alloc(); - else - return 0; - } - if(name == 0){ - ret = this->prot_anonymous_construct(num, dothrow, table); - } - else if(name == reinterpret_cast(-1)){ - ret = this->priv_generic_named_construct - (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t()); - } - else{ - ret = this->priv_generic_named_construct - (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t()); - } - return ret; - } - - void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor) - { - block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment); - switch(ctrl_data->alloc_type()){ - case anonymous_type: - this->prot_anonymous_destroy(ptr, dtor); - break; - - case named_type: - this->priv_generic_named_destroy - (ctrl_data, m_header.m_named_index, dtor, is_node_index_t()); - break; - - case unique_type: - this->priv_generic_named_destroy - (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t()); - break; - - default: - //This type is unknown, bad pointer passed to this function! - BOOST_ASSERT(0); - break; - } - } - - //!Returns the name of an object created with construct/find_or_construct - //!functions. Does not throw - static const CharType *priv_get_instance_name(block_header_t *ctrl_data) - { - boost::interprocess::allocation_type type = ctrl_data->alloc_type(); - if(type == anonymous_type){ - BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) || - (type == unique_type && ctrl_data->m_num_char != 0) ); - return 0; - } - CharType *name = static_cast(ctrl_data->template name()); - - //Sanity checks - BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType)); - BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits::length(name)); - return name; - } - - static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue) - { - //Get header - BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0); - return ctrl_data->value_bytes()/sizeofvalue; - } - - //!Returns is the the name of an object created with construct/find_or_construct - //!functions. Does not throw - static instance_type priv_get_instance_type(block_header_t *ctrl_data) - { - //Get header - BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type); - return (instance_type)ctrl_data->alloc_type(); - } - - static size_type priv_get_reserved_bytes() - { - //Get the number of bytes until the end of (*this) - //beginning in the end of the segment_manager_base_t base. - return sizeof(segment_manager) - sizeof(segment_manager_base_t); - } - - template - void *priv_generic_find - (const CharT* name, - IndexType > &index, - ipcdetail::in_place_interface &table, - size_type &length, ipcdetail::true_ is_intrusive, bool use_lock) - { - (void)is_intrusive; - typedef IndexType > index_type_t; - typedef typename index_type_t::iterator index_it; - - //------------------------------- - scoped_lock guard(priv_get_lock(use_lock)); - //------------------------------- - //Find name in index - ipcdetail::intrusive_compare_key key - (name, std::char_traits::length(name)); - index_it it = index.find(key); - - //Initialize return values - void *ret_ptr = 0; - length = 0; - - //If found, assign values - if(it != index.end()){ - //Get header - block_header_t *ctrl_data = it->get_block_header(); - - //Sanity check - BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); - BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT)); - ret_ptr = ctrl_data->value(); - length = ctrl_data->m_value_bytes/table.size; - } - return ret_ptr; - } - - template - void *priv_generic_find - (const CharT* name, - IndexType > &index, - ipcdetail::in_place_interface &table, - size_type &length, ipcdetail::false_ is_intrusive, bool use_lock) - { - (void)is_intrusive; - typedef IndexType > char_aware_index_type; - typedef typename char_aware_index_type::key_type key_type; - typedef typename char_aware_index_type::iterator index_it; - - //------------------------------- - scoped_lock guard(priv_get_lock(use_lock)); - //------------------------------- - //Find name in index - index_it it = index.find(key_type(name, std::char_traits::length(name))); - - //Initialize return values - void *ret_ptr = 0; - length = 0; - - //If found, assign values - if(it != index.end()){ - //Get header - block_header_t *ctrl_data = reinterpret_cast - (ipcdetail::to_raw_pointer(it->second.m_ptr)); - - //Sanity check - BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); - BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT)); - ret_ptr = ctrl_data->value(); - length = ctrl_data->m_value_bytes/table.size; - } - return ret_ptr; - } - - template - bool priv_generic_named_destroy - (block_header_t *block_header, - IndexType > &index, - ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index) - { - (void)is_node_index; - typedef typename IndexType >::iterator index_it; - - index_it *ihdr = block_header_t::template to_first_header(block_header); - return this->priv_generic_named_destroy_impl(*ihdr, index, table); - } - - template - bool priv_generic_named_destroy - (block_header_t *block_header, - IndexType > &index, - ipcdetail::in_place_interface &table, - ipcdetail::false_ is_node_index) - { - (void)is_node_index; - CharT *name = static_cast(block_header->template name()); - return this->priv_generic_named_destroy(name, index, table, is_intrusive_t()); - } - - template - bool priv_generic_named_destroy(const CharT *name, - IndexType > &index, - ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index) - { - (void)is_intrusive_index; - typedef IndexType > index_type_t; - typedef typename index_type_t::iterator index_it; - typedef typename index_type_t::value_type intrusive_value_type; - - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - //Find name in index - ipcdetail::intrusive_compare_key key - (name, std::char_traits::length(name)); - index_it it = index.find(key); - - //If not found, return false - if(it == index.end()){ - //This name is not present in the index, wrong pointer or name! - //BOOST_ASSERT(0); - return false; - } - - block_header_t *ctrl_data = it->get_block_header(); - intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data); - void *memory = iv; - void *values = ctrl_data->value(); - std::size_t num = ctrl_data->m_value_bytes/table.size; - - //Sanity check - BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); - BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); - - //Erase node from index - index.erase(it); - - //Destroy the headers - ctrl_data->~block_header_t(); - iv->~intrusive_value_type(); - - //Call destructors and free memory - table.destroy_n(values, num); - this->deallocate(memory); - return true; - } - - template - bool priv_generic_named_destroy(const CharT *name, - IndexType > &index, - ipcdetail::in_place_interface &table, - ipcdetail::false_ is_intrusive_index) - { - (void)is_intrusive_index; - typedef IndexType > char_aware_index_type; - typedef typename char_aware_index_type::iterator index_it; - typedef typename char_aware_index_type::key_type key_type; - - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - //Try to find the name in the index - index_it it = index.find(key_type (name, - std::char_traits::length(name))); - - //If not found, return false - if(it == index.end()){ - //This name is not present in the index, wrong pointer or name! - //BOOST_ASSERT(0); - return false; - } - return this->priv_generic_named_destroy_impl(it, index, table); - } - - template - bool priv_generic_named_destroy_impl - (const typename IndexType >::iterator &it, - IndexType > &index, - ipcdetail::in_place_interface &table) - { - typedef IndexType > char_aware_index_type; - typedef typename char_aware_index_type::iterator index_it; - - //Get allocation parameters - block_header_t *ctrl_data = reinterpret_cast - (ipcdetail::to_raw_pointer(it->second.m_ptr)); - char *stored_name = static_cast(static_cast(const_cast(it->first.name()))); - (void)stored_name; - - //Check if the distance between the name pointer and the memory pointer - //is correct (this can detect incorrect type in destruction) - std::size_t num = ctrl_data->m_value_bytes/table.size; - void *values = ctrl_data->value(); - - //Sanity check - BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); - BOOST_ASSERT(static_cast(stored_name) == static_cast(ctrl_data->template name())); - BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); - - //Erase node from index - index.erase(it); - - //Destroy the header - ctrl_data->~block_header_t(); - - void *memory; - if(is_node_index_t::value){ - index_it *ihdr = block_header_t::template - to_first_header(ctrl_data); - ihdr->~index_it(); - memory = ihdr; - } - else{ - memory = ctrl_data; - } - - //Call destructors and free memory - table.destroy_n(values, num); - this->deallocate(memory); - return true; - } - - template - void * priv_generic_named_construct - (unsigned char type, const CharT *name, size_type num, bool try2find, - bool dothrow, ipcdetail::in_place_interface &table, - IndexType > &index, ipcdetail::true_ is_intrusive) - { - (void)is_intrusive; - std::size_t namelen = std::char_traits::length(name); - - block_header_t block_info ( size_type(table.size*num) - , size_type(table.alignment) - , type - , sizeof(CharT) - , namelen); - - typedef IndexType > index_type_t; - typedef typename index_type_t::iterator index_it; - typedef std::pair index_ib; - - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - //Insert the node. This can throw. - //First, we want to know if the key is already present before - //we allocate any memory, and if the key is not present, we - //want to allocate all memory in a single buffer that will - //contain the name and the user buffer. - // - //Since equal_range(key) + insert(hint, value) approach is - //quite inefficient in container implementations - //(they re-test if the position is correct), I've chosen - //to insert the node, do an ugly un-const cast and modify - //the key (which is a smart pointer) to an equivalent one - index_ib insert_ret; - - typename index_type_t::insert_commit_data commit_data; - typedef typename index_type_t::value_type intrusive_value_type; - - BOOST_TRY{ - ipcdetail::intrusive_compare_key key(name, namelen); - insert_ret = index.insert_check(key, commit_data); - } - //Ignore exceptions - BOOST_CATCH(...){ - if(dothrow) - BOOST_RETHROW - return 0; - } - BOOST_CATCH_END - - index_it it = insert_ret.first; - - //If found and this is find or construct, return data - //else return null - if(!insert_ret.second){ - if(try2find){ - return it->get_block_header()->value(); - } - if(dothrow){ - throw interprocess_exception(already_exists_error); - } - else{ - return 0; - } - } - - //Allocates buffer for name + data, this can throw (it hurts) - void *buffer_ptr; - - //Check if there is enough memory - if(dothrow){ - buffer_ptr = this->allocate - (block_info.template total_size_with_header()); - } - else{ - buffer_ptr = this->allocate - (block_info.template total_size_with_header(), nothrow<>::get()); - if(!buffer_ptr) - return 0; - } - - //Now construct the intrusive hook plus the header - intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type(); - block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t())block_header_t(block_info); - void *ptr = 0; //avoid gcc warning - ptr = hdr->value(); - - //Copy name to memory segment and insert data - CharT *name_ptr = static_cast(hdr->template name()); - std::char_traits::copy(name_ptr, name, namelen+1); - - BOOST_TRY{ - //Now commit the insertion using previous context data - it = index.insert_commit(*intrusive_hdr, commit_data); - } - //Ignore exceptions - BOOST_CATCH(...){ - if(dothrow) - BOOST_RETHROW - return 0; - } - BOOST_CATCH_END - - //Avoid constructions if constructor is trivial - //Build scoped ptr to avoid leaks with constructor exception - ipcdetail::mem_algo_deallocator mem - (buffer_ptr, *static_cast(this)); - - //Initialize the node value_eraser to erase inserted node - //if something goes wrong. This will be executed *before* - //the memory allocation as the intrusive value is built in that - //memory - value_eraser v_eraser(index, it); - - //Construct array, this can throw - table.construct_n(ptr, num); - - //Release rollbacks since construction was successful - v_eraser.release(); - mem.release(); - return ptr; - } - - //!Generic named new function for - //!named functions - template - void * priv_generic_named_construct - (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow, - ipcdetail::in_place_interface &table, - IndexType > &index, ipcdetail::false_ is_intrusive) - { - (void)is_intrusive; - std::size_t namelen = std::char_traits::length(name); - - block_header_t block_info ( size_type(table.size*num) - , size_type(table.alignment) - , type - , sizeof(CharT) - , namelen); - - typedef IndexType > index_type_t; - typedef typename index_type_t::key_type key_type; - typedef typename index_type_t::mapped_type mapped_type; - typedef typename index_type_t::value_type value_type; - typedef typename index_type_t::iterator index_it; - typedef std::pair index_ib; - - //------------------------------- - scoped_lock guard(m_header); - //------------------------------- - //Insert the node. This can throw. - //First, we want to know if the key is already present before - //we allocate any memory, and if the key is not present, we - //want to allocate all memory in a single buffer that will - //contain the name and the user buffer. - // - //Since equal_range(key) + insert(hint, value) approach is - //quite inefficient in container implementations - //(they re-test if the position is correct), I've chosen - //to insert the node, do an ugly un-const cast and modify - //the key (which is a smart pointer) to an equivalent one - index_ib insert_ret; - BOOST_TRY{ - insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0))); - } - //Ignore exceptions - BOOST_CATCH(...){ - if(dothrow) - BOOST_RETHROW; - return 0; - } - BOOST_CATCH_END - - index_it it = insert_ret.first; - - //If found and this is find or construct, return data - //else return null - if(!insert_ret.second){ - if(try2find){ - block_header_t *hdr = static_cast - (ipcdetail::to_raw_pointer(it->second.m_ptr)); - return hdr->value(); - } - return 0; - } - //Initialize the node value_eraser to erase inserted node - //if something goes wrong - value_eraser v_eraser(index, it); - - //Allocates buffer for name + data, this can throw (it hurts) - void *buffer_ptr; - block_header_t * hdr; - - //Allocate and construct the headers - if(is_node_index_t::value){ - size_type total_size = block_info.template total_size_with_header(); - if(dothrow){ - buffer_ptr = this->allocate(total_size); - } - else{ - buffer_ptr = this->allocate(total_size, nothrow<>::get()); - if(!buffer_ptr) - return 0; - } - index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it); - hdr = block_header_t::template from_first_header(idr); - } - else{ - if(dothrow){ - buffer_ptr = this->allocate(block_info.total_size()); - } - else{ - buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get()); - if(!buffer_ptr) - return 0; - } - hdr = static_cast(buffer_ptr); - } - - hdr = ::new(hdr, boost_container_new_t())block_header_t(block_info); - void *ptr = 0; //avoid gcc warning - ptr = hdr->value(); - - //Copy name to memory segment and insert data - CharT *name_ptr = static_cast(hdr->template name()); - std::char_traits::copy(name_ptr, name, namelen+1); - - //Do the ugly cast, please mama, forgive me! - //This new key points to an identical string, so it must have the - //same position than the overwritten key according to the predicate - const_cast(it->first).name(name_ptr); - it->second.m_ptr = hdr; - - //Build scoped ptr to avoid leaks with constructor exception - ipcdetail::mem_algo_deallocator mem - (buffer_ptr, *static_cast(this)); - - //Construct array, this can throw - table.construct_n(ptr, num); - - //All constructors successful, we don't want to release memory - mem.release(); - - //Release node v_eraser since construction was successful - v_eraser.release(); - return ptr; - } - - private: - //!Returns the this pointer - segment_manager *get_this_pointer() - { return this; } - - typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex; - - scoped_lock priv_get_lock(bool use_lock) - { - scoped_lock local(m_header, defer_lock); - if(use_lock){ - local.lock(); - } - return scoped_lock(boost::move(local)); - } - - //!This struct includes needed data and derives from - //!rmutex to allow EBO when using null interprocess_mutex - struct header_t - : public rmutex - { - named_index_t m_named_index; - unique_index_t m_unique_index; - - header_t(segment_manager_base_t *segment_mngr_base) - : m_named_index (segment_mngr_base) - , m_unique_index(segment_mngr_base) - {} - } m_header; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - - -}} //namespace boost { namespace interprocess - -#include - -#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP - diff --git a/extern/boost/boost/interprocess/smart_ptr/deleter.hpp b/extern/boost/boost/interprocess/smart_ptr/deleter.hpp deleted file mode 100644 index bc0f8c8aaf5..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/deleter.hpp +++ /dev/null @@ -1,68 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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_DELETER_HPP -#define BOOST_INTERPROCESS_DELETER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include - -//!\file -//!Describes the functor to delete objects from the segment. - -namespace boost { -namespace interprocess { - -//!A deleter that uses the segment manager's destroy_ptr -//!function to destroy the passed pointer resource. -//! -//!This deleter is used -template -class deleter -{ - public: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - - private: - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type segment_manager_pointer; - - segment_manager_pointer mp_mngr; - - public: - deleter(segment_manager_pointer pmngr) BOOST_NOEXCEPT - : mp_mngr(pmngr) - {} - - void operator()(const pointer &p) - { mp_mngr->destroy_ptr(ipcdetail::to_raw_pointer(p)); } -}; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DELETER_HPP diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp deleted file mode 100644 index e2ce9a78d87..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp +++ /dev/null @@ -1,48 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/detail/bad_weak_ptr.hpp -// -// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006. 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_BAD_WEAK_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#ifndef BOOST_NO_EXCEPTIONS -#include -#endif - -namespace boost{ -namespace interprocess{ - -class bad_weak_ptr - : public std::exception -{ - public: - - virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE - { return "boost::interprocess::bad_weak_ptr"; } -}; - -} // namespace interprocess -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp deleted file mode 100644 index 9b0244e4230..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp +++ /dev/null @@ -1,347 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/detail/shared_count.hpp -// -// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 -// (C) Copyright Peter Dimov 2004-2005 -// (C) Copyright Ion Gaztanaga 2006-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_SHARED_COUNT_HPP_INCLUDED -#define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include //std::less -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -template -class weak_count; - -template -class shared_count -{ - public: - - typedef typename boost::container:: - allocator_traits::pointer void_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - - private: - typedef sp_counted_impl_pd counted_impl; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type counted_impl_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type counted_base_ptr; - - typedef boost::container::allocator_traits vallocator_traits; - - typedef typename vallocator_traits::template - portable_rebind_alloc::type counted_impl_allocator; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_deleter_pointer; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_allocator_pointer; - - pointer m_px; - counted_impl_ptr m_pi; - - template - friend class weak_count; - - template - friend class shared_count; - - public: - - shared_count() - : m_px(0), m_pi(0) // nothrow - {} - - template - shared_count(const shared_count &other_shared_count, const Ptr &p) - : m_px(p), m_pi(other_shared_count.m_pi) - {} - - template - shared_count(const Ptr &p, const VoidAllocator &a, Deleter d) - : m_px(p), m_pi(0) - { - BOOST_TRY{ - if(p){ - counted_impl_allocator alloc(a); - m_pi = alloc.allocate(1); - //Anti-exception deallocator - scoped_ptr > - deallocator(m_pi, alloc); - //It's more correct to use VoidAllocator::construct but - //this needs copy constructor and we don't like it - ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d); - deallocator.release(); - } - } - BOOST_CATCH (...){ - d(p); // delete p - BOOST_RETHROW - } - BOOST_CATCH_END - } - - ~shared_count() // nothrow - { - if(m_pi) - m_pi->release(); - } - - shared_count(shared_count const & r) - : m_px(r.m_px), m_pi(r.m_pi) // nothrow - { if( m_pi != 0 ) m_pi->add_ref_copy(); } - - //this is a test - template - explicit shared_count(shared_count const & r) - : m_px(r.m_px), m_pi(r.m_pi) // nothrow - { if( m_pi != 0 ) m_pi->add_ref_copy(); } - - //this is a test - template - explicit shared_count(const pointer & ptr, shared_count const & r) - : m_px(ptr), m_pi(r.m_pi) // nothrow - { if( m_pi != 0 ) m_pi->add_ref_copy(); } - -/* - explicit shared_count(weak_count const & r) - // throws bad_weak_ptr when r.use_count() == 0 - : m_pi( r.m_pi ) - { - if( m_pi == 0 || !m_pi->add_ref_lock() ){ - boost::throw_exception( boost::interprocess::bad_weak_ptr() ); - } - } -*/ - template - explicit shared_count(weak_count const & r) - // throws bad_weak_ptr when r.use_count() == 0 - : m_px(r.m_px), m_pi( r.m_pi ) - { - if( m_pi == 0 || !m_pi->add_ref_lock() ){ - throw( boost::interprocess::bad_weak_ptr() ); - } - } - - const pointer &to_raw_pointer() const - { return m_px; } - - pointer &to_raw_pointer() - { return m_px; } - - shared_count & operator= (shared_count const & r) // nothrow - { - m_px = r.m_px; - counted_impl_ptr tmp = r.m_pi; - if( tmp != m_pi ){ - if(tmp != 0) tmp->add_ref_copy(); - if(m_pi != 0) m_pi->release(); - m_pi = tmp; - } - return *this; - } - - template - shared_count & operator= (shared_count const & r) // nothrow - { - m_px = r.m_px; - counted_impl_ptr tmp = r.m_pi; - if( tmp != m_pi ){ - if(tmp != 0) tmp->add_ref_copy(); - if(m_pi != 0) m_pi->release(); - m_pi = tmp; - } - return *this; - } - - void swap(shared_count & r) // nothrow - { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } - - long use_count() const // nothrow - { return m_pi != 0? m_pi->use_count(): 0; } - - bool unique() const // nothrow - { return use_count() == 1; } - - const_deleter_pointer get_deleter() const - { return m_pi ? m_pi->get_deleter() : 0; } - -// const_allocator_pointer get_allocator() const -// { return m_pi ? m_pi->get_allocator() : 0; } - - template - bool internal_equal (shared_count const & other) const - { return this->m_pi == other.m_pi; } - - template - bool internal_less (shared_count const & other) const - { return std::less()(this->m_pi, other.m_pi); } -}; - -template inline -bool operator==(shared_count const & a, shared_count const & b) -{ return a.internal_equal(b); } - -template inline -bool operator<(shared_count const & a, shared_count const & b) -{ return a.internal_less(b); } - - -template -class weak_count -{ - public: - typedef typename boost::container:: - allocator_traits::pointer void_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - - private: - - typedef sp_counted_impl_pd counted_impl; - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type counted_impl_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type counted_base_ptr; - - pointer m_px; - counted_impl_ptr m_pi; - - template - friend class weak_count; - - template - friend class shared_count; - - public: - - weak_count(): m_px(0), m_pi(0) // nothrow - {} - - template - explicit weak_count(shared_count const & r) - : m_px(r.m_px), m_pi(r.m_pi) // nothrow - { if(m_pi != 0) m_pi->weak_add_ref(); } - - weak_count(weak_count const & r) - : m_px(r.m_px), m_pi(r.m_pi) // nothrow - { if(m_pi != 0) m_pi->weak_add_ref(); } - - template - weak_count(weak_count const & r) - : m_px(r.m_px), m_pi(r.m_pi) // nothrow - { if(m_pi != 0) m_pi->weak_add_ref(); } - - ~weak_count() // nothrow - { if(m_pi != 0) m_pi->weak_release(); } - - template - weak_count & operator= (shared_count const & r) // nothrow - { - m_px = r.m_px; - counted_impl_ptr tmp = r.m_pi; - if(tmp != 0) tmp->weak_add_ref(); - if(m_pi != 0) m_pi->weak_release(); - m_pi = tmp; - return *this; - } - - weak_count & operator= (weak_count const & r) // nothrow - { - m_px = r.m_px; - counted_impl_ptr tmp = r.m_pi; - if(tmp != 0) tmp->weak_add_ref(); - if(m_pi != 0) m_pi->weak_release(); - m_pi = tmp; - return *this; - } - - void set_pointer(const pointer &ptr) - { m_px = ptr; } - - template - weak_count & operator= (weak_count const& r) // nothrow - { - counted_impl_ptr tmp = r.m_pi; - if(tmp != 0) tmp->weak_add_ref(); - if(m_pi != 0) m_pi->weak_release(); - m_pi = tmp; - return *this; - } - - void swap(weak_count & r) // nothrow - { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } - - long use_count() const // nothrow - { return m_pi != 0? m_pi->use_count() : 0; } - - template - bool internal_equal (weak_count const & other) const - { return this->m_pi == other.m_pi; } - - template - bool internal_less (weak_count const & other) const - { return std::less()(this->m_pi, other.m_pi); } -}; - -template inline -bool operator==(weak_count const & a, weak_count const & b) -{ return a.internal_equal(b); } - -template inline -bool operator<(weak_count const & a, weak_count const & b) -{ return a.internal_less(b); } - -} // namespace ipcdetail -} // namespace interprocess -} // namespace boost - - -#include - - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp deleted file mode 100644 index 3b6a0876f92..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp +++ /dev/null @@ -1,26 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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_SP_COUNTED_BASE_HPP_INCLUDED -#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -# include - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED - diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp deleted file mode 100644 index 50392741d0e..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED -#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov -// Copyright 2007-2012 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) -// -// -// Lock-free algorithm by Alexander Terekhov -// -// Thanks to Ben Hitchings for the #weak + (#shared != 0) -// formulation -// - -#include -#include - -#include -#include - -namespace boost { - -namespace interprocess { - -namespace ipcdetail { - -class sp_counted_base -{ -private: - - sp_counted_base( sp_counted_base const & ); - sp_counted_base & operator= ( sp_counted_base const & ); - - boost::uint32_t use_count_; // #shared - boost::uint32_t weak_count_; // #weak + (#shared != 0) - -public: - - sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) - {} - - ~sp_counted_base() // nothrow - {} - - void add_ref_copy() - { - ipcdetail::atomic_inc32( &use_count_ ); - } - - bool add_ref_lock() // true on success - { - for( ;; ) - { - boost::uint32_t tmp = static_cast< boost::uint32_t const volatile& >( use_count_ ); - if( tmp == 0 ) return false; - if( ipcdetail::atomic_cas32( &use_count_, tmp + 1, tmp ) == tmp ) - return true; - } - } - - bool ref_release() // nothrow - { return 1 == ipcdetail::atomic_dec32( &use_count_ ); } - - void weak_add_ref() // nothrow - { ipcdetail::atomic_inc32( &weak_count_ ); } - - bool weak_release() // nothrow - { return 1 == ipcdetail::atomic_dec32( &weak_count_ ); } - - long use_count() const // nothrow - { return (long)static_cast( use_count_ ); } -}; - -} // namespace ipcdetail - -} // namespace interprocess - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp deleted file mode 100644 index ed1d72706f4..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED -#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -// -// This file is the adaptation for shared memory memory mapped -// files of boost/detail/sp_counted_impl.hpp -// -// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov -// Copyright 2006 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) -// - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace boost { - -namespace interprocess { - -namespace ipcdetail { - -//!A deleter for scoped_ptr that deallocates the memory -//!allocated for an object using a STL allocator. -template -struct scoped_ptr_dealloc_functor -{ - typedef typename boost::container:: - allocator_traits::pointer pointer; - - typedef ipcdetail::integral_constant::value> alloc_version; - typedef ipcdetail::integral_constant allocator_v1; - typedef ipcdetail::integral_constant allocator_v2; - - private: - void priv_deallocate(const pointer &p, allocator_v1) - { m_alloc.deallocate(p, 1); } - - void priv_deallocate(const pointer &p, allocator_v2) - { m_alloc.deallocate_one(p); } - - public: - Allocator& m_alloc; - - scoped_ptr_dealloc_functor(Allocator& a) - : m_alloc(a) {} - - void operator()(pointer ptr) - { if (ptr) priv_deallocate(ptr, alloc_version()); } -}; - - - -template -class sp_counted_impl_pd - : public sp_counted_base - , boost::container::allocator_traits::template - portable_rebind_alloc< sp_counted_impl_pd >::type - , D // copy constructor must not throw -{ - private: - typedef sp_counted_impl_pd this_type; - typedef typename boost::container:: - allocator_traits::template - portable_rebind_alloc - < this_type >::type this_allocator; - typedef typename boost::container:: - allocator_traits::template - portable_rebind_alloc - < const this_type >::type const_this_allocator; - typedef typename boost::container:: - allocator_traits - ::pointer this_pointer; - typedef typename boost::container:: - allocator_traits::pointer a_pointer; - typedef typename boost::intrusive:: - pointer_traits this_pointer_traits; - - sp_counted_impl_pd( sp_counted_impl_pd const & ); - sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); - - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_deleter_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_allocator_pointer; - - typedef typename D::pointer pointer; - pointer m_ptr; - - public: - // pre: d(p) must not throw - template - sp_counted_impl_pd(const Ptr & p, const A &a, const D &d ) - : this_allocator(a), D(d), m_ptr(p) - {} - - const_deleter_pointer get_deleter() const - { return const_deleter_pointer(&static_cast(*this)); } - - const_allocator_pointer get_allocator() const - { return const_allocator_pointer(&static_cast(*this)); } - - void dispose() // nothrow - { static_cast(*this)(m_ptr); } - - void destroy() // nothrow - { - //Self destruction, so move the allocator - this_allocator a_copy(::boost::move(static_cast(*this))); - BOOST_ASSERT(a_copy == *this); - this_pointer this_ptr(this_pointer_traits::pointer_to(*this)); - //Do it now! - scoped_ptr< this_type, scoped_ptr_dealloc_functor > - deleter_ptr(this_ptr, a_copy); - ipcdetail::to_raw_pointer(this_ptr)->~this_type(); - } - - void release() // nothrow - { - if(this->ref_release()){ - this->dispose(); - this->weak_release(); - } - } - - void weak_release() // nothrow - { - if(sp_counted_base::weak_release()){ - this->destroy(); - } - } -}; - - -} // namespace ipcdetail - -} // namespace interprocess - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp deleted file mode 100644 index 188b68d6784..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/enable_shared_from_this.hpp +++ /dev/null @@ -1,87 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp -// -// (C) Copyright Peter Dimov 2002 -// (C) Copyright Ion Gaztanaga 2006-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_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED -#define BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include - -//!\file -//!Describes an utility to form a shared pointer from this - -namespace boost{ -namespace interprocess{ - -//!This class is used as a base class that allows a shared_ptr to the current -//!object to be obtained from within a member function. -//!enable_shared_from_this defines two member functions called shared_from_this -//!that return a shared_ptr and shared_ptr, depending on constness, to this. -template -class enable_shared_from_this -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - protected: - enable_shared_from_this() - {} - - enable_shared_from_this(enable_shared_from_this const &) - {} - - enable_shared_from_this & operator=(enable_shared_from_this const &) - { return *this; } - - ~enable_shared_from_this() - {} - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - shared_ptr shared_from_this() - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(ipcdetail::to_raw_pointer(p.get()) == this); - return p; - } - - shared_ptr shared_from_this() const - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(ipcdetail::to_raw_pointer(p.get()) == this); - return p; - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef T element_type; - mutable weak_ptr _internal_weak_this; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} // namespace interprocess -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED - diff --git a/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp deleted file mode 100644 index 585b9952d52..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/intrusive_ptr.hpp +++ /dev/null @@ -1,333 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp -// -// (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006-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_INTRUSIVE_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -//!\file -//!Describes an intrusive ownership pointer. - -#include -#include - -#include -#include -#include -#include -#include - -#include // for std::basic_ostream - -#include //std::less - -namespace boost { -namespace interprocess { - -//!The intrusive_ptr class template stores a pointer to an object -//!with an embedded reference count. intrusive_ptr is parameterized on -//!T (the type of the object pointed to) and VoidPointer(a void pointer type -//!that defines the type of pointer that intrusive_ptr will store). -//!intrusive_ptr defines a class with a T* member whereas -//!intrusive_ptr > defines a class with a offset_ptr member. -//!Relies on unqualified calls to: -//! -//! void intrusive_ptr_add_ref(T * p) BOOST_NOEXCEPT; -//! void intrusive_ptr_release(T * p) BOOST_NOEXCEPT; -//! -//! with (p != 0) -//! -//!The object is responsible for destroying itself. -template -class intrusive_ptr -{ - public: - //!Provides the type of the internal stored pointer. - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - //!Provides the type of the stored pointer. - typedef T element_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef VoidPointer VP; - typedef intrusive_ptr this_type; - typedef pointer this_type::*unspecified_bool_type; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - BOOST_COPYABLE_AND_MOVABLE(intrusive_ptr) - - public: - //!Constructor. Initializes internal pointer to 0. - //!Does not throw - intrusive_ptr() BOOST_NOEXCEPT - : m_ptr(0) - {} - - //!Constructor. Copies pointer and if "p" is not zero and - //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)). - //!Does not throw - intrusive_ptr(const pointer &p, bool add_ref = true) BOOST_NOEXCEPT - : m_ptr(p) - { - if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); - } - - //!Copy constructor. Copies the internal pointer and if "p" is not - //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw - intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT - : m_ptr(rhs.m_ptr) - { - if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); - } - - //!Move constructor. Moves the internal pointer. Does not throw - intrusive_ptr(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT - : m_ptr(rhs.m_ptr) - { - rhs.m_ptr = 0; - } - - //!Constructor from related. Copies the internal pointer and if "p" is not - //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw - template intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT - : m_ptr(rhs.get()) - { - if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); - } - - //!Destructor. Calls reset(). Does not throw - ~intrusive_ptr() - { - reset(); - } - - //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). - //!Does not throw - intrusive_ptr & operator=(BOOST_COPY_ASSIGN_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT - { - this_type(rhs).swap(*this); - return *this; - } - - //!Move Assignment operator - //!Does not throw - intrusive_ptr & operator=(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT - { - rhs.swap(*this); - rhs.reset(); - return *this; - } - - //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). - //!Does not throw - template intrusive_ptr & operator=(intrusive_ptr const & rhs) BOOST_NOEXCEPT - { - this_type(rhs).swap(*this); - return *this; - } - - //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). - //!Does not throw - intrusive_ptr & operator=(pointer rhs) BOOST_NOEXCEPT - { - this_type(rhs).swap(*this); - return *this; - } - - //!Release internal pointer and set it to 0. If internal pointer is not 0, calls - //!intrusive_ptr_release(to_raw_pointer(m_ptr)). Does not throw - void reset() BOOST_NOEXCEPT { - if(m_ptr != 0) { - pointer ptr = m_ptr; - m_ptr = 0; - intrusive_ptr_release(ipcdetail::to_raw_pointer(ptr)); - } - } - - //!Returns a reference to the internal pointer. - //!Does not throw - pointer &get() BOOST_NOEXCEPT - { return m_ptr; } - - //!Returns a reference to the internal pointer. - //!Does not throw - const pointer &get() const BOOST_NOEXCEPT - { return m_ptr; } - - //!Returns *get(). - //!Does not throw - T & operator*() const BOOST_NOEXCEPT - { return *m_ptr; } - - //!Returns *get(). - //!Does not throw - const pointer &operator->() const BOOST_NOEXCEPT - { return m_ptr; } - - //!Returns get(). - //!Does not throw - pointer &operator->() BOOST_NOEXCEPT - { return m_ptr; } - - //!Conversion to boolean. - //!Does not throw - operator unspecified_bool_type () const BOOST_NOEXCEPT - { return m_ptr == 0? 0: &this_type::m_ptr; } - - //!Not operator. - //!Does not throw - bool operator! () const BOOST_NOEXCEPT - { return m_ptr == 0; } - - //!Exchanges the contents of the two smart pointers. - //!Does not throw - void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT - { ::boost::adl_move_swap(m_ptr, rhs.m_ptr); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - pointer m_ptr; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Returns a.get() == b.get(). -//!Does not throw -template inline -bool operator==(intrusive_ptr const & a, - intrusive_ptr const & b) BOOST_NOEXCEPT -{ return a.get() == b.get(); } - -//!Returns a.get() != b.get(). -//!Does not throw -template inline -bool operator!=(intrusive_ptr const & a, - intrusive_ptr const & b) BOOST_NOEXCEPT -{ return a.get() != b.get(); } - -//!Returns a.get() == b. -//!Does not throw -template inline -bool operator==(intrusive_ptr const & a, - const typename intrusive_ptr::pointer &b) BOOST_NOEXCEPT -{ return a.get() == b; } - -//!Returns a.get() != b. -//!Does not throw -template inline -bool operator!=(intrusive_ptr const & a, - const typename intrusive_ptr::pointer &b) BOOST_NOEXCEPT -{ return a.get() != b; } - -//!Returns a == b.get(). -//!Does not throw -template inline -bool operator==(const typename intrusive_ptr::pointer &a, - intrusive_ptr const & b) BOOST_NOEXCEPT -{ return a == b.get(); } - -//!Returns a != b.get(). -//!Does not throw -template inline -bool operator!=(const typename intrusive_ptr::pointer &a, - intrusive_ptr const & b) BOOST_NOEXCEPT -{ return a != b.get(); } - -//!Returns a.get() < b.get(). -//!Does not throw -template inline -bool operator<(intrusive_ptr const & a, - intrusive_ptr const & b) BOOST_NOEXCEPT -{ - return std::less::pointer>() - (a.get(), b.get()); -} - -//!Exchanges the contents of the two intrusive_ptrs. -//!Does not throw -template inline -void swap(intrusive_ptr & lhs, - intrusive_ptr & rhs) BOOST_NOEXCEPT -{ lhs.swap(rhs); } - -// operator<< -template -inline std::basic_ostream & operator<< - (std::basic_ostream & os, intrusive_ptr const & p) BOOST_NOEXCEPT -{ os << p.get(); return os; } - -//!Returns p.get(). -//!Does not throw -template -inline typename boost::interprocess::intrusive_ptr::pointer - to_raw_pointer(intrusive_ptr p) BOOST_NOEXCEPT -{ return p.get(); } - -/*Emulates static cast operator. Does not throw*/ -/* -template -inline boost::interprocess::intrusive_ptr static_pointer_cast - (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT -{ return do_static_cast(p.get()); } -*/ -/*Emulates const cast operator. Does not throw*/ -/* -template -inline boost::interprocess::intrusive_ptr const_pointer_cast - (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT -{ return do_const_cast(p.get()); } -*/ - -/*Emulates dynamic cast operator. Does not throw*/ -/* -template -inline boost::interprocess::intrusive_ptr dynamic_pointer_cast - (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT -{ return do_dynamic_cast(p.get()); } -*/ - -/*Emulates reinterpret cast operator. Does not throw*/ -/* -template -inline boost::interprocess::intrusive_ptrreinterpret_pointer_cast - (boost::interprocess::intrusive_ptr const & p) BOOST_NOEXCEPT -{ return do_reinterpret_cast(p.get()); } -*/ - -} // namespace interprocess - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#if defined(_MSC_VER) && (_MSC_VER < 1400) -//!Returns p.get(). -//!Does not throw -template -inline T *to_raw_pointer(boost::interprocess::intrusive_ptr p) BOOST_NOEXCEPT -{ return p.get(); } -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp deleted file mode 100644 index f480428ca89..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/scoped_ptr.hpp +++ /dev/null @@ -1,176 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/scoped_ptr.hpp -// -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006-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_SCOPED_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes the smart pointer scoped_ptr - -namespace boost { -namespace interprocess { - -//!scoped_ptr stores a pointer to a dynamically allocated object. -//!The object pointed to is guaranteed to be deleted, either on destruction -//!of the scoped_ptr, or via an explicit reset. The user can avoid this -//!deletion using release(). -//!scoped_ptr is parameterized on T (the type of the object pointed to) and -//!Deleter (the functor to be executed to delete the internal pointer). -//!The internal pointer will be of the same pointer type as typename -//!Deleter::pointer type (that is, if typename Deleter::pointer is -//!offset_ptr, the internal pointer will be offset_ptr). -template -class scoped_ptr - : private Deleter -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - scoped_ptr(scoped_ptr const &); - scoped_ptr & operator=(scoped_ptr const &); - - typedef scoped_ptr this_type; - typedef typename ipcdetail::add_reference::type reference; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - - typedef T element_type; - typedef Deleter deleter_type; - typedef typename ipcdetail::pointer_type::type pointer; - - //!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d. - //!Does not throw. - explicit scoped_ptr(const pointer &p = 0, const Deleter &d = Deleter()) - : Deleter(d), m_ptr(p) // throws if pointer/Deleter copy ctor throws - {} - - //!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. - //!calling the operator() of the stored deleter. Never throws - ~scoped_ptr() - { - if(m_ptr){ - Deleter &del = static_cast(*this); - del(m_ptr); - } - } - - //!Deletes the object pointed to by the stored pointer and then - //!stores a copy of p. Never throws - void reset(const pointer &p = 0) // never throws - { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p).swap(*this); } - - //!Deletes the object pointed to by the stored pointer and then - //!stores a copy of p and a copy of d. - void reset(const pointer &p, const Deleter &d) // never throws - { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p, d).swap(*this); } - - //!Assigns internal pointer as 0 and returns previous pointer. This will - //!avoid deletion on destructor - 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 BOOST_NOEXCEPT - { BOOST_ASSERT(m_ptr != 0); return *m_ptr; } - - //!Returns the internal stored pointer. - //!Never throws. - pointer &operator->() BOOST_NOEXCEPT - { BOOST_ASSERT(m_ptr != 0); return m_ptr; } - - //!Returns the internal stored pointer. - //!Never throws. - const pointer &operator->() const BOOST_NOEXCEPT - { BOOST_ASSERT(m_ptr != 0); return m_ptr; } - - //!Returns the stored pointer. - //!Never throws. - pointer & get() BOOST_NOEXCEPT - { return m_ptr; } - - //!Returns the stored pointer. - //!Never throws. - 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 BOOST_NOEXCEPT - { return m_ptr == 0? 0: &this_type::m_ptr; } - - //!Returns true if the stored pointer is 0. - //!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) BOOST_NOEXCEPT // never throws - { - ::boost::adl_move_swap(static_cast(*this), static_cast(b)); - ::boost::adl_move_swap(m_ptr, b.m_ptr); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - pointer m_ptr; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!Exchanges the internal pointer and deleter with other scoped_ptr -//!Never throws. -template inline -void swap(scoped_ptr & a, scoped_ptr & b) BOOST_NOEXCEPT -{ a.swap(b); } - -//!Returns a copy of the stored pointer -//!Never throws -template inline -typename scoped_ptr::pointer to_raw_pointer(scoped_ptr const & p) -{ return p.get(); } - -} // namespace interprocess - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#if defined(_MSC_VER) && (_MSC_VER < 1400) -template inline -T *to_raw_pointer(boost::interprocess::scoped_ptr const & p) -{ return p.get(); } -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp deleted file mode 100644 index 7633bd5de73..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/shared_ptr.hpp +++ /dev/null @@ -1,430 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/shared_ptr.hpp -// -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-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_SHARED_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // for std::basic_ostream - -//!\file -//!Describes the smart pointer shared_ptr - -namespace boost{ -namespace interprocess{ - -template class weak_ptr; -template class enable_shared_from_this; - -namespace ipcdetail{ - -template -inline void sp_enable_shared_from_this - (shared_count const & pn - ,enable_shared_from_this const*pe - ,T *ptr) - -{ - (void)ptr; - if(pe != 0){ - pe->_internal_weak_this._internal_assign(pn); - } -} - -template -inline void sp_enable_shared_from_this(shared_count const &, ...) -{} - -} // namespace ipcdetail - -//!shared_ptr stores a pointer to a dynamically allocated object. -//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to -//!it is destroyed or reset. -//! -//!shared_ptr is parameterized on -//!T (the type of the object pointed to), VoidAllocator (the void allocator to be used -//!to allocate the auxiliary data) and Deleter (the deleter whose -//!operator() will be used to delete the object. -//! -//!The internal pointer will be of the same pointer type as typename -//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is -//!offset_ptr, the internal pointer will be offset_ptr). -//! -//!Because the implementation uses reference counting, cycles of shared_ptr -//!instances will not be reclaimed. For example, if main() holds a -//!shared_ptr to A, which directly or indirectly holds a shared_ptr back -//!to A, A's use count will be 2. Destruction of the original shared_ptr -//!will leave A dangling with a use count of 1. -//!Use weak_ptr to "break cycles." -template -class shared_ptr -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef shared_ptr this_type; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - - typedef T element_type; - typedef T value_type; - typedef typename boost::container:: - allocator_traits::pointer void_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_deleter_pointer; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type const_allocator_pointer; - - BOOST_COPYABLE_AND_MOVABLE(shared_ptr) - public: - - //!Constructs an empty shared_ptr. - //!Use_count() == 0 && get()== 0. - shared_ptr() - : m_pn() // never throws - {} - - //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated - //!with a copy of a and the object will be deleted with a copy of d. - //!Requirements: Deleter and A's copy constructor must not throw. - explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) - : m_pn(p, a, d) - { - //Check that the pointer passed is of the same type that - //the pointer the allocator defines or it's a raw pointer - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type ParameterPointer; - - BOOST_STATIC_ASSERT((ipcdetail::is_same::value) || - (ipcdetail::is_pointer::value)); - ipcdetail::sp_enable_shared_from_this( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) ); - } - - //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs - //!a shared_ptr that shares ownership with r. Never throws. - shared_ptr(const shared_ptr &r) - : m_pn(r.m_pn) // never throws - {} - - //!Constructs a shared_ptr that shares ownership with other and stores p. - //!Postconditions: get() == p && use_count() == r.use_count(). - //!Throws: nothing. - shared_ptr(const shared_ptr &other, const pointer &p) - : m_pn(other.m_pn, p) - {} - - //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs - //!a shared_ptr that shares ownership with r. Never throws. - template - shared_ptr(shared_ptr const & r) - : m_pn(r.m_pn) // never throws - {} - - //!Constructs a shared_ptr that shares ownership with r and stores - //!a copy of the pointer stored in r. - template - explicit shared_ptr(weak_ptr const & r) - : m_pn(r.m_pn) // may throw - {} - - //!Move-Constructs a shared_ptr that takes ownership of other resource and - //!other is put in default-constructed state. - //!Throws: nothing. - explicit shared_ptr(BOOST_RV_REF(shared_ptr) other) - : m_pn() - { this->swap(other); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - template - shared_ptr(shared_ptr const & r, ipcdetail::static_cast_tag) - : m_pn( pointer(static_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) - , r.m_pn) - {} - - template - shared_ptr(shared_ptr const & r, ipcdetail::const_cast_tag) - : m_pn( pointer(const_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) - , r.m_pn) - {} - - template - shared_ptr(shared_ptr const & r, ipcdetail::dynamic_cast_tag) - : m_pn( pointer(dynamic_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer()))) - , r.m_pn) - { - if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed - m_pn = ipcdetail::shared_count(); - } - } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Equivalent to shared_ptr(r).swap(*this). - //!Never throws - template - shared_ptr & operator=(shared_ptr const & r) - { - m_pn = r.m_pn; // shared_count::op= doesn't throw - return *this; - } - - //!Equivalent to shared_ptr(r).swap(*this). - //!Never throws - shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r) - { - m_pn = r.m_pn; // shared_count::op= doesn't throw - return *this; - } - - //!Move-assignment. Equivalent to shared_ptr(other).swap(*this). - //!Never throws - shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws - { - this_type(other).swap(*this); - return *this; - } - - //!This is equivalent to: - //!this_type().swap(*this); - void reset() - { - this_type().swap(*this); - } - - //!This is equivalent to: - //!this_type(p, a, d).swap(*this); - template - void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) - { - //Check that the pointer passed is of the same type that - //the pointer the allocator defines or it's a raw pointer - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type ParameterPointer; - BOOST_STATIC_ASSERT((ipcdetail::is_same::value) || - (ipcdetail::is_pointer::value)); - this_type(p, a, d).swap(*this); - } - - template - void reset(shared_ptr const & r, const pointer &p) - { - this_type(r, p).swap(*this); - } - - //!Returns a reference to the - //!pointed type - reference operator* () const // never throws - { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); } - - //!Returns the pointer pointing - //!to the owned object - pointer operator-> () const // never throws - { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); } - - //!Returns the pointer pointing - //!to the owned object - pointer get() const // never throws - { return m_pn.to_raw_pointer(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - // implicit conversion to "bool" - void unspecified_bool_type_func() const {} - typedef void (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - //!Not operator. - //!Returns true if this->get() != 0, false otherwise - bool operator! () const // never throws - { return !m_pn.to_raw_pointer(); } - - //!Returns use_count() == 1. - //!unique() might be faster than use_count() - bool unique() const // never throws - { return m_pn.unique(); } - - //!Returns the number of shared_ptr objects, *this included, - //!that share ownership with *this, or an unspecified nonnegative - //!value when *this is empty. - //!use_count() is not necessarily efficient. Use only for - //!debugging and testing purposes, not for production code. - long use_count() const // never throws - { return m_pn.use_count(); } - - //!Exchanges the contents of the two - //!smart pointers. - void swap(shared_ptr & other) // never throws - { m_pn.swap(other.m_pn); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - template - bool _internal_less(shared_ptr const & rhs) const - { return m_pn < rhs.m_pn; } - - const_deleter_pointer get_deleter() const - { return m_pn.get_deleter(); } - -// const_allocator_pointer get_allocator() const -// { return m_pn.get_allocator(); } - - private: - - template friend class shared_ptr; - template friend class weak_ptr; - - ipcdetail::shared_count m_pn; // reference counter - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; // shared_ptr - -template inline -bool operator==(shared_ptr const & a, shared_ptr const & b) -{ return a.get() == b.get(); } - -template inline -bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ return a.get() != b.get(); } - -template inline -bool operator<(shared_ptr const & a, shared_ptr const & b) -{ return a._internal_less(b); } - -template inline -void swap(shared_ptr & a, shared_ptr & b) -{ a.swap(b); } - -template inline -shared_ptr static_pointer_cast(shared_ptr const & r) -{ return shared_ptr(r, ipcdetail::static_cast_tag()); } - -template inline -shared_ptr const_pointer_cast(shared_ptr const & r) -{ return shared_ptr(r, ipcdetail::const_cast_tag()); } - -template inline -shared_ptr dynamic_pointer_cast(shared_ptr const & r) -{ return shared_ptr(r, ipcdetail::dynamic_cast_tag()); } - -// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr -template inline -T * to_raw_pointer(shared_ptr const & p) -{ return p.get(); } - -// operator<< -template inline -std::basic_ostream & operator<< - (std::basic_ostream & os, shared_ptr const & p) -{ os << p.get(); return os; } - -//!Returns the type of a shared pointer -//!of type T with the allocator boost::interprocess::allocator allocator -//!and boost::interprocess::deleter deleter -//!that can be constructed in the given managed segment type. -template -struct managed_shared_ptr -{ - typedef typename ManagedMemory::template allocator::type void_allocator; - typedef typename ManagedMemory::template deleter::type deleter; - typedef shared_ptr< T, void_allocator, deleter> type; -}; - -//!Returns an instance of a shared pointer constructed -//!with the default allocator and deleter from a pointer -//!of type T that has been allocated in the passed managed segment -template -inline typename managed_shared_ptr::type - make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory) -{ - return typename managed_shared_ptr::type - ( constructed_object - , managed_memory.template get_allocator() - , managed_memory.template get_deleter() - ); -} - -//!Returns an instance of a shared pointer constructed -//!with the default allocator and deleter from a pointer -//!of type T that has been allocated in the passed managed segment. -//!Does not throw, return null shared pointer in error. -template -inline typename managed_shared_ptr::type - make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &) -{ - BOOST_TRY{ - return typename managed_shared_ptr::type - ( constructed_object - , managed_memory.template get_allocator() - , managed_memory.template get_deleter() - ); - } - BOOST_CATCH(...){ - return typename managed_shared_ptr::type(); - } BOOST_CATCH_END -} - - -} // namespace interprocess - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#if defined(_MSC_VER) && (_MSC_VER < 1400) -// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr -template inline -T * to_raw_pointer(boost::interprocess::shared_ptr const & p) -{ return p.get(); } -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp deleted file mode 100644 index 919b91d71b7..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/unique_ptr.hpp +++ /dev/null @@ -1,63 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2006-2014. 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_UNIQUE_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -//!\file -//!This header provides utilities to define a unique_ptr that plays nicely with managed segments. - -namespace boost{ -namespace interprocess{ - -//For backwards compatibility -using ::boost::movelib::unique_ptr; - -//!Returns the type of a unique pointer -//!of type T with boost::interprocess::deleter deleter -//!that can be constructed in the given managed segment type. -template -struct managed_unique_ptr -{ - typedef boost::movelib::unique_ptr - < T - , typename ManagedMemory::template deleter::type - > type; -}; - -//!Returns an instance of a unique pointer constructed -//!with boost::interproces::deleter from a pointer -//!of type T that has been allocated in the passed managed segment -template -inline typename managed_unique_ptr::type - make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) -{ - return typename managed_unique_ptr::type - (constructed_object, managed_memory.template get_deleter()); -} - -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp b/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp deleted file mode 100644 index e4873122d8e..00000000000 --- a/extern/boost/boost/interprocess/smart_ptr/weak_ptr.hpp +++ /dev/null @@ -1,271 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// This file is the adaptation for Interprocess of boost/weak_ptr.hpp -// -// (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-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_WEAK_PTR_HPP_INCLUDED -#define BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes the smart pointer weak_ptr. - -namespace boost{ -namespace interprocess{ - -//!The weak_ptr class template stores a "weak reference" to an object -//!that's already managed by a shared_ptr. To access the object, a weak_ptr -//!can be converted to a shared_ptr using the shared_ptr constructor or the -//!member function lock. When the last shared_ptr to the object goes away -//!and the object is deleted, the attempt to obtain a shared_ptr from the -//!weak_ptr instances that refer to the deleted object will fail: the constructor -//!will throw an exception of type bad_weak_ptr, and weak_ptr::lock will -//!return an empty shared_ptr. -//! -//!Every weak_ptr meets the CopyConstructible and Assignable requirements -//!of the C++ Standard Library, and so can be used in standard library containers. -//!Comparison operators are supplied so that weak_ptr works with the standard -//!library's associative containers. -//! -//!weak_ptr operations never throw exceptions. -//! -//!The class template is parameterized on T, the type of the object pointed to. -template -class weak_ptr -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - // Borland 5.5.1 specific workarounds - typedef weak_ptr this_type; - typedef typename boost::container:: - allocator_traits::pointer alloc_ptr; - typedef typename boost::intrusive:: - pointer_traits::template - rebind_pointer::type pointer; - typedef typename ipcdetail::add_reference - ::type reference; - typedef typename ipcdetail::add_reference - ::type const_reference; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - typedef T element_type; - typedef T value_type; - - //!Effects: Constructs an empty weak_ptr. - //!Postconditions: use_count() == 0. - weak_ptr() - : m_pn() // never throws - {} - // generated copy constructor, assignment, destructor are fine - // - // The "obvious" converting constructor implementation: - // - // template - // weak_ptr(weak_ptr const & r): m_px(r.m_px), m_pn(r.m_pn) // never throws - // { - // } - // - // has a serious problem. - // - // r.m_px may already have been invalidated. The m_px(r.m_px) - // conversion may require access to *r.m_px (virtual inheritance). - // - // It is not possible to avoid spurious access violations since - // in multithreaded programs r.m_px may be invalidated at any point. - - //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, - //!constructs a weak_ptr that shares ownership with r as if by storing a - //!copy of the pointer stored in r. - //! - //!Postconditions: use_count() == r.use_count(). - //! - //!Throws: nothing. - template - weak_ptr(weak_ptr const & r) - : m_pn(r.m_pn) // never throws - { - //Construct a temporary shared_ptr so that nobody - //can destroy the value while constructing this - const shared_ptr &ref = r.lock(); - m_pn.set_pointer(ref.get()); - } - - //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, - //!constructs a weak_ptr that shares ownership with r as if by storing a - //!copy of the pointer stored in r. - //! - //!Postconditions: use_count() == r.use_count(). - //! - //!Throws: nothing. - template - weak_ptr(shared_ptr const & r) - : m_pn(r.m_pn) // never throws - {} - - //!Effects: Equivalent to weak_ptr(r).swap(*this). - //! - //!Throws: nothing. - //! - //!Notes: The implementation is free to meet the effects (and the - //!implied guarantees) via different means, without creating a temporary. - template - weak_ptr & operator=(weak_ptr const & r) // never throws - { - //Construct a temporary shared_ptr so that nobody - //can destroy the value while constructing this - const shared_ptr &ref = r.lock(); - m_pn = r.m_pn; - m_pn.set_pointer(ref.get()); - return *this; - } - - //!Effects: Equivalent to weak_ptr(r).swap(*this). - //! - //!Throws: nothing. - //! - //!Notes: The implementation is free to meet the effects (and the - //!implied guarantees) via different means, without creating a temporary. - template - weak_ptr & operator=(shared_ptr const & r) // never throws - { m_pn = r.m_pn; return *this; } - - //!Returns: expired()? shared_ptr(): shared_ptr(*this). - //! - //!Throws: nothing. - shared_ptr lock() const // never throws - { - // optimization: avoid throw overhead - if(expired()){ - return shared_ptr(); - } - BOOST_TRY{ - return shared_ptr(*this); - } - BOOST_CATCH(bad_weak_ptr const &){ - // Q: how can we get here? - // A: another thread may have invalidated r after the use_count test above. - return shared_ptr(); - } - BOOST_CATCH_END - } - - //!Returns: 0 if *this is empty; otherwise, the number of shared_ptr objects - //!that share ownership with *this. - //! - //!Throws: nothing. - //! - //!Notes: use_count() is not necessarily efficient. Use only for debugging and - //!testing purposes, not for production code. - long use_count() const // never throws - { return m_pn.use_count(); } - - //!Returns: Returns: use_count() == 0. - //! - //!Throws: nothing. - //! - //!Notes: expired() may be faster than use_count(). - bool expired() const // never throws - { return m_pn.use_count() == 0; } - - //!Effects: Equivalent to: - //!weak_ptr().swap(*this). - void reset() // never throws in 1.30+ - { this_type().swap(*this); } - - //!Effects: Exchanges the contents of the two - //!smart pointers. - //! - //!Throws: nothing. - void swap(this_type & other) // never throws - { ::boost::adl_move_swap(m_pn, other.m_pn); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - template - bool _internal_less(weak_ptr const & rhs) const - { return m_pn < rhs.m_pn; } - - template - void _internal_assign(const ipcdetail::shared_count & pn2) - { - - m_pn = pn2; - } - - private: - - template friend class shared_ptr; - template friend class weak_ptr; - - ipcdetail::weak_count m_pn; // reference counter - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; // weak_ptr - -template inline -bool operator<(weak_ptr const & a, weak_ptr const & b) -{ return a._internal_less(b); } - -template inline -void swap(weak_ptr & a, weak_ptr & b) -{ a.swap(b); } - -//!Returns the type of a weak pointer -//!of type T with the allocator boost::interprocess::allocator allocator -//!and boost::interprocess::deleter deleter -//!that can be constructed in the given managed segment type. -template -struct managed_weak_ptr -{ - typedef weak_ptr - < T - , typename ManagedMemory::template allocator::type - , typename ManagedMemory::template deleter::type - > type; -}; - -//!Returns an instance of a weak pointer constructed -//!with the default allocator and deleter from a pointer -//!of type T that has been allocated in the passed managed segment -template -inline typename managed_weak_ptr::type - make_managed_weak_ptr(T *constructed_object, ManagedMemory &managed_memory) -{ - return typename managed_weak_ptr::type - ( constructed_object - , managed_memory.template get_allocator() - , managed_memory.template get_deleter() - ); -} - -} // namespace interprocess -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED diff --git a/extern/boost/boost/interprocess/streams/vectorstream.hpp b/extern/boost/boost/interprocess/streams/vectorstream.hpp deleted file mode 100644 index e4845a01e05..00000000000 --- a/extern/boost/boost/interprocess/streams/vectorstream.hpp +++ /dev/null @@ -1,633 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. -// Changed internal SGI string to a generic, templatized vector. Added efficient -// internal buffer get/set/swap functions, so that we can obtain/establish the -// internal buffer without any reallocation or copy. Kill those temporaries! -/////////////////////////////////////////////////////////////////////////////// -/* - * Copyright (c) 1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -//!\file -//!This file defines basic_vectorbuf, basic_ivectorstream, -//!basic_ovectorstream, and basic_vectorstreamclasses. These classes -//!represent streamsbufs and streams whose sources or destinations are -//!STL-like vectors that can be swapped with external vectors to avoid -//!unnecessary allocations/copies. - -#ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP -#define BOOST_INTERPROCESS_VECTORSTREAM_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include // char traits -#include // INT_MAX -#include // ptrdiff_t -#include -#include - -namespace boost { namespace interprocess { - -//!A streambuf class that controls the transmission of elements to and from -//!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. -//!It holds a character vector specified by CharVector template parameter -//!as its formatting buffer. The vector must have contiguous storage, like -//!std::vector, boost::interprocess::vector or boost::interprocess::basic_string -template -class basic_vectorbuf - : public std::basic_streambuf -{ - public: - typedef CharVector vector_type; - typedef typename CharVector::value_type char_type; - typedef typename CharTraits::int_type int_type; - typedef typename CharTraits::pos_type pos_type; - typedef typename CharTraits::off_type off_type; - typedef CharTraits traits_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef std::basic_streambuf base_t; - - basic_vectorbuf(const basic_vectorbuf&); - basic_vectorbuf & operator =(const basic_vectorbuf&); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Throws if vector_type default - //!constructor throws. - explicit basic_vectorbuf(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out) - : base_t(), m_mode(mode) - { this->initialize_pointers(); } - - //!Constructor. Throws if - //!vector_type(const VectorParameter ¶m) throws. - template - explicit basic_vectorbuf(const VectorParameter ¶m, - std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out) - : base_t(), m_mode(mode), m_vect(param) - { this->initialize_pointers(); } - - public: - - //!Swaps the underlying vector with the passed vector. - //!This function resets the read/write position in the stream. - //!Does not throw. - void swap_vector(vector_type &vect) - { - if (this->m_mode & std::ios_base::out){ - //Update high water if necessary - //And resize vector to remove extra size - if (mp_high_water < base_t::pptr()){ - //Restore the vector's size if necessary - mp_high_water = base_t::pptr(); - } - //This does not reallocate - m_vect.resize(std::size_t(mp_high_water - (m_vect.size() ? &m_vect[0] : 0))); - } - //Now swap vector - m_vect.swap(vect); - this->initialize_pointers(); - } - - //!Returns a const reference to the internal vector. - //!Does not throw. - const vector_type &vector() const - { - if (this->m_mode & std::ios_base::out){ - if (mp_high_water < base_t::pptr()){ - //Restore the vector's size if necessary - mp_high_water = base_t::pptr(); - } - //This shouldn't reallocate - typedef typename vector_type::size_type size_type; - char_type *old_ptr = base_t::pbase(); - size_type high_pos = size_type(mp_high_water-old_ptr); - if(m_vect.size() > high_pos){ - m_vect.resize(high_pos); - //But we must update end write pointer because vector size is now shorter - off_type old_pos = base_t::pptr() - base_t::pbase(); - const_cast(this)->base_t::setp(old_ptr, old_ptr + high_pos); - const_cast(this)->pbump(old_pos); - } - } - return m_vect; - } - - //!Preallocates memory from the internal vector. - //!Resets the stream to the first position. - //!Throws if the internals vector's memory allocation throws. - void reserve(typename vector_type::size_type size) - { - if (this->m_mode & std::ios_base::out && size > m_vect.size()){ - off_type write_pos = base_t::pptr() - base_t::pbase(); - off_type read_pos = base_t::gptr() - base_t::eback(); - //Now update pointer data - m_vect.reserve(size); - this->initialize_pointers(); - this->pbump(write_pos); - if(this->m_mode & std::ios_base::in){ - base_t::setg(base_t::eback(), base_t::eback() + read_pos, base_t::egptr()); - } - } - } - - //!Calls clear() method of the internal vector. - //!Resets the stream to the first position. - void clear() - { m_vect.clear(); this->initialize_pointers(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - //Maximizes high watermark to the initial vector size, - //initializes read and write iostream buffers to the capacity - //and resets stream positions - void initialize_pointers() - { - // The initial read position is the beginning of the vector. - if(!(m_mode & std::ios_base::out)){ - if(m_vect.empty()){ - this->setg(0, 0, 0); - } - else{ - this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size()); - } - } - - // The initial write position is the beginning of the vector. - if(m_mode & std::ios_base::out){ - //First get real size - off_type real_size = m_vect.size(); - //Then maximize size for high watermarking - m_vect.resize(m_vect.capacity()); - BOOST_ASSERT(m_vect.size() == m_vect.capacity()); - //Set high watermarking with the expanded size - mp_high_water = m_vect.size() ? (&m_vect[0] + real_size) : 0; - //Now set formatting pointers - if(m_vect.empty()){ - this->setp(0, 0); - if(m_mode & std::ios_base::in) - this->setg(0, 0, 0); - } - else{ - char_type *p = &m_vect[0]; - this->setp(p, p + m_vect.size()); - if(m_mode & std::ios_base::in) - this->setg(p, p, p + real_size); - } - if (m_mode & (std::ios_base::app | std::ios_base::ate)){ - this->pbump(real_size); - } - } - } - - // LWG255-inspired variant of base_t::pbump that takes a streamoff instead of an int. - void pbump(off_type delta) { - if (delta > INT_MAX) { - for (off_type d = delta / INT_MAX; d > 0; d--) - base_t::pbump(INT_MAX); - delta %= INT_MAX; - } - base_t::pbump((int)delta); - } - - protected: - virtual int_type underflow() BOOST_OVERRIDE - { - if (base_t::gptr() == 0) - return CharTraits::eof(); - if(m_mode & std::ios_base::out){ - if (mp_high_water < base_t::pptr()) - mp_high_water = base_t::pptr(); - if (base_t::egptr() < mp_high_water) - base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); - } - if (base_t::gptr() < base_t::egptr()) - return CharTraits::to_int_type(*base_t::gptr()); - return 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())) { - if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { - this->gbump(-1); - return c; - } - else if(m_mode & std::ios_base::out) { - this->gbump(-1); - *this->gptr() = CharTraits::to_char_type(c); - return c; - } - else - return CharTraits::eof(); - } - else { - this->gbump(-1); - return CharTraits::not_eof(c); - } - } - else - return 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())) { - typedef typename vector_type::difference_type dif_t; - //The new output position is the previous one plus one - //because 'overflow' requires putting 'c' on the buffer - dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1; - //Adjust high water if necessary - dif_t hipos = mp_high_water - base_t::pbase(); - if (hipos < new_outpos) - hipos = new_outpos; - //Insert the new data - m_vect.push_back(CharTraits::to_char_type(c)); - m_vect.resize(m_vect.capacity()); - BOOST_ASSERT(m_vect.size() == m_vect.capacity()); - char_type* p = const_cast(&m_vect[0]); - //A reallocation might have happened, update pointers - base_t::setp(p, p + (dif_t)m_vect.size()); - mp_high_water = p + hipos; - if (m_mode & std::ios_base::in) - base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water); - //Update write position to the old position + 1 - this->pbump((off_type)new_outpos); - return c; - } - else // c is EOF, so we don't have to do anything - return CharTraits::not_eof(c); - } - else // Overflow always fails if it's read-only. - return CharTraits::eof(); - } - - 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) BOOST_OVERRIDE - { - //Get seek mode - bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out)); - //Test for logic errors - if(!in & !out) - return pos_type(off_type(-1)); - else if((in && out) && (dir == std::ios_base::cur)) - return pos_type(off_type(-1)); - else if((in && (!(m_mode & std::ios_base::in) || (off != 0 && this->gptr() == 0) )) || - (out && (!(m_mode & std::ios_base::out) || (off != 0 && this->pptr() == 0)))) - return pos_type(off_type(-1)); - - off_type newoff; - //Just calculate the end of the stream. If the stream is read-only - //the limit is the size of the vector. Otherwise, the high water mark - //will mark the real size. - off_type limit; - if(m_mode & std::ios_base::out){ - //Update high water marking because pptr() is going to change and it might - //have been updated since last overflow() - if(mp_high_water < base_t::pptr()) - mp_high_water = base_t::pptr(); - //Update read limits in case high water mark was changed - if(m_mode & std::ios_base::in){ - if (base_t::egptr() < mp_high_water) - base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); - } - limit = static_cast(mp_high_water - base_t::pbase()); - } - else{ - limit = static_cast(m_vect.size()); - } - - switch(dir) { - case std::ios_base::beg: - newoff = 0; - break; - case std::ios_base::end: - newoff = limit; - break; - case std::ios_base::cur: - newoff = in ? static_cast(this->gptr() - this->eback()) - : static_cast(this->pptr() - this->pbase()); - break; - default: - return pos_type(off_type(-1)); - } - - newoff += off; - - if (newoff < 0 || newoff > limit) - return pos_type(-1); - if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit) - return pos_type(-1); - //This can reassign pointers - //if(m_vect.size() != m_vect.capacity()) - //this->initialize_pointers(); - if (in) - base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr()); - if (out){ - base_t::setp(base_t::pbase(), base_t::epptr()); - this->pbump(newoff); - } - return pos_type(newoff); - } - - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE - { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } - - private: - std::ios_base::openmode m_mode; - mutable vector_type m_vect; - mutable char_type* mp_high_water; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -//!A basic_istream class that holds a character vector specified by CharVector -//!template parameter as its formatting buffer. The vector must have -//!contiguous storage, like std::vector, boost::interprocess::vector or -//!boost::interprocess::basic_string -template -class basic_ivectorstream - : public std::basic_istream - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - , private basic_vectorbuf - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - public: - typedef CharVector vector_type; - typedef typename std::basic_ios - ::char_type char_type; - typedef typename std::basic_ios::int_type int_type; - typedef typename std::basic_ios::pos_type pos_type; - typedef typename std::basic_ios::off_type off_type; - typedef typename std::basic_ios::traits_type traits_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef basic_vectorbuf vectorbuf_t; - typedef std::basic_ios basic_ios_t; - typedef std::basic_istream base_t; - - vectorbuf_t & get_buf() { return *this; } - const vectorbuf_t & get_buf() const{ return *this; } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - - //!Constructor. Throws if vector_type default - //!constructor throws. - basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) - : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base - //(via basic_ios::init() call in base_t's constructor) without the risk of a - //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. - , vectorbuf_t(mode | std::ios_base::in) - { this->base_t::rdbuf(&get_buf()); } - - //!Constructor. Throws if vector_type(const VectorParameter ¶m) - //!throws. - template - basic_ivectorstream(const VectorParameter ¶m, - std::ios_base::openmode mode = std::ios_base::in) - : vectorbuf_t(param, mode | std::ios_base::in) - //basic_ios_t() is constructed uninitialized as virtual base - //and initialized inside base_t calling basic_ios::init() - , base_t(&get_buf()) - {} - - public: - //!Returns the address of the stored - //!stream buffer. - basic_vectorbuf* rdbuf() const - { return const_cast*>(&get_buf()); } - - //!Swaps the underlying vector with the passed vector. - //!This function resets the read position in the stream. - //!Does not throw. - void swap_vector(vector_type &vect) - { get_buf().swap_vector(vect); } - - //!Returns a const reference to the internal vector. - //!Does not throw. - const vector_type &vector() const - { return get_buf().vector(); } - - //!Calls reserve() method of the internal vector. - //!Resets the stream to the first position. - //!Throws if the internals vector's reserve throws. - void reserve(typename vector_type::size_type size) - { get_buf().reserve(size); } - - //!Calls clear() method of the internal vector. - //!Resets the stream to the first position. - void clear() - { get_buf().clear(); } -}; - -//!A basic_ostream class that holds a character vector specified by CharVector -//!template parameter as its formatting buffer. The vector must have -//!contiguous storage, like std::vector, boost::interprocess::vector or -//!boost::interprocess::basic_string -template -class basic_ovectorstream - : public std::basic_ostream - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - , private basic_vectorbuf - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - public: - typedef CharVector vector_type; - typedef typename std::basic_ios - ::char_type char_type; - typedef typename std::basic_ios::int_type int_type; - typedef typename std::basic_ios::pos_type pos_type; - typedef typename std::basic_ios::off_type off_type; - typedef typename std::basic_ios::traits_type traits_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef basic_vectorbuf vectorbuf_t; - typedef std::basic_ios basic_ios_t; - typedef std::basic_ostream base_t; - - vectorbuf_t & get_buf() { return *this; } - const vectorbuf_t & get_buf()const { return *this; } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Throws if vector_type default - //!constructor throws. - basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) - : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base - //(via basic_ios::init() call in base_t's constructor) without the risk of a - //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. - , vectorbuf_t(mode | std::ios_base::out) - { this->base_t::rdbuf(&get_buf()); } - - //!Constructor. Throws if vector_type(const VectorParameter ¶m) - //!throws. - template - basic_ovectorstream(const VectorParameter ¶m, - std::ios_base::openmode mode = std::ios_base::out) - : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base - //(via basic_ios::init() call in base_t's constructor) without the risk of a - //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. - , vectorbuf_t(param, mode | std::ios_base::out) - { this->base_t::rdbuf(&get_buf()); } - - public: - //!Returns the address of the stored - //!stream buffer. - basic_vectorbuf* rdbuf() const - { return const_cast*>(&get_buf()); } - - //!Swaps the underlying vector with the passed vector. - //!This function resets the write position in the stream. - //!Does not throw. - void swap_vector(vector_type &vect) - { get_buf().swap_vector(vect); } - - //!Returns a const reference to the internal vector. - //!Does not throw. - const vector_type &vector() const - { return get_buf().vector(); } - - //!Calls reserve() method of the internal vector. - //!Resets the stream to the first position. - //!Throws if the internals vector's reserve throws. - void reserve(typename vector_type::size_type size) - { get_buf().reserve(size); } -}; - -//!A basic_iostream class that holds a character vector specified by CharVector -//!template parameter as its formatting buffer. The vector must have -//!contiguous storage, like std::vector, boost::interprocess::vector or -//!boost::interprocess::basic_string -template -class basic_vectorstream - : public std::basic_iostream - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - , private basic_vectorbuf - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -{ - public: - typedef CharVector vector_type; - typedef typename std::basic_ios - ::char_type char_type; - typedef typename std::basic_ios::int_type int_type; - typedef typename std::basic_ios::pos_type pos_type; - typedef typename std::basic_ios::off_type off_type; - typedef typename std::basic_ios::traits_type traits_type; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef basic_vectorbuf vectorbuf_t; - typedef std::basic_ios basic_ios_t; - typedef std::basic_iostream base_t; - - vectorbuf_t & get_buf() { return *this; } - const vectorbuf_t & get_buf() const{ return *this; } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructor. Throws if vector_type default - //!constructor throws. - basic_vectorstream(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out) - : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base - //(via basic_ios::init() call in base_t's constructor) without the risk of a - //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. - , vectorbuf_t(mode) - { this->base_t::rdbuf(&get_buf()); } - - //!Constructor. Throws if vector_type(const VectorParameter ¶m) - //!throws. - template - basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out) - : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base - //(via basic_ios::init() call in base_t's constructor) without the risk of a - //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. - , vectorbuf_t(param, mode) - { this->base_t::rdbuf(&get_buf()); } - - public: - //Returns the address of the stored stream buffer. - basic_vectorbuf* rdbuf() const - { return const_cast*>(&get_buf()); } - - //!Swaps the underlying vector with the passed vector. - //!This function resets the read/write position in the stream. - //!Does not throw. - void swap_vector(vector_type &vect) - { get_buf().swap_vector(vect); } - - //!Returns a const reference to the internal vector. - //!Does not throw. - const vector_type &vector() const - { return get_buf().vector(); } - - //!Calls reserve() method of the internal vector. - //!Resets the stream to the first position. - //!Throws if the internals vector's reserve throws. - void reserve(typename vector_type::size_type size) - { get_buf().reserve(size); } - - //!Calls clear() method of the internal vector. - //!Resets the stream to the first position. - void clear() - { get_buf().clear(); } -}; - -//Some typedefs to simplify usage -//! -//!typedef basic_vectorbuf > vectorbuf; -//!typedef basic_vectorstream > vectorstream; -//!typedef basic_ivectorstream > ivectorstream; -//!typedef basic_ovectorstream > ovectorstream; -//! -//!typedef basic_vectorbuf > wvectorbuf; -//!typedef basic_vectorstream > wvectorstream; -//!typedef basic_ivectorstream > wivectorstream; -//!typedef basic_ovectorstream > wovectorstream; - -}} //namespace boost { namespace interprocess { - -#include - -#endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */ diff --git a/extern/boost/boost/interprocess/sync/cv_status.hpp b/extern/boost/boost/interprocess/sync/cv_status.hpp deleted file mode 100644 index afbcdf6fd75..00000000000 --- a/extern/boost/boost/interprocess/sync/cv_status.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// 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 - -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/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp deleted file mode 100644 index a4cce7ba7ec..00000000000 --- a/extern/boost/boost/interprocess/sync/detail/condition_algorithm_8a.hpp +++ /dev/null @@ -1,389 +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_CONDITION_ALGORITHM_8A_HPP -#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -// -// Condition variable algorithm taken from pthreads-win32 discussion. -// -// The algorithm was developed by Alexander Terekhov in colaboration with -// Louis Thomas. -// -// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL -// -// semBlockLock - bin.semaphore -// semBlockQueue - semaphore -// mtxExternal - mutex or CS -// mtxUnblockLock - mutex or CS -// nWaitersGone - int -// nWaitersBlocked - int -// nWaitersToUnblock - int -// -// wait( timeout ) { -// -// [auto: register int result ] // error checking omitted -// [auto: register int nSignalsWasLeft ] -// [auto: register int nWaitersWasGone ] -// -// sem_wait( semBlockLock ); -// nWaitersBlocked++; -// sem_post( semBlockLock ); -// -// unlock( mtxExternal ); -// bTimedOut = sem_wait( semBlockQueue,timeout ); -// -// lock( mtxUnblockLock ); -// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { -// if ( bTimedOut ) { // timeout (or canceled) -// if ( 0 != nWaitersBlocked ) { -// nWaitersBlocked--; -// } -// else { -// nWaitersGone++; // count spurious wakeups. -// } -// } -// if ( 0 == --nWaitersToUnblock ) { -// if ( 0 != nWaitersBlocked ) { -// sem_post( semBlockLock ); // open the gate. -// nSignalsWasLeft = 0; // do not open the gate -// // below again. -// } -// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { -// nWaitersGone = 0; -// } -// } -// } -// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or -// // spurious semaphore :-) -// sem_wait( semBlockLock ); -// nWaitersBlocked -= nWaitersGone; // something is going on here -// // - test of timeouts? :-) -// sem_post( semBlockLock ); -// nWaitersGone = 0; -// } -// unlock( mtxUnblockLock ); -// -// if ( 1 == nSignalsWasLeft ) { -// if ( 0 != nWaitersWasGone ) { -// // sem_adjust( semBlockQueue,-nWaitersWasGone ); -// while ( nWaitersWasGone-- ) { -// sem_wait( semBlockQueue ); // better now than spurious later -// } -// } sem_post( semBlockLock ); // open the gate -// } -// -// lock( mtxExternal ); -// -// return ( bTimedOut ) ? ETIMEOUT : 0; -// } -// -// signal(bAll) { -// -// [auto: register int result ] -// [auto: register int nSignalsToIssue] -// -// lock( mtxUnblockLock ); -// -// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! -// if ( 0 == nWaitersBlocked ) { // NO-OP -// return unlock( mtxUnblockLock ); -// } -// if (bAll) { -// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; -// nWaitersBlocked = 0; -// } -// else { -// nSignalsToIssue = 1; -// nWaitersToUnblock++; -// nWaitersBlocked--; -// } -// } -// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! -// sem_wait( semBlockLock ); // close the gate -// if ( 0 != nWaitersGone ) { -// nWaitersBlocked -= nWaitersGone; -// nWaitersGone = 0; -// } -// if (bAll) { -// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; -// nWaitersBlocked = 0; -// } -// else { -// nSignalsToIssue = nWaitersToUnblock = 1; -// nWaitersBlocked--; -// } -// } -// else { // NO-OP -// return unlock( mtxUnblockLock ); -// } -// -// unlock( mtxUnblockLock ); -// sem_post( semBlockQueue,nSignalsToIssue ); -// return result; -// } -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - - -// Required interface for ConditionMembers -// class ConditionMembers -// { -// typedef implementation_defined semaphore_type; -// typedef implementation_defined mutex_type; -// typedef implementation_defined integer_type; -// -// integer_type &get_nwaiters_blocked() -// integer_type &get_nwaiters_gone() -// integer_type &get_nwaiters_to_unblock() -// semaphore_type &get_sem_block_queue() -// semaphore_type &get_sem_block_lock() -// mutex_type &get_mtx_unblock_lock() -// }; -// -// Must be initialized as following -// -// get_nwaiters_blocked() == 0 -// get_nwaiters_gone() == 0 -// get_nwaiters_to_unblock() == 0 -// get_sem_block_queue() == initial count 0 -// get_sem_block_lock() == initial count 1 -// get_mtx_unblock_lock() (unlocked) -// -template -class condition_algorithm_8a -{ - private: - condition_algorithm_8a(); - ~condition_algorithm_8a(); - condition_algorithm_8a(const condition_algorithm_8a &); - condition_algorithm_8a &operator=(const condition_algorithm_8a &); - - typedef typename ConditionMembers::semaphore_type semaphore_type; - typedef typename ConditionMembers::mutex_type mutex_type; - typedef typename ConditionMembers::integer_type integer_type; - - public: - template - static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &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(); - - //Unlock external lock and program for relock - lock_inverter inverted_lock(lock); - scoped_lock > external_unlock(inverted_lock); - - bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_()); - - { - scoped_lock 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 ( (std::numeric_limits::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 - } - } - data.get_sem_block_lock().post(); // open the gate - } - - //lock.lock(); called from unlocker destructor - - return ( bTimedOut ) ? false : true; - } - - static void signal(ConditionMembers &data, bool broadcast) - { - integer_type nsignals_to_issue; - - { - scoped_lock 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()--; - } - } - 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 { // 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); - } - - private: - template - static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_) - { return sem.timed_wait(abs_time); } - - template - static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_) - { sem.wait(); return true; } -}; - -template -class condition_8a_wrapper -{ - //Non-copyable - condition_8a_wrapper(const condition_8a_wrapper &); - condition_8a_wrapper &operator=(const condition_8a_wrapper &); - - ConditionMembers m_data; - typedef condition_algorithm_8a algo_type; - - public: - - condition_8a_wrapper(){} - - //Compiler-generated destructor is OK - //~condition_8a_wrapper(){} - - ConditionMembers & get_members() - { return m_data; } - - const ConditionMembers & get_members() const - { return m_data; } - - void notify_one() - { algo_type::signal(m_data, false); } - - void notify_all() - { algo_type::signal(m_data, true); } - - template - void wait(L& lock) - { - if (!lock) - throw lock_exception(); - algo_type::template wait(m_data, lock, 0); - } - - template - void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - algo_type::template wait(m_data, lock, 0); - } - - template - bool timed_wait(L& lock, const TimePoint &abs_time) - { - if (!lock) - throw lock_exception(); - return algo_type::template wait(m_data, lock, abs_time); - } - - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!algo_type::template wait(m_data, lock, abs_time)) - return pred(); - } - return true; - } -}; - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP diff --git a/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp b/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp deleted file mode 100644 index 0155d90bc50..00000000000 --- a/extern/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp +++ /dev/null @@ -1,191 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_ALGORITHM_HPP -#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -// -// Condition variable 'any' (able to use any type of external mutex) -// -// The code is based on Howard E. Hinnant's ISO C++ N2406 paper. -// Many thanks to Howard for his support and comments. -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -// Required interface for ConditionAnyMembers -// class ConditionAnyMembers -// { -// typedef implementation_defined mutex_type; -// typedef implementation_defined condvar_type; -// -// condvar &get_condvar() -// mutex_type &get_mutex() -// }; -// -// Must be initialized as following -// -// get_condvar() [no threads blocked] -// get_mutex() [unlocked] - -template -class condition_any_algorithm -{ - private: - condition_any_algorithm(); - ~condition_any_algorithm(); - condition_any_algorithm(const condition_any_algorithm &); - condition_any_algorithm &operator=(const condition_any_algorithm &); - - typedef typename ConditionAnyMembers::mutex_type mutex_type; - typedef typename ConditionAnyMembers::condvar_type condvar_type; - - public: - template - static void wait(ConditionAnyMembers& data, Lock& lock) - { - //lock internal before unlocking external to avoid race with a notifier - scoped_lock internal_lock(data.get_mutex()); - { - lock_inverter inverted_lock(lock); - scoped_lock > external_unlock(inverted_lock); - { //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock internal_unlock; - internal_lock.swap(internal_unlock); - data.get_condvar().wait(internal_unlock); - } - } - } - - template - static bool timed_wait(ConditionAnyMembers &data, Lock& lock, const TimePoint &abs_time) - { - //lock internal before unlocking external to avoid race with a notifier - scoped_lock internal_lock(data.get_mutex()); - { - //Unlock external lock and program for relock - lock_inverter inverted_lock(lock); - scoped_lock > external_unlock(inverted_lock); - { //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock internal_unlock; - internal_lock.swap(internal_unlock); - return data.get_condvar().timed_wait(internal_unlock, abs_time); - } - } - } - - static void signal(ConditionAnyMembers& data, bool broadcast) - { - scoped_lock internal_lock(data.get_mutex()); - if(broadcast){ - data.get_condvar().notify_all(); - } - else{ - data.get_condvar().notify_one(); - } - } -}; - - -template -class condition_any_wrapper -{ - //Non-copyable - condition_any_wrapper(const condition_any_wrapper &); - condition_any_wrapper &operator=(const condition_any_wrapper &); - - ConditionAnyMembers m_data; - typedef ipcdetail::condition_any_algorithm algo_type; - - public: - - condition_any_wrapper(){} - - ~condition_any_wrapper(){} - - ConditionAnyMembers & get_members() - { return m_data; } - - const ConditionAnyMembers & get_members() const - { return m_data; } - - void notify_one() - { algo_type::signal(m_data, false); } - - void notify_all() - { algo_type::signal(m_data, true); } - - template - void wait(Lock& lock) - { - if (!lock) - throw lock_exception(); - algo_type::wait(m_data, lock); - } - - template - void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - algo_type::wait(m_data, lock); - } - - template - bool timed_wait(L& lock, const TimePoint &abs_time) - { - if (!lock) - throw lock_exception(); - return algo_type::timed_wait(m_data, lock, abs_time); - } - - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!algo_type::timed_wait(m_data, lock, abs_time)) - return pred(); - } - return true; - } -}; - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP diff --git a/extern/boost/boost/interprocess/sync/detail/locks.hpp b/extern/boost/boost/interprocess/sync/detail/locks.hpp deleted file mode 100644 index a2beb8917ce..00000000000 --- a/extern/boost/boost/interprocess/sync/detail/locks.hpp +++ /dev/null @@ -1,111 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2012-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_LOCKS_HPP -#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template -class internal_mutex_lock -{ - typedef void (internal_mutex_lock::*unspecified_bool_type)(); - public: - - typedef typename Lock::mutex_type::internal_mutex_type mutex_type; - - - BOOST_INTERPROCESS_FORCEINLINE internal_mutex_lock(Lock &l) - : l_(l) - {} - - BOOST_INTERPROCESS_FORCEINLINE mutex_type* mutex() const - { return l_ ? &l_.mutex()->internal_mutex() : 0; } - - BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock(); } - - BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock(); } - - BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const - { return l_ ? &internal_mutex_lock::lock : 0; } - - private: - Lock &l_; -}; - -template -class lock_inverter -{ - Lock &l_; - public: - BOOST_INTERPROCESS_FORCEINLINE lock_inverter(Lock &l) - : l_(l) - {} - - BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.unlock(); } - - BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.lock(); } -}; - -template -class lock_to_sharable -{ - Lock &l_; - - public: - BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_sharable(Lock &l) - : l_(l) - {} - - 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_to_wait -{ - Lock &l_; - - public: - BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_wait(Lock &l) - : l_(l) - {} - BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.wait(); } - - BOOST_INTERPROCESS_FORCEINLINE bool try_lock() { return l_.try_wait(); } - - template - BOOST_INTERPROCESS_FORCEINLINE bool timed_lock(const TimePoint &abs_time) - { return l_.timed_wait(abs_time); } -}; - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP diff --git a/extern/boost/boost/interprocess/sync/file_lock.hpp b/extern/boost/boost/interprocess/sync/file_lock.hpp deleted file mode 100644 index 34adbd53b11..00000000000 --- a/extern/boost/boost/interprocess/sync/file_lock.hpp +++ /dev/null @@ -1,324 +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_FILE_LOCK_HPP -#define BOOST_INTERPROCESS_FILE_LOCK_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a class that wraps file locking capabilities. - -namespace boost { -namespace interprocess { - - -//!A file lock, is a mutual exclusion utility similar to a mutex using a -//!file. A file lock has sharable and exclusive locking capabilities and -//!can be used with scoped_lock and sharable_lock classes. -//!A file lock can't guarantee synchronization between threads of the same -//!process so just use file locks to synchronize threads from different processes. -class file_lock -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructs an empty file mapping. - //!Does not throw - file_lock() BOOST_NOEXCEPT - : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) - {} - - //!Opens a file lock. Throws interprocess_exception if the file does not - //!exist or there are no operating system resources. - file_lock(const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Opens a file lock. Throws interprocess_exception if the file does not - //!exist or there are no operating system resources. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - file_lock(const wchar_t *name); - #endif - - //!Moves the ownership of "moved"'s file mapping object to *this. - //!After the call, "moved" does not represent any file mapping object. - //!Does not throw - file_lock(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT - : m_file_hnd(file_handle_t(ipcdetail::invalid_file())) - { this->swap(moved); } - - //!Moves the ownership of "moved"'s file mapping to *this. - //!After the call, "moved" does not represent any file mapping. - //!Does not throw - file_lock &operator=(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT - { - file_lock tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Closes a file lock. Does not throw. - ~file_lock(); - - //!Swaps two file_locks. - //!Does not throw. - void swap(file_lock &other) BOOST_NOEXCEPT - { - file_handle_t tmp = m_file_hnd; - m_file_hnd = other.m_file_hnd; - other.m_file_hnd = tmp; - } - - //Exclusive locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive, or sharable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!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 acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive, or sharable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive, or sharable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, waits until - //! it can obtain the ownership. - //!Throws: interprocess_exception on error. - //! - //!Note: A program may deadlock if the thread that owns a mutex object calls - //! this function. If the implementation can detect the deadlock, - //! an exception could be thrown. - void lock_sharable(); - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership of the - //! mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. - //!Throws: interprocess_exception on error. - bool try_lock_sharable(); - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive ownership of - //! the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. - //!Throws: interprocess_exception on error. - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_until(const TimePoint &abs_time) - { return this->timed_lock_sharable(abs_time); } - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_for(const Duration &dur) - { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - file_handle_t m_file_hnd; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline file_lock::file_lock(const char *name) -{ - m_file_hnd = ipcdetail::open_existing_file(name, read_write); - - if(m_file_hnd == ipcdetail::invalid_file()){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline file_lock::file_lock(const wchar_t *name) -{ - m_file_hnd = ipcdetail::open_existing_file(name, read_write); - - if(m_file_hnd == ipcdetail::invalid_file()){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline file_lock::~file_lock() -{ - if(m_file_hnd != ipcdetail::invalid_file()){ - ipcdetail::close_file(m_file_hnd); - m_file_hnd = ipcdetail::invalid_file(); - } -} - -inline void file_lock::lock() -{ - if(!ipcdetail::acquire_file_lock(m_file_hnd)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -inline bool file_lock::try_lock() -{ - bool result; - if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } - return result; -} - -template -inline bool file_lock::timed_lock(const TimePoint &abs_time) -{ return ipcdetail::try_based_timed_lock(*this, abs_time); } - -inline void file_lock::unlock() -{ - if(!ipcdetail::release_file_lock(m_file_hnd)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -inline void file_lock::lock_sharable() -{ - if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -inline bool file_lock::try_lock_sharable() -{ - bool result; - if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } - return result; -} - -template -inline bool file_lock::timed_lock_sharable(const TimePoint &abs_time) -{ - ipcdetail::lock_to_sharable lsh(*this); - return ipcdetail::try_based_timed_lock(lsh, abs_time); -} - -inline void file_lock::unlock_sharable() -{ - if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){ - error_info err(system_error_code()); - throw interprocess_exception(err); - } -} - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_FILE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_condition.hpp b/extern/boost/boost/interprocess/sync/interprocess_condition.hpp deleted file mode 100644 index 7fde9fe2191..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_condition.hpp +++ /dev/null @@ -1,177 +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_CONDITION_HPP -#define BOOST_INTERPROCESS_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) - #include - #define BOOST_INTERPROCESS_CONDITION_USE_POSIX -//Experimental... -#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_CONDITION_USE_WINAPI -#else - //spin_condition is used - #include -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!\file -//!Describes process-shared variables interprocess_condition class - -namespace boost { -namespace interprocess { - -class named_condition; - -//!This class is a condition variable that can be placed in shared memory or -//!memory mapped files. -//!Destroys the object of type std::condition_variable_any -//! -//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all -//!threads have been only notified. It is required that they have exited their respective wait -//!functions. -class interprocess_condition -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - interprocess_condition(const interprocess_condition &); - interprocess_condition &operator=(const interprocess_condition &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Constructs a interprocess_condition. On error throws interprocess_exception. - interprocess_condition() - {} - - //!Destroys *this - //!liberating system resources. - ~interprocess_condition() - {} - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect. - void notify_one() - { m_condition.notify_one(); } - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all() - { m_condition.notify_all(); } - - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock) - { - ipcdetail::internal_mutex_lock internal_lock(lock); - m_condition.wait(internal_lock); - } - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred) - { - ipcdetail::internal_mutex_lock internal_lock(lock); - m_condition.wait(internal_lock, pred); - } - - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time) - { - ipcdetail::internal_mutex_lock internal_lock(lock); - return m_condition.timed_wait(internal_lock, abs_time); - } - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { - ipcdetail::internal_mutex_lock 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 - 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 - 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 - 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 - 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_CONDITION_USE_POSIX) - ipcdetail::posix_condition m_condition; - #elif defined(BOOST_INTERPROCESS_CONDITION_USE_WINAPI) - ipcdetail::winapi_condition m_condition; - #else - ipcdetail::spin_condition m_condition; - #endif - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess -} // namespace boost - -#include - -#endif // BOOST_INTERPROCESS_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp b/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp deleted file mode 100644 index 4a1d84a5ac1..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_condition_any.hpp +++ /dev/null @@ -1,154 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2012-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_CONDITION_ANY_HPP -#define BOOST_INTERPROCESS_CONDITION_ANY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#include -#include - -#include -#include -#include -#include -#include -#include - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!\file -//!Describes process-shared variables interprocess_condition_any class - -namespace boost { -namespace interprocess { - -//!This class is a condition variable that can be placed in shared memory or -//!memory mapped files. -//! -//!The interprocess_condition_any class is a generalization of interprocess_condition. -//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex -//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable -//!requirements (lock()/unlock() member functions). -//! -//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all -//!threads have been only notified. It is required that they have exited their respective wait -//!functions. -class interprocess_condition_any -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - interprocess_condition_any(const interprocess_condition_any &); - interprocess_condition_any &operator=(const interprocess_condition_any &); - - class members - { - public: - typedef interprocess_condition condvar_type; - typedef interprocess_mutex mutex_type; - - condvar_type &get_condvar() { return m_cond; } - mutex_type &get_mutex() { return m_mut; } - - private: - condvar_type m_cond; - mutex_type m_mut; - }; - - ipcdetail::condition_any_wrapper m_cond; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - //!Constructs a interprocess_condition_any. On error throws interprocess_exception. - interprocess_condition_any(){} - - //!Destroys *this - //!liberating system resources. - ~interprocess_condition_any(){} - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect. - void notify_one() - { m_cond.notify_one(); } - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all() - { m_cond.notify_all(); } - - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock) - { m_cond.wait(lock); } - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred) - { m_cond.wait(lock, pred); } - - //!Releases the lock on the interprocess_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time) - { return m_cond.timed_wait(lock, abs_time); } - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { return m_cond.timed_wait(lock, abs_time, pred); } - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - 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 - 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 - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } -}; - -} //namespace interprocess -} // namespace boost - -#include - -#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp deleted file mode 100644 index 3819080e2e4..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_mutex.hpp +++ /dev/null @@ -1,198 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// Parts of the pthread code come from Boost Threads code. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_MUTEX_HPP -#define BOOST_INTERPROCESS_MUTEX_HPP - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) - #include - #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 -#else - //spin_mutex is used - #include - namespace boost { - namespace interprocess { - namespace ipcdetail{ - namespace robust_emulation_helpers { - - template - class mutex_traits; - - }}}} -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!\file -//!Describes a mutex class that can be placed in memory shared by -//!several processes. - -namespace boost { -namespace interprocess { - -class interprocess_condition; - -//!Wraps a interprocess_mutex that can be placed in shared memory and can be -//!shared between processes. Allows timed lock tries -class interprocess_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - interprocess_mutex(const interprocess_mutex &); - interprocess_mutex &operator=(const interprocess_mutex &); - friend class interprocess_condition; - - public: - #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; - void take_ownership(){ m_mutex.take_ownership(); } - public: - #endif - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Constructor. - //!Throws interprocess_exception on error. - interprocess_mutex(); - - //!Destructor. If any process uses the mutex after the destructor is called - //!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 - //! number of times it is locked. - //!Returns: If the thread acquires ownership of the mutex, returns true, if - //! the timeout expires 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. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 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. - void unlock(); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - internal_mutex_type &internal_mutex() - { return m_mutex; } - - const internal_mutex_type &internal_mutex() const - { return m_mutex; } - - private: - internal_mutex_type m_mutex; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess { -} //namespace boost { - - -namespace boost { -namespace interprocess { - -inline interprocess_mutex::interprocess_mutex(){} - -inline interprocess_mutex::~interprocess_mutex(){} - -inline void interprocess_mutex::lock() -{ ipcdetail::timeout_when_locking_aware_lock(m_mutex); } - -inline bool interprocess_mutex::try_lock() -{ return m_mutex.try_lock(); } - -template -inline bool interprocess_mutex::timed_lock(const TimePoint &abs_time) -{ return m_mutex.timed_lock(abs_time); } - -inline void interprocess_mutex::unlock() -{ m_mutex.unlock(); } - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp deleted file mode 100644 index dc5c5a07463..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_recursive_mutex.hpp +++ /dev/null @@ -1,184 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// Parts of the pthread code come from Boost Threads code: -// -////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2003 -// William E. Kempf -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. William E. Kempf makes no representations -// about the suitability of this software for any purpose. -// It is provided "as is" without express or implied warranty. -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \ - defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \ - defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES) - #include - #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX -#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - //Experimental... - #include - #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI -#else - //spin_recursive_mutex is used - #include - namespace boost { - namespace interprocess { - namespace ipcdetail{ - namespace robust_emulation_helpers { - - template - class mutex_traits; - - }}}} -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!\file -//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes - -namespace boost { -namespace interprocess { - -//!Wraps a interprocess_mutex that can be placed in shared memory and can be -//!shared between processes. Allows several locking calls by the same -//!process. Allows timed lock tries -class interprocess_recursive_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - interprocess_recursive_mutex(const interprocess_recursive_mutex &); - interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - //!Constructor. - //!Throws interprocess_exception on error. - interprocess_recursive_mutex(); - - //!Destructor. If any process uses the mutex after the destructor is called - //!the result is undefined. Does not throw. - ~interprocess_recursive_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. The mutex must be unlocked - //! the same number of times it is locked. - //!Throws: interprocess_exception on error. - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - void lock(); - - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex - //!is already locked, returns true when success. The mutex must be unlocked - //!the same number of times it is locked. - //!Throws: interprocess_exception if a severe error is found - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - bool try_lock(); - - //!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before - //!abs_time time, returns false. The mutex must be unlocked - //! the same number of times it is locked. - //!Throws: interprocess_exception if a severe error is found - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 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. - //! If the mutex supports recursive locking, the mutex must be unlocked the - //! same number of times it is locked. - //!Throws: interprocess_exception on error. - void unlock(); - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - #if defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX) - ipcdetail::posix_recursive_mutex mutex; - #elif defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI) - ipcdetail::winapi_recursive_mutex mutex; - #else - void take_ownership(){ mutex.take_ownership(); } - friend class ipcdetail::robust_emulation_helpers::mutex_traits; - ipcdetail::spin_recursive_mutex mutex; - #endif - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess { -} //namespace boost { - -namespace boost { -namespace interprocess { - -inline interprocess_recursive_mutex::interprocess_recursive_mutex(){} - -inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){} - -inline void interprocess_recursive_mutex::lock() -{ ipcdetail::timeout_when_locking_aware_lock(mutex); } - -inline bool interprocess_recursive_mutex::try_lock() -{ return mutex.try_lock(); } - -template -inline bool interprocess_recursive_mutex::timed_lock(const TimePoint &abs_time) -{ return mutex.timed_lock(abs_time); } - -inline void interprocess_recursive_mutex::unlock() -{ mutex.unlock(); } - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp b/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp deleted file mode 100644 index abb74e8aa48..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_semaphore.hpp +++ /dev/null @@ -1,143 +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_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_SEMAPHORE_HPP - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \ - defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \ - defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES) - #include - #define BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX -#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - //Experimental... - #include - #define BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI -#else - //spin_semaphore is used - #include -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!\file -//!Describes a interprocess_semaphore class for inter-process synchronization - -namespace boost { -namespace interprocess { - -//!Wraps a interprocess_semaphore that can be placed in shared memory and can be -//!shared between processes. Allows timed lock tries -class interprocess_semaphore -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - interprocess_semaphore(const interprocess_semaphore &); - interprocess_semaphore &operator=(const interprocess_semaphore &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - //!Creates a interprocess_semaphore with the given initial count. - //!interprocess_exception if there is an error.*/ - interprocess_semaphore(unsigned int initialCount); - - //!Destroys the interprocess_semaphore. - //!Does not throw - ~interprocess_semaphore(); - - //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting - //!for the interprocess_semaphore, then one of these processes will return successfully from - //!its wait function. If there is an error an interprocess_exception exception is thrown. - void post(); - - //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. - //!If there is an error an interprocess_exception exception is thrown. - void wait(); - - //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero - //!and returns true. If the value is not greater than zero returns false. - //!If there is an error an interprocess_exception exception is thrown. - bool try_wait(); - - //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater - //!than zero and returns true. Otherwise, waits for the interprocess_semaphore - //!to the posted or the timeout expires. If the timeout expires, the - //!function returns false. If the interprocess_semaphore is posted the function - //!returns true. If there is an error throws sem_exception - template - bool timed_wait(const TimePoint &abs_time); - - //!Returns the interprocess_semaphore count -// int get_count() const; - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - #if defined(BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX) - typedef ipcdetail::posix_semaphore internal_sem_t; - #elif defined(BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI) - typedef ipcdetail::winapi_semaphore internal_sem_t; - #else - typedef ipcdetail::spin_semaphore internal_sem_t; - #endif //#if defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) - internal_sem_t m_sem; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess { -} //namespace boost { - -namespace boost { -namespace interprocess { - -inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount) - : m_sem(initialCount) -{} - -inline interprocess_semaphore::~interprocess_semaphore(){} - -inline void interprocess_semaphore::wait() -{ - ipcdetail::lock_to_wait ltw(m_sem); - timeout_when_locking_aware_lock(ltw); -} - -inline bool interprocess_semaphore::try_wait() -{ return m_sem.try_wait(); } - -template -inline bool interprocess_semaphore::timed_wait(const TimePoint &abs_time) -{ return m_sem.timed_wait(abs_time); } - -inline void interprocess_semaphore::post() -{ m_sem.post(); } - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp deleted file mode 100644 index bee9eedeade..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_sharable_mutex.hpp +++ /dev/null @@ -1,424 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Code based on Howard Hinnant's shared_mutex class -// -// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost -// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt) -// -// (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_SHARABLE_MUTEX_HPP -#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - - -//!\file -//!Describes interprocess_sharable_mutex class - -namespace boost { -namespace interprocess { - -//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be -//!shared between processes. Allows timed lock tries -class interprocess_sharable_mutex -{ - //Non-copyable - interprocess_sharable_mutex(const interprocess_sharable_mutex &); - interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &); - - friend class interprocess_condition; - public: - - //!Constructs the sharable lock. - //!Throws interprocess_exception on error. - interprocess_sharable_mutex(); - - //!Destroys the sharable lock. - //!Does not throw. - ~interprocess_sharable_mutex(); - - //Exclusive locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive or sharable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!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 acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive or sharable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive or sharable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_sharable(); - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, 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_sharable(); - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise 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. - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_until(const TimePoint &abs_time) - { return this->timed_lock_sharable(abs_time); } - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_for(const Duration &dur) - { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef scoped_lock scoped_lock_t; - - //Pack all the control data in a word to be able - //to use atomic instructions in the future - struct control_word_t - { - unsigned exclusive_in : 1; - unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1; - } m_ctrl; - - interprocess_mutex m_mut; - interprocess_condition m_first_gate; - interprocess_condition m_second_gate; - - private: - //Rollback structures for exceptions or failure return values - struct exclusive_rollback - { - exclusive_rollback(control_word_t &ctrl - ,interprocess_condition &first_gate) - : mp_ctrl(&ctrl), m_first_gate(first_gate) - {} - - void release() - { mp_ctrl = 0; } - - ~exclusive_rollback() - { - if(mp_ctrl){ - mp_ctrl->exclusive_in = 0; - m_first_gate.notify_all(); - } - } - control_word_t *mp_ctrl; - interprocess_condition &m_first_gate; - }; - - template - struct base_constants_t - { - static const unsigned max_readers - = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1)); - }; - typedef base_constants_t<0> constants; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -const unsigned interprocess_sharable_mutex::base_constants_t::max_readers; - -inline interprocess_sharable_mutex::interprocess_sharable_mutex() -{ - this->m_ctrl.exclusive_in = 0; - this->m_ctrl.num_shared = 0; -} - -inline interprocess_sharable_mutex::~interprocess_sharable_mutex() -{} - -inline void interprocess_sharable_mutex::lock() -{ - scoped_lock_t lck(m_mut); - - //The exclusive lock must block in the first gate - //if an exclusive lock has been acquired - while (this->m_ctrl.exclusive_in){ - this->m_first_gate.wait(lck); - } - - //Mark that exclusive lock has been acquired - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); - - //Now wait until all readers are gone - while (this->m_ctrl.num_shared){ - this->m_second_gate.wait(lck); - } - rollback.release(); -} - -inline bool interprocess_sharable_mutex::try_lock() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //If we can't lock or any has there is any exclusive - //or sharable mark return false; - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.num_shared){ - return false; - } - this->m_ctrl.exclusive_in = 1; - return true; -} - -template -inline bool interprocess_sharable_mutex::timed_lock - (const TimePoint &abs_time) -{ - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //The exclusive lock must block in the first gate - //if an exclusive lock has been acquired - while (this->m_ctrl.exclusive_in){ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - if(!this->m_first_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.exclusive_in){ - return false; - } - break; - } - } - - //Mark that exclusive lock has been acquired - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); - - //Now wait until all readers are gone - while (this->m_ctrl.num_shared){ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - if(!this->m_second_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.num_shared){ - return false; - } - break; - } - } - rollback.release(); - return true; -} - -inline void interprocess_sharable_mutex::unlock() -{ - scoped_lock_t lck(m_mut); - this->m_ctrl.exclusive_in = 0; - this->m_first_gate.notify_all(); -} - -//Sharable locking - -inline void interprocess_sharable_mutex::lock_sharable() -{ - scoped_lock_t lck(m_mut); - - //The sharable lock must block in the first gate - //if an exclusive lock has been acquired - //or there are too many sharable locks - while(this->m_ctrl.exclusive_in - || this->m_ctrl.num_shared == constants::max_readers){ - this->m_first_gate.wait(lck); - } - - //Increment sharable count - ++this->m_ctrl.num_shared; -} - -inline bool interprocess_sharable_mutex::try_lock_sharable() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //The sharable lock must fail - //if an exclusive lock has been acquired - //or there are too many sharable locks - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.num_shared == constants::max_readers){ - return false; - } - - //Increment sharable count - ++this->m_ctrl.num_shared; - return true; -} - -template -inline bool interprocess_sharable_mutex::timed_lock_sharable - (const TimePoint &abs_time) -{ - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //The sharable lock must block in the first gate - //if an exclusive lock has been acquired - //or there are too many sharable locks - while (this->m_ctrl.exclusive_in - || this->m_ctrl.num_shared == constants::max_readers){ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - if(!this->m_first_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.exclusive_in - || this->m_ctrl.num_shared == constants::max_readers){ - return false; - } - break; - } - } - - //Increment sharable count - ++this->m_ctrl.num_shared; - return true; -} - -inline void interprocess_sharable_mutex::unlock_sharable() -{ - scoped_lock_t lck(m_mut); - //Decrement sharable count - --this->m_ctrl.num_shared; - if (this->m_ctrl.num_shared == 0){ - this->m_second_gate.notify_one(); - } - //Check if there are blocked sharables because of - //there were too many sharables - else if(this->m_ctrl.num_shared == (constants::max_readers-1)){ - this->m_first_gate.notify_all(); - } -} - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp deleted file mode 100644 index 7b7893a8b3f..00000000000 --- a/extern/boost/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ /dev/null @@ -1,771 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Code based on Howard Hinnant's upgrade_mutex class -// -// (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_UPGRADABLE_MUTEX_HPP -#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - - -//!\file -//!Describes interprocess_upgradable_mutex class - -namespace boost { -namespace interprocess { - -//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be -//!shared between processes. Allows timed lock tries -class interprocess_upgradable_mutex -{ - //Non-copyable - interprocess_upgradable_mutex(const interprocess_upgradable_mutex &); - interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &); - - friend class interprocess_condition; - public: - - //!Constructs the upgradable lock. - //!Throws interprocess_exception on error. - interprocess_upgradable_mutex(); - - //!Destroys the upgradable lock. - //!Does not throw. - ~interprocess_upgradable_mutex(); - - //Exclusive locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive, sharable or upgradable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!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 acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive, sharable or upgradable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_sharable(); - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, 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_sharable(); - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise 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. - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_until(const TimePoint &abs_time) - { return this->timed_lock_sharable(abs_time); } - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_for(const Duration &dur) - { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - //Upgradable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, - //! and if another thread has exclusive or upgradable ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_upgradable(); - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire upgradable ownership immediately returns true. - //! If it has to wait, 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_upgradable(); - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! waiting if necessary until no other thread has exclusive or upgradable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise 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. - template - bool timed_lock_upgradable(const TimePoint &abs_time); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable(); - - //Demotions - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_upgradable(); - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_sharable(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock_sharable(); - - //Promotions - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release their sharable lock. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to - //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to acquire - //! exclusive ownership, waiting if necessary until abs_time. This operation will - //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. */ - template - bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The thread atomically releases sharable ownership and tries to acquire - //! exclusive ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_sharable_and_lock(); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The thread atomically releases sharable ownership and tries to acquire - //! upgradable ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_sharable_and_lock_upgradable(); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef scoped_lock scoped_lock_t; - - //Pack all the control data in a word to be able - //to use atomic instructions in the future - struct control_word_t - { - unsigned exclusive_in : 1; - unsigned upgradable_in : 1; - unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2; - } m_ctrl; - - interprocess_mutex m_mut; - interprocess_condition m_first_gate; - interprocess_condition m_second_gate; - - private: - //Rollback structures for exceptions or failure return values - struct exclusive_rollback - { - exclusive_rollback(control_word_t &ctrl - ,interprocess_condition &first_gate) - : mp_ctrl(&ctrl), m_first_gate(first_gate) - {} - - void release() - { mp_ctrl = 0; } - - ~exclusive_rollback() - { - if(mp_ctrl){ - mp_ctrl->exclusive_in = 0; - m_first_gate.notify_all(); - } - } - control_word_t *mp_ctrl; - interprocess_condition &m_first_gate; - }; - - struct upgradable_to_exclusive_rollback - { - upgradable_to_exclusive_rollback(control_word_t &ctrl) - : mp_ctrl(&ctrl) - {} - - void release() - { mp_ctrl = 0; } - - ~upgradable_to_exclusive_rollback() - { - if(mp_ctrl){ - //Recover upgradable lock - mp_ctrl->upgradable_in = 1; - ++mp_ctrl->num_upr_shar; - //Execute the second half of exclusive locking - mp_ctrl->exclusive_in = 0; - } - } - control_word_t *mp_ctrl; - }; - - template - struct base_constants_t - { - static const unsigned max_readers - = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); - }; - typedef base_constants_t<0> constants; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -template -const unsigned interprocess_upgradable_mutex::base_constants_t::max_readers; - -inline interprocess_upgradable_mutex::interprocess_upgradable_mutex() -{ - this->m_ctrl.exclusive_in = 0; - this->m_ctrl.upgradable_in = 0; - this->m_ctrl.num_upr_shar = 0; -} - -inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex() -{} - -inline void interprocess_upgradable_mutex::lock() -{ - scoped_lock_t lck(m_mut); - - //The exclusive lock must block in the first gate - //if an exclusive or upgradable lock has been acquired - while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - this->m_first_gate.wait(lck); - } - - //Mark that exclusive lock has been acquired - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); - - //Now wait until all readers are gone - while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lck); - } - rollback.release(); -} - -inline bool interprocess_upgradable_mutex::try_lock() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //If we can't lock or any has there is any exclusive, upgradable - //or sharable mark return false; - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar){ - return false; - } - this->m_ctrl.exclusive_in = 1; - return true; -} - -template -bool interprocess_upgradable_mutex::timed_lock(const TimePoint &abs_time) -{ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //The exclusive lock must block in the first gate - //if an exclusive or upgradable lock has been acquired - while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - if(!this->m_first_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - return false; - } - break; - } - } - - //Mark that exclusive lock has been acquired - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); - - //Now wait until all readers are gone - while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.num_upr_shar){ - return false; - } - break; - } - } - rollback.release(); - return true; -} - -inline void interprocess_upgradable_mutex::unlock() -{ - scoped_lock_t lck(m_mut); - this->m_ctrl.exclusive_in = 0; - this->m_first_gate.notify_all(); -} - -//Upgradable locking - -inline void interprocess_upgradable_mutex::lock_upgradable() -{ - scoped_lock_t lck(m_mut); - - //The upgradable lock must block in the first gate - //if an exclusive or upgradable lock has been acquired - //or there are too many sharable locks - while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lck); - } - - //Mark that upgradable lock has been acquired - //And add upgradable to the sharable count - this->m_ctrl.upgradable_in = 1; - ++this->m_ctrl.num_upr_shar; -} - -inline bool interprocess_upgradable_mutex::try_lock_upgradable() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //The upgradable lock must fail - //if an exclusive or upgradable lock has been acquired - //or there are too many sharable locks - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - return false; - } - - //Mark that upgradable lock has been acquired - //And add upgradable to the sharable count - this->m_ctrl.upgradable_in = 1; - ++this->m_ctrl.num_upr_shar; - return true; -} - -template -bool interprocess_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) -{ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //The upgradable lock must block in the first gate - //if an exclusive or upgradable lock has been acquired - //or there are too many sharable locks - while(this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lck, abs_time)){ - if((this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers)){ - return false; - } - break; - } - } - - //Mark that upgradable lock has been acquired - //And add upgradable to the sharable count - this->m_ctrl.upgradable_in = 1; - ++this->m_ctrl.num_upr_shar; - return true; -} - -inline void interprocess_upgradable_mutex::unlock_upgradable() -{ - scoped_lock_t lck(m_mut); - //Mark that upgradable lock has been acquired - //And add upgradable to the sharable count - this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; - this->m_first_gate.notify_all(); -} - -//Sharable locking - -inline void interprocess_upgradable_mutex::lock_sharable() -{ - scoped_lock_t lck(m_mut); - - //The sharable lock must block in the first gate - //if an exclusive lock has been acquired - //or there are too many sharable locks - while(this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lck); - } - - //Increment sharable count - ++this->m_ctrl.num_upr_shar; -} - -inline bool interprocess_upgradable_mutex::try_lock_sharable() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //The sharable lock must fail - //if an exclusive lock has been acquired - //or there are too many sharable locks - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - return false; - } - - //Increment sharable count - ++this->m_ctrl.num_upr_shar; - return true; -} - -template -inline bool interprocess_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) -{ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //The sharable lock must block in the first gate - //if an exclusive lock has been acquired - //or there are too many sharable locks - while (this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers){ - return false; - } - break; - } - } - - //Increment sharable count - ++this->m_ctrl.num_upr_shar; - return true; -} - -inline void interprocess_upgradable_mutex::unlock_sharable() -{ - scoped_lock_t lck(m_mut); - //Decrement sharable count - --this->m_ctrl.num_upr_shar; - if (this->m_ctrl.num_upr_shar == 0){ - this->m_second_gate.notify_one(); - } - //Check if there are blocked sharables because of - //there were too many sharables - else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){ - this->m_first_gate.notify_all(); - } -} - -//Downgrading - -inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() -{ - scoped_lock_t lck(m_mut); - //Unmark it as exclusive - this->m_ctrl.exclusive_in = 0; - //Mark it as upgradable - this->m_ctrl.upgradable_in = 1; - //The sharable count should be 0 so increment it - this->m_ctrl.num_upr_shar = 1; - //Notify readers that they can enter - m_first_gate.notify_all(); -} - -inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() -{ - scoped_lock_t lck(m_mut); - //Unmark it as exclusive - this->m_ctrl.exclusive_in = 0; - //The sharable count should be 0 so increment it - this->m_ctrl.num_upr_shar = 1; - //Notify readers that they can enter - m_first_gate.notify_all(); -} - -inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() -{ - scoped_lock_t lck(m_mut); - //Unmark it as upgradable (we don't have to decrement count) - this->m_ctrl.upgradable_in = 0; - //Notify readers/upgradable that they can enter - m_first_gate.notify_all(); -} - -//Upgrading - -inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() -{ - scoped_lock_t lck(m_mut); - //Simulate unlock_upgradable() without - //notifying sharables. - this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; - //Execute the second half of exclusive locking - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - upgradable_to_exclusive_rollback rollback(m_ctrl); - - while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lck); - } - rollback.release(); -} - -inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() -{ - scoped_lock_t lck(m_mut, try_to_lock); - //Check if there are no readers - if(!lck.owns() - || this->m_ctrl.num_upr_shar != 1){ - return false; - } - //Now unlock upgradable and mark exclusive - this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; - this->m_ctrl.exclusive_in = 1; - return true; -} - -template -bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) -{ - //Mutexes and condvars handle just fine infinite abs_times - //so avoid checking it here - scoped_lock_t lck(m_mut, abs_time); - if(!lck.owns()) return false; - - //Simulate unlock_upgradable() without - //notifying sharables. - this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; - //Execute the second half of exclusive locking - this->m_ctrl.exclusive_in = 1; - - //Prepare rollback - upgradable_to_exclusive_rollback rollback(m_ctrl); - - while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lck, abs_time)){ - if(this->m_ctrl.num_upr_shar){ - return false; - } - break; - } - } - rollback.release(); - return true; -} - -inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //If we can't lock or any has there is any exclusive, upgradable - //or sharable mark return false; - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar != 1){ - return false; - } - this->m_ctrl.exclusive_in = 1; - this->m_ctrl.num_upr_shar = 0; - return true; -} - -inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() -{ - scoped_lock_t lck(m_mut, try_to_lock); - - //The upgradable lock must fail - //if an exclusive or upgradable lock has been acquired - if(!lck.owns() - || this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in){ - return false; - } - - //Mark that upgradable lock has been acquired - this->m_ctrl.upgradable_in = 1; - return true; -} - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - - -#include - -#endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/mutex_family.hpp b/extern/boost/boost/interprocess/sync/mutex_family.hpp deleted file mode 100644 index b136ce4418d..00000000000 --- a/extern/boost/boost/interprocess/sync/mutex_family.hpp +++ /dev/null @@ -1,60 +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_MUTEX_FAMILY_HPP -#define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include - -//!\file -//!Describes a shared interprocess_mutex family fit algorithm used to allocate objects in shared memory. - -namespace boost { - -namespace interprocess { - -//!Describes interprocess_mutex family to use with Interprocess framework -//!based on boost::interprocess synchronization objects. -struct mutex_family -{ - typedef boost::interprocess::interprocess_mutex mutex_type; - typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type; -}; - -//!Describes interprocess_mutex family to use with Interprocess frameworks -//!based on null operation synchronization objects. -struct null_mutex_family -{ - typedef boost::interprocess::null_mutex mutex_type; - typedef boost::interprocess::null_mutex recursive_mutex_type; -}; - -} //namespace interprocess { - -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP - - diff --git a/extern/boost/boost/interprocess/sync/named_condition.hpp b/extern/boost/boost/interprocess/sync/named_condition.hpp deleted file mode 100644 index 78a9fb90159..00000000000 --- a/extern/boost/boost/interprocess/sync/named_condition.hpp +++ /dev/null @@ -1,299 +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_NAMED_CONDITION_HPP -#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI -#else - #include -#endif - -//!\file -//!Describes a named condition class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//! A global condition variable that can be created by name. -//! This condition variable is designed to work with named_mutex and -//! can't be placed in shared memory or memory mapped files. -class named_condition -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_condition(); - named_condition(const named_condition &); - named_condition &operator=(const named_condition &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - named_condition(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!named_condition(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!named_condition(open_only_t, ... ) - //!Does not throw - named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_condition(open_only_t, const char *name); - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!named_condition(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!named_condition(open_only_t, ... ) - //!Does not throw - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition(open_only_t, const wchar_t *name); - - #endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_condition(); - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one(); - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all(); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock); - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time); - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred); - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - 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 - 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 - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } - - //!Erases a named condition 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 named condition 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) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - #if defined(BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI) - typedef ipcdetail::winapi_named_condition condition_type; - #else - typedef ipcdetail::shm_named_condition condition_type; - #endif - condition_type m_cond; - - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction() - { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_condition::~named_condition() -{} - -inline named_condition::named_condition(create_only_t, const char *name, const permissions &perm) - : m_cond(create_only_t(), name, perm) -{} - -inline named_condition::named_condition(open_or_create_t, const char *name, const permissions &perm) - : m_cond(open_or_create_t(), name, perm) -{} - -inline named_condition::named_condition(open_only_t, const char *name) - : m_cond(open_only_t(), name) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_condition::named_condition(create_only_t, const wchar_t *name, const permissions &perm) - : m_cond(create_only_t(), name, perm) -{} - -inline named_condition::named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_cond(open_or_create_t(), name, perm) -{} - -inline named_condition::named_condition(open_only_t, const wchar_t *name) - : m_cond(open_only_t(), name) -{} - -#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - -inline void named_condition::notify_one() -{ m_cond.notify_one(); } - -inline void named_condition::notify_all() -{ m_cond.notify_all(); } - -template -inline void named_condition::wait(L& lock) -{ - ipcdetail::internal_mutex_lock internal_lock(lock); - m_cond.wait(internal_lock); -} - -template -inline void named_condition::wait(L& lock, Pr pred) -{ - ipcdetail::internal_mutex_lock internal_lock(lock); - m_cond.wait(internal_lock, pred); -} - -template -inline bool named_condition::timed_wait - (L& lock, const TimePoint &abs_time) -{ - ipcdetail::internal_mutex_lock internal_lock(lock); - return m_cond.timed_wait(internal_lock, abs_time); -} - -template -inline bool named_condition::timed_wait - (L& lock, const TimePoint &abs_time, Pr pred) -{ - ipcdetail::internal_mutex_lock internal_lock(lock); - return m_cond.timed_wait(internal_lock, abs_time, pred); -} - -inline bool named_condition::remove(const char *name) -{ - return condition_type::remove(name); -} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_condition::remove(const wchar_t *name) -{ - return condition_type::remove(name); -} - -#endif - - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess -} //namespace boost - -#include - -#endif // BOOST_INTERPROCESS_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/named_condition_any.hpp deleted file mode 100644 index 2614c46d488..00000000000 --- a/extern/boost/boost/interprocess/sync/named_condition_any.hpp +++ /dev/null @@ -1,230 +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_NAMED_CONDITION_ANY_HPP -#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI -#else - #include -#endif - -//!\file -//!Describes a named condition class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//! A global condition variable that can be created by name. -//! This condition variable is designed to work with named_mutex and -//! can't be placed in shared memory or memory mapped files. -class named_condition_any -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_condition_any(); - named_condition_any(const named_condition_any &); - named_condition_any &operator=(const named_condition_any &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - named_condition_any(create_only_t, const char *name, const permissions &perm = permissions()) - : m_cond(create_only_t(), name, perm) - {} - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!named_condition_any(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!named_condition_any(open_only_t, ... ) - //!Does not throw - named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions()) - : m_cond(open_or_create_t(), name, perm) - {} - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_condition_any(open_only_t, const char *name) - : m_cond(open_only_t(), name) - {} - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition_any(create_only_t, const wchar_t *name, const permissions &perm = permissions()) - : m_cond(create_only_t(), name, perm) - {} - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!named_condition_any(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!named_condition_any(open_only_t, ... ) - //!Does not throw - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition_any(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) - : m_cond(open_or_create_t(), name, perm) - {} - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_condition_any(open_only_t, const wchar_t *name) - : m_cond(open_only_t(), name) - {} - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_condition_any() - {} - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one() - { m_cond.notify_one(); } - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all() - { m_cond.notify_all(); } - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock) - { return m_cond.wait(lock); } - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred) - { return m_cond.wait(lock, pred); } - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time) - { return m_cond.timed_wait(lock, abs_time); } - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { return m_cond.timed_wait(lock, abs_time, pred); } - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - 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 - 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 - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } - - //!Erases a named condition from the system. - //!Returns false on error. Never throws. - static bool remove(const char *name) - { return condition_any_type::remove(name); } - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Erases a named condition 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) - { return condition_any_type::remove(name); } - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - #if defined(BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI) - typedef ipcdetail::winapi_named_condition_any condition_any_type; - #else - typedef ipcdetail::shm_named_condition_any condition_any_type; - #endif - condition_any_type m_cond; - - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction() - { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess -} //namespace boost - -#include - -#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/named_mutex.hpp b/extern/boost/boost/interprocess/sync/named_mutex.hpp deleted file mode 100644 index c7415769dae..00000000000 --- a/extern/boost/boost/interprocess/sync/named_mutex.hpp +++ /dev/null @@ -1,267 +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_NAMED_MUTEX_HPP -#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - #include - #define BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX -#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI -#else - #include -#endif - -//!\file -//!Describes a named mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { - -class named_condition; - -//!A mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named_mutex. -class named_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - named_mutex(); - named_mutex(const named_mutex &); - named_mutex &operator=(const named_mutex &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Creates a global mutex with a name. - //!Throws interprocess_exception on error. - named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global mutex with a name. - //!If the mutex is created, this call is equivalent to - //!named_mutex(create_only_t, ... ) - //!If the mutex is already created, this call is equivalent - //!named_mutex(open_only_t, ... ) - //!Does not throw - named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global mutex with a name if that mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global mutex with a name. - //!Throws interprocess_exception on error. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global mutex with a name. - //!If the mutex is created, this call is equivalent to - //!named_mutex(create_only_t, ... ) - //!If the mutex is already created, this call is equivalent - //!named_mutex(open_only_t, ... ) - //!Does not throw - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global mutex with a name if that mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_mutex(); - - //!Unlocks a previously locked - //!mutex. - void unlock(); - - //!Requires: The calling thread does not own the mutex. - //! - //!Locks the mutex, sleeps when the mutex is already locked. - //!Throws interprocess_exception if a severe error is found - //! - //!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. - //! - //!Tries to lock the mutex, returns false when the mutex - //!is already locked, returns true when success. - //!Throws interprocess_exception if a severe error is found - //! - //!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. - //! - //!Tries to lock the the mutex until time abs_time, - //!Returns false when timeout expires, returns true when locks. - //!Throws interprocess_exception if a severe error is found - //! - //!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 - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Erases a named mutex 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 named mutex 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) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - public: - #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX) - typedef ipcdetail::posix_named_mutex internal_mutex_type; - #elif defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI) - typedef ipcdetail::winapi_named_mutex internal_mutex_type; - #else - typedef ipcdetail::shm_named_mutex internal_mutex_type; - #endif - internal_mutex_type &internal_mutex() - { return m_mut; } - - internal_mutex_type m_mut; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_mutex::named_mutex(create_only_t, const char *name, const permissions &perm) - : m_mut(create_only_t(), name, perm) -{} - -inline named_mutex::named_mutex(open_or_create_t, const char *name, const permissions &perm) - : m_mut(open_or_create_t(), name, perm) -{} - -inline named_mutex::named_mutex(open_only_t, const char *name) - : m_mut(open_only_t(), name) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_mutex::named_mutex(create_only_t, const wchar_t *name, const permissions &perm) - : m_mut(create_only_t(), name, perm) -{} - -inline named_mutex::named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_mut(open_or_create_t(), name, perm) -{} - -inline named_mutex::named_mutex(open_only_t, const wchar_t *name) - : m_mut(open_only_t(), name) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void named_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); } - -inline named_mutex::~named_mutex() -{} - -inline void named_mutex::lock() -{ m_mut.lock(); } - -inline void named_mutex::unlock() -{ m_mut.unlock(); } - -inline bool named_mutex::try_lock() -{ return m_mut.try_lock(); } - -template -inline bool named_mutex::timed_lock(const TimePoint &abs_time) -{ return m_mut.timed_lock(abs_time); } - -inline bool named_mutex::remove(const char *name) -{ return internal_mutex_type::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_mutex::remove(const wchar_t *name) -{ return internal_mutex_type::remove(name); } - -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp deleted file mode 100644 index e75d0f9d6f3..00000000000 --- a/extern/boost/boost/interprocess/sync/named_recursive_mutex.hpp +++ /dev/null @@ -1,245 +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_NAMED_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI -#else - #include -#endif - -//!\file -//!Describes a named named_recursive_mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//!A recursive mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named_recursive_mutex. -class named_recursive_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_recursive_mutex(); - named_recursive_mutex(const named_recursive_mutex &); - named_recursive_mutex &operator=(const named_recursive_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global recursive_mutex with a name. - //!If the recursive_mutex can't be created throws interprocess_exception - named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global recursive_mutex with a name. - //!If the recursive_mutex is created, this call is equivalent to - //!named_recursive_mutex(create_only_t, ... ) - //!If the recursive_mutex is already created, this call is equivalent - //!named_recursive_mutex(open_only_t, ... ) - //!Does not throw - named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global recursive_mutex with a name if that recursive_mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_recursive_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global recursive_mutex with a name. - //!If the recursive_mutex can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global recursive_mutex with a name. - //!If the recursive_mutex is created, this call is equivalent to - //!named_recursive_mutex(create_only_t, ... ) - //!If the recursive_mutex is already created, this call is equivalent - //!named_recursive_mutex(open_only_t, ... ) - //!Does not throw - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global recursive_mutex with a name if that recursive_mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_recursive_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_recursive_mutex(); - - //!Unlocks a previously locked - //!named_recursive_mutex. - void unlock(); - - //!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked. - //!Throws interprocess_exception if a severe error is found. - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - void lock(); - - //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex - //!is already locked, returns true when success. - //!Throws interprocess_exception if a severe error is found. - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - bool try_lock(); - - //!Tries to lock the named_recursive_mutex until time abs_time, - //!Returns false when timeout expires, returns true when locks. - //!Throws interprocess_exception if a severe error is found - //! - //!Note: A program shall not deadlock if the thread that has ownership calls - //! this function. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Erases a named recursive mutex - //!from the system - static bool remove(const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //!Erases a named recursive mutex - //!from the system - //! - //!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) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - #if defined(BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI) - typedef ipcdetail::winapi_named_recursive_mutex impl_t; - #else - typedef ipcdetail::shm_named_recursive_mutex impl_t; - #endif - impl_t m_mut; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_recursive_mutex::~named_recursive_mutex() -{} - -inline void named_recursive_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); } - -inline named_recursive_mutex::named_recursive_mutex(create_only_t, const char *name, const permissions &perm) - : m_mut (create_only, name, perm) -{} - -inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm) - : m_mut (open_or_create, name, perm) -{} - -inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *name) - : m_mut (open_only, name) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_recursive_mutex::named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) - : m_mut (create_only, name, perm) -{} - -inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_mut (open_or_create, name, perm) -{} - -inline named_recursive_mutex::named_recursive_mutex(open_only_t, const wchar_t *name) - : m_mut (open_only, name) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void named_recursive_mutex::lock() -{ m_mut.lock(); } - -inline void named_recursive_mutex::unlock() -{ m_mut.unlock(); } - -inline bool named_recursive_mutex::try_lock() -{ return m_mut.try_lock(); } - -template -inline bool named_recursive_mutex::timed_lock(const TimePoint &abs_time) -{ return m_mut.timed_lock(abs_time); } - -inline bool named_recursive_mutex::remove(const char *name) -{ return impl_t::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_recursive_mutex::remove(const wchar_t *name) -{ return impl_t::remove(name); } - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/named_semaphore.hpp deleted file mode 100644 index 74d38ba97c2..00000000000 --- a/extern/boost/boost/interprocess/sync/named_semaphore.hpp +++ /dev/null @@ -1,239 +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_NAMED_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) -#include -//Experimental... -#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) - #include - #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI -#else - #include -#endif - -//!\file -//!Describes a named semaphore class for inter-process synchronization - -namespace boost { -namespace interprocess { - -//!A semaphore with a global name, so it can be found from different -//!processes. Allows several resource sharing patterns and efficient -//!acknowledgment mechanisms. -class named_semaphore -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - named_semaphore(); - named_semaphore(const named_semaphore &); - named_semaphore &operator=(const named_semaphore &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Creates a global semaphore with a name, and an initial count. - //!If the semaphore can't be created throws interprocess_exception - named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - //!Opens or creates a global semaphore with a name, and an initial count. - //!If the semaphore is created, this call is equivalent to - //!named_semaphore(create_only_t, ...) - //!If the semaphore is already created, this call is equivalent to - //!named_semaphore(open_only_t, ... ) - //!and initialCount is ignored. - named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - //!Opens a global semaphore with a name if that semaphore is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_semaphore(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global semaphore with a name, and an initial count. - //!If the semaphore can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - //!Opens or creates a global semaphore with a name, and an initial count. - //!If the semaphore is created, this call is equivalent to - //!named_semaphore(create_only_t, ...) - //!If the semaphore is already created, this call is equivalent to - //!named_semaphore(open_only_t, ... ) - //!and initialCount is ignored. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - //!Opens a global semaphore with a name if that semaphore is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_semaphore(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_semaphore(); - - //!Increments the semaphore count. If there are processes/threads blocked waiting - //!for the semaphore, then one of these processes will return successfully from - //!its wait function. If there is an error an interprocess_exception exception is thrown. - void post(); - - //!Decrements the semaphore. If the semaphore value is not greater than zero, - //!then the calling process/thread blocks until it can decrement the counter. - //!If there is an error an interprocess_exception exception is thrown. - void wait(); - - //!Decrements the semaphore if the semaphore's value is greater than zero - //!and returns true. If the value is not greater than zero returns false. - //!If there is an error an interprocess_exception exception is thrown. - bool try_wait(); - - //!Decrements the semaphore if the semaphore's value is greater - //!than zero and returns true. Otherwise, waits for the semaphore - //!to the posted or the timeout expires. If the timeout expires, the - //!function returns false. If the semaphore is posted the function - //!returns true. If there is an error throws sem_exception - template - bool timed_wait(const TimePoint &abs_time); - - //!Erases a named semaphore 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 named semaphore 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) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_semaphore impl_t; - #elif defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI) - typedef ipcdetail::winapi_named_semaphore impl_t; - #else - typedef ipcdetail::shm_named_semaphore impl_t; - #endif - impl_t m_sem; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_semaphore::named_semaphore - (create_only_t, const char *name, unsigned int initialCount, const permissions &perm) - : m_sem(create_only, name, initialCount, perm) -{} - -inline named_semaphore::named_semaphore - (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm) - : m_sem(open_or_create, name, initialCount, perm) -{} - -inline named_semaphore::named_semaphore(open_only_t, const char *name) - : m_sem(open_only, name) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_semaphore::named_semaphore - (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) - : m_sem(create_only, name, initialCount, perm) -{} - -inline named_semaphore::named_semaphore - (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) - : m_sem(open_or_create, name, initialCount, perm) -{} - -inline named_semaphore::named_semaphore(open_only_t, const wchar_t *name) - : m_sem(open_only, name) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_semaphore::~named_semaphore() -{} - -inline void named_semaphore::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_sem); } - -inline void named_semaphore::wait() -{ m_sem.wait(); } - -inline void named_semaphore::post() -{ m_sem.post(); } - -inline bool named_semaphore::try_wait() -{ return m_sem.try_wait(); } - -template -inline bool named_semaphore::timed_wait(const TimePoint &abs_time) -{ return m_sem.timed_wait(abs_time); } - -inline bool named_semaphore::remove(const char *name) -{ return impl_t::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_semaphore::remove(const wchar_t *name) -{ return impl_t::remove(name); } - -#endif - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - - -#include - -#endif //BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp b/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp deleted file mode 100644 index d56e7b9c064..00000000000 --- a/extern/boost/boost/interprocess/sync/named_sharable_mutex.hpp +++ /dev/null @@ -1,391 +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_NAMED_SHARABLE_MUTEX_HPP -#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a named sharable mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -class named_condition; - -//!A sharable mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named sharable mutex. -class named_sharable_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_sharable_mutex(); - named_sharable_mutex(const named_sharable_mutex &); - named_sharable_mutex &operator=(const named_sharable_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global sharable mutex with a name. - //!If the sharable mutex can't be created throws interprocess_exception - named_sharable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global sharable mutex with a name. - //!If the sharable mutex is created, this call is equivalent to - //!named_sharable_mutex(create_only_t, ...) - //!If the sharable mutex is already created, this call is equivalent to - //!named_sharable_mutex(open_only_t, ... ). - named_sharable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global sharable mutex with a name if that sharable mutex - //!is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_sharable_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global sharable mutex with a name. - //!If the sharable mutex can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_sharable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global sharable mutex with a name. - //!If the sharable mutex is created, this call is equivalent to - //!named_sharable_mutex(create_only_t, ...) - //!If the sharable mutex is already created, this call is equivalent to - //!named_sharable_mutex(open_only_t, ... ). - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_sharable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global sharable mutex with a name if that sharable mutex - //!is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_sharable_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_sharable_mutex(); - - //Exclusive locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive or sharable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!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 acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive or sharable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive, or sharable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise 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. - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_sharable(); - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, 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_sharable(); - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise 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 - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_until(const TimePoint &abs_time) - { return this->timed_lock_sharable(abs_time); } - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_for(const Duration &dur) - { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - //!Erases a named sharable mutex 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 named sharable mutex from the system. - //!Returns false on error. Never throws. - static bool remove(const wchar_t *name); - - #endif - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - interprocess_sharable_mutex *mutex() const - { return static_cast(m_shmem.get_user_address()); } - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_sharable_mutex::~named_sharable_mutex() -{} - -inline named_sharable_mutex::named_sharable_mutex - (create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_sharable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline named_sharable_mutex::named_sharable_mutex - (open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_sharable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline named_sharable_mutex::named_sharable_mutex - (open_only_t, const char *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_sharable_mutex::named_sharable_mutex - (create_only_t, const wchar_t *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_sharable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline named_sharable_mutex::named_sharable_mutex - (open_or_create_t, const wchar_t *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_sharable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline named_sharable_mutex::named_sharable_mutex - (open_only_t, const wchar_t *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#endif - -inline void named_sharable_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline void named_sharable_mutex::lock() -{ this->mutex()->lock(); } - -inline void named_sharable_mutex::unlock() -{ this->mutex()->unlock(); } - -inline bool named_sharable_mutex::try_lock() -{ return this->mutex()->try_lock(); } - -template -inline bool named_sharable_mutex::timed_lock - (const TimePoint &abs_time) -{ return this->mutex()->timed_lock(abs_time); } - -inline void named_sharable_mutex::lock_sharable() -{ this->mutex()->lock_sharable(); } - -inline void named_sharable_mutex::unlock_sharable() -{ this->mutex()->unlock_sharable(); } - -inline bool named_sharable_mutex::try_lock_sharable() -{ return this->mutex()->try_lock_sharable(); } - -template -inline bool named_sharable_mutex::timed_lock_sharable - (const TimePoint &abs_time) -{ return this->mutex()->timed_lock_sharable(abs_time); } - -inline bool named_sharable_mutex::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_sharable_mutex::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp deleted file mode 100644 index 679e961d771..00000000000 --- a/extern/boost/boost/interprocess/sync/named_upgradable_mutex.hpp +++ /dev/null @@ -1,540 +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_named_upgradable_mutex_HPP -#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a named upgradable mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -class named_condition; - -//!A upgradable mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named upgradable mutex. -class named_upgradable_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_upgradable_mutex(); - named_upgradable_mutex(const named_upgradable_mutex &); - named_upgradable_mutex &operator=(const named_upgradable_mutex &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global upgradable mutex with a name. - //!If the upgradable mutex can't be created throws interprocess_exception - named_upgradable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global upgradable mutex with a name. - //!If the upgradable mutex is created, this call is equivalent to - //!named_upgradable_mutex(create_only_t, ...) - //!If the upgradable mutex is already created, this call is equivalent to - //!named_upgradable_mutex(open_only_t, ... ). - named_upgradable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global upgradable mutex with a name if that upgradable mutex - //!is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_upgradable_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global upgradable mutex with a name. - //!If the upgradable mutex can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_upgradable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global upgradable mutex with a name. - //!If the upgradable mutex is created, this call is equivalent to - //!named_upgradable_mutex(create_only_t, ...) - //!If the upgradable mutex is already created, this call is equivalent to - //!named_upgradable_mutex(open_only_t, ... ). - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_upgradable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global upgradable mutex with a name if that upgradable mutex - //!is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - named_upgradable_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_upgradable_mutex(); - - //Exclusive locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive, sharable or upgradable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!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 acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive, sharable or upgradable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, 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 tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise 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 - template - bool timed_lock(const TimePoint &abs_time); - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template 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 bool try_lock_for(const Duration &dur) - { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_sharable(); - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, 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_sharable(); - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise 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 - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_until(const TimePoint &abs_time) - { return this->timed_lock_sharable(abs_time); } - - //!Same as `timed_lock_sharable`, but this function is modeled after the - //!standard library interface. - template bool try_lock_shared_for(const Duration &dur) - { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); } - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - //Upgradable locking - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, - //! and if another thread has exclusive or upgradable ownership of the mutex, - //! waits until it can obtain the ownership. - //!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_upgradable(); - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire upgradable ownership immediately returns true. - //! If it has to wait, 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_upgradable(); - - //!Requires: The calling thread does not own the mutex. - //! - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! waiting if necessary until no other thread has exclusive or upgradable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise 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 - template - bool timed_lock_upgradable(const TimePoint &abs_time); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable(); - - //Demotions - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_upgradable(); - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_sharable(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock_sharable(); - - //Promotions - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to - //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to acquire - //! exclusive ownership, waiting if necessary until abs_time. This operation will - //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - template - bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The thread atomically releases sharable ownership and tries to acquire - //! exclusive ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_sharable_and_lock(); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The thread atomically releases sharable ownership and tries to acquire - //! upgradable ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_sharable_and_lock_upgradable(); - - //!Erases a named upgradable mutex 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 named upgradable mutex 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 - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - interprocess_upgradable_mutex *mutex() const - { return static_cast(m_shmem.get_user_address()); } - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_upgradable_mutex::~named_upgradable_mutex() -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_only_t, const char *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_upgradable_mutex::named_upgradable_mutex - (create_only_t, const wchar_t *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_or_create_t, const wchar_t *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_only_t, const wchar_t *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#endif - -inline void named_upgradable_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline void named_upgradable_mutex::lock() -{ this->mutex()->lock(); } - -inline void named_upgradable_mutex::unlock() -{ this->mutex()->unlock(); } - -inline bool named_upgradable_mutex::try_lock() -{ return this->mutex()->try_lock(); } - -template -inline bool named_upgradable_mutex::timed_lock(const TimePoint &abs_time) -{ return this->mutex()->timed_lock(abs_time); } - -inline void named_upgradable_mutex::lock_upgradable() -{ this->mutex()->lock_upgradable(); } - -inline void named_upgradable_mutex::unlock_upgradable() -{ this->mutex()->unlock_upgradable(); } - -inline bool named_upgradable_mutex::try_lock_upgradable() -{ return this->mutex()->try_lock_upgradable(); } - -template -inline bool named_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) -{ return this->mutex()->timed_lock_upgradable(abs_time); } - -inline void named_upgradable_mutex::lock_sharable() -{ this->mutex()->lock_sharable(); } - -inline void named_upgradable_mutex::unlock_sharable() -{ this->mutex()->unlock_sharable(); } - -inline bool named_upgradable_mutex::try_lock_sharable() -{ return this->mutex()->try_lock_sharable(); } - -template -inline bool named_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) -{ return this->mutex()->timed_lock_sharable(abs_time); } - -inline void named_upgradable_mutex::unlock_and_lock_upgradable() -{ this->mutex()->unlock_and_lock_upgradable(); } - -inline void named_upgradable_mutex::unlock_and_lock_sharable() -{ this->mutex()->unlock_and_lock_sharable(); } - -inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable() -{ this->mutex()->unlock_upgradable_and_lock_sharable(); } - -inline void named_upgradable_mutex::unlock_upgradable_and_lock() -{ this->mutex()->unlock_upgradable_and_lock(); } - -inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock() -{ return this->mutex()->try_unlock_upgradable_and_lock(); } - -template -inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) -{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); } - -inline bool named_upgradable_mutex::try_unlock_sharable_and_lock() -{ return this->mutex()->try_unlock_sharable_and_lock(); } - -inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() -{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); } - -inline bool named_upgradable_mutex::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool named_upgradable_mutex::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif - - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP diff --git a/extern/boost/boost/interprocess/sync/null_mutex.hpp b/extern/boost/boost/interprocess/sync/null_mutex.hpp deleted file mode 100644 index cf12c9e6d8a..00000000000 --- a/extern/boost/boost/interprocess/sync/null_mutex.hpp +++ /dev/null @@ -1,178 +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_NULL_MUTEX_HPP -#define BOOST_INTERPROCESS_NULL_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - - -//!\file -//!Describes null_mutex classes - -namespace boost { -namespace interprocess { - -//!Implements a mutex that simulates a mutex without doing any operation and -//!simulates a successful operation. -class null_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - null_mutex(const null_mutex&); - null_mutex &operator= (const null_mutex&); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Constructor. - //!Empty. - null_mutex() BOOST_NOEXCEPT {} - - //!Destructor. - //!Empty. - ~null_mutex(){} - - //!Simulates a mutex lock() operation. Empty function. - void lock(){} - - //!Simulates a mutex try_lock() operation. - //!Equivalent to "return true;" - bool try_lock() - { return true; } - - //!Simulates a mutex timed_lock() operation. - //!Equivalent to "return true;" - template - bool timed_lock(const TimePoint &) - { return true; } - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template - bool try_lock_until(const TimePoint &) - { return true; } - - //!Same as `timed_lock`, but this function is modeled after the - //!standard library interface. - template - bool try_lock_for(const Duration &) - { return true; } - - //!Simulates a mutex unlock() operation. - //!Empty function. - void unlock(){} - - //!Simulates a mutex lock_sharable() operation. - //!Empty function. - void lock_sharable(){} - - //!Same as `lock_sharable` but with a std-compatible interface - //! - void lock_shared() - { this->lock_sharable(); } - - //!Simulates a mutex try_lock_sharable() operation. - //!Equivalent to "return true;" - bool try_lock_sharable() - { return true; } - - //!Same as `try_lock_sharable` but with a std-compatible interface - //! - bool try_lock_shared() - { return this->try_lock_sharable(); } - - //!Simulates a mutex timed_lock_sharable() operation. - //!Equivalent to "return true;" - template - bool timed_lock_sharable(const TimePoint &) - { return true; } - - //!Simulates a mutex unlock_sharable() operation. - //!Empty function. - void unlock_sharable(){} - - //!Same as `unlock_sharable` but with a std-compatible interface - //! - void unlock_shared() - { this->unlock_sharable(); } - - //!Simulates a mutex lock_upgradable() operation. - //!Empty function. - void lock_upgradable(){} - - //!Simulates a mutex try_lock_upgradable() operation. - //!Equivalent to "return true;" - bool try_lock_upgradable() - { return true; } - - //!Simulates a mutex timed_lock_upgradable() operation. - //!Equivalent to "return true;" - template - bool timed_lock_upgradable(const TimePoint &) - { return true; } - - //!Simulates a mutex unlock_upgradable() operation. - //!Empty function. - void unlock_upgradable(){} - - //!Simulates unlock_and_lock_upgradable(). - //!Empty function. - void unlock_and_lock_upgradable(){} - - //!Simulates unlock_and_lock_sharable(). - //!Empty function. - void unlock_and_lock_sharable(){} - - //!Simulates unlock_upgradable_and_lock_sharable(). - //!Empty function. - void unlock_upgradable_and_lock_sharable(){} - - //Promotions - - //!Simulates unlock_upgradable_and_lock(). - //!Empty function. - void unlock_upgradable_and_lock(){} - - //!Simulates try_unlock_upgradable_and_lock(). - //!Equivalent to "return true;" - bool try_unlock_upgradable_and_lock() - { return true; } - - //!Simulates timed_unlock_upgradable_and_lock(). - //!Equivalent to "return true;" - template - bool timed_unlock_upgradable_and_lock(const TimePoint &) - { return true; } - - //!Simulates try_unlock_sharable_and_lock(). - //!Equivalent to "return true;" - bool try_unlock_sharable_and_lock() - { return true; } - - //!Simulates try_unlock_sharable_and_lock_upgradable(). - //!Equivalent to "return true;" - bool try_unlock_sharable_and_lock_upgradable() - { return true; } -}; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_NULL_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/condition.hpp b/extern/boost/boost/interprocess/sync/posix/condition.hpp deleted file mode 100644 index 5b3b7526617..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/condition.hpp +++ /dev/null @@ -1,218 +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_CONDITION_HPP -#define BOOST_INTERPROCESS_POSIX_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class posix_condition -{ - //Non-copyable - posix_condition(const posix_condition &); - posix_condition &operator=(const posix_condition &); - - public: - //!Constructs a posix_condition. On error throws interprocess_exception. - posix_condition(); - - //!Destroys *this - //!liberating system resources. - ~posix_condition(); - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect. - void notify_one(); - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all(); - - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock) - { - if (!lock) - throw lock_exception(); - this->do_wait(*lock.mutex()); - } - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - this->do_wait(*lock.mutex()); - } - - //!Releases the lock on the posix_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - 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(ipcdetail::is_pos_infinity(abs_time)){ - this->wait(lock); - return true; - } - return this->do_timed_wait(abs_time, *lock.mutex()); - } - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - 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(ipcdetail::is_pos_infinity(abs_time)){ - this->wait(lock, pred); - return true; - } - while (!pred()){ - if (!this->do_timed_wait(abs_time, *lock.mutex())) - return pred(); - } - return true; - } - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) - { return this->timed_wait(lock, abs_time, pred); } - - template - 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 - 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); - - template - bool do_timed_wait(const TimePoint &abs_time, posix_mutex &mut); - - private: - pthread_cond_t m_condition; -}; - -inline posix_condition::posix_condition() -{ - int res; - pthread_condattr_t cond_attr; - res = pthread_condattr_init(&cond_attr); - if(res != 0){ - throw interprocess_exception("pthread_condattr_init failed"); - } - res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); - if(res != 0){ - pthread_condattr_destroy(&cond_attr); - throw interprocess_exception(res); - } - res = pthread_cond_init(&m_condition, &cond_attr); - pthread_condattr_destroy(&cond_attr); - if(res != 0){ - throw interprocess_exception(res); - } -} - -inline posix_condition::~posix_condition() -{ - int res = 0; - res = pthread_cond_destroy(&m_condition); - BOOST_ASSERT(res == 0); (void)res; -} - -inline void posix_condition::notify_one() -{ - int res = 0; - res = pthread_cond_signal(&m_condition); - BOOST_ASSERT(res == 0); (void)res; -} - -inline void posix_condition::notify_all() -{ - int res = 0; - res = pthread_cond_broadcast(&m_condition); - BOOST_ASSERT(res == 0); (void)res; -} - -inline void posix_condition::do_wait(posix_mutex &mut) -{ - pthread_mutex_t* pmutex = &mut.m_mut; - int res = 0; - res = pthread_cond_wait(&m_condition, pmutex); - BOOST_ASSERT(res == 0); (void)res; -} - -template -inline bool posix_condition::do_timed_wait - (const TimePoint &abs_time, posix_mutex &mut) -{ - 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); - BOOST_ASSERT(res == 0 || res == ETIMEDOUT); - - return res != ETIMEDOUT; -} - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/mutex.hpp b/extern/boost/boost/interprocess/sync/posix/mutex.hpp deleted file mode 100644 index 8716f79b799..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/mutex.hpp +++ /dev/null @@ -1,188 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// Parts of the pthread code come from Boost Threads code: -// -////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2003 -// William E. Kempf -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. William E. Kempf makes no representations -// about the suitability of this software for any purpose. -// It is provided "as is" without express or implied warranty. -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP -#define BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS -# include -# include -#endif -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class posix_condition; - -class posix_mutex -{ - posix_mutex(const posix_mutex &); - posix_mutex &operator=(const posix_mutex &); - public: - - posix_mutex(); - ~posix_mutex(); - - void lock(); - bool try_lock(); - template bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - void unlock(); - - friend class posix_condition; - - private: - pthread_mutex_t m_mut; -}; - -inline posix_mutex::posix_mutex() -{ - mutexattr_wrapper mut_attr; - mutex_initializer mut(m_mut, mut_attr); - mut.release(); -} - -inline posix_mutex::~posix_mutex() -{ - int res = pthread_mutex_destroy(&m_mut); - BOOST_ASSERT(res == 0);(void)res; -} - -inline void posix_mutex::lock() -{ - 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; -} - -template -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(ipcdetail::is_pos_infinity(abs_time)){ - this->lock(); - return true; - } - 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; - - #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS - - return ipcdetail::try_based_timed_lock(*this, abs_time); - - #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS -} - -inline void posix_mutex::unlock() -{ - int res = pthread_mutex_unlock(&m_mut); - (void)res; - BOOST_ASSERT(res == 0); -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp b/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp deleted file mode 100644 index bdf3ea4dec3..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/named_mutex.hpp +++ /dev/null @@ -1,126 +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_NAMED_MUTEX_HPP -#define BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class named_condition; - -class posix_named_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - posix_named_mutex(); - posix_named_mutex(const posix_named_mutex &); - posix_named_mutex &operator=(const posix_named_mutex &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - posix_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - posix_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - posix_named_mutex(open_only_t, const char *name); - - ~posix_named_mutex(); - - void unlock(); - void lock(); - bool try_lock(); - - template - bool timed_lock(const TimePoint &abs_time); - - template - bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template - bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - static bool remove(const char *name); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - - posix_named_semaphore m_sem; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline posix_named_mutex::posix_named_mutex(create_only_t, const char *name, const permissions &perm) - : m_sem(create_only, name, 1, perm) -{} - -inline posix_named_mutex::posix_named_mutex(open_or_create_t, const char *name, const permissions &perm) - : m_sem(open_or_create, name, 1, perm) -{} - -inline posix_named_mutex::posix_named_mutex(open_only_t, const char *name) - : m_sem(open_only, name) -{} - -inline void posix_named_mutex::dont_close_on_destruction() -{ interprocess_tester::dont_close_on_destruction(m_sem); } - -inline posix_named_mutex::~posix_named_mutex() -{} - -inline void posix_named_mutex::lock() -{ m_sem.wait(); } - -inline void posix_named_mutex::unlock() -{ m_sem.post(); } - -inline bool posix_named_mutex::try_lock() -{ return m_sem.try_wait(); } - -template -inline bool posix_named_mutex::timed_lock(const TimePoint &abs_time) -{ return m_sem.timed_wait(abs_time); } - -inline bool posix_named_mutex::remove(const char *name) -{ return posix_named_semaphore::remove(name); } - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_POSIX_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp deleted file mode 100644 index 410e76f9a4f..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/named_semaphore.hpp +++ /dev/null @@ -1,89 +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_NAMED_CONDITION_HPP -#define BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -namespace ipcdetail { - -class posix_named_semaphore -{ - posix_named_semaphore(); - posix_named_semaphore(const posix_named_semaphore&); - posix_named_semaphore &operator= (const posix_named_semaphore &); - - public: - posix_named_semaphore - (create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()) - { semaphore_open(mp_sem, DoCreate, name, initialCount, perm); } - - posix_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()) - { semaphore_open(mp_sem, DoOpenOrCreate, name, initialCount, perm); } - - posix_named_semaphore(open_only_t, const char *name) - { semaphore_open(mp_sem, DoOpen, name); } - - ~posix_named_semaphore() - { - if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED) - semaphore_close(mp_sem); - } - - void post() - { semaphore_post(mp_sem); } - - void wait() - { semaphore_wait(mp_sem); } - - bool try_wait() - { return semaphore_try_wait(mp_sem); } - - template - bool timed_wait(const TimePoint &abs_time) - { return semaphore_timed_wait(mp_sem, abs_time); } - - static bool remove(const char *name) - { return semaphore_unlink(name); } - - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction() - { mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; } - - sem_t *mp_sem; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_POSIX_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp b/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp deleted file mode 100644 index f247d5e5961..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/pthread_helpers.hpp +++ /dev/null @@ -1,176 +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_PTHREAD_HELPERS_HPP -#define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - - #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED - - //!Makes pthread_mutexattr_t cleanup easy when using exceptions - struct mutexattr_wrapper - { - //!Constructor - mutexattr_wrapper(bool recursive = false) - { - 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 ) - #ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES - || pthread_mutexattr_setrobust(&m_attr, PTHREAD_MUTEX_ROBUST) != 0 - #endif - ) - throw interprocess_exception("pthread_mutexattr_xxxx failed"); - } - - //!Destructor - ~mutexattr_wrapper() { pthread_mutexattr_destroy(&m_attr); } - - //!This allows using mutexattr_wrapper as pthread_mutexattr_t - operator pthread_mutexattr_t&() { return m_attr; } - - pthread_mutexattr_t m_attr; - }; - - //!Makes pthread_condattr_t cleanup easy when using exceptions - struct condattr_wrapper - { - //!Constructor - condattr_wrapper() - { - if(pthread_condattr_init(&m_attr)!=0 || - pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) - throw interprocess_exception("pthread_condattr_xxxx failed"); - } - - //!Destructor - ~condattr_wrapper() { pthread_condattr_destroy(&m_attr); } - - //!This allows using condattr_wrapper as pthread_condattr_t - operator pthread_condattr_t&(){ return m_attr; } - - pthread_condattr_t m_attr; - }; - - //!Makes initialized pthread_mutex_t cleanup easy when using exceptions - class mutex_initializer - { - public: - //!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex - mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr) - : mp_mut(&mut) - { - if(pthread_mutex_init(mp_mut, &mut_attr) != 0) - throw interprocess_exception("pthread_mutex_init failed"); - } - - ~mutex_initializer() { if(mp_mut) pthread_mutex_destroy(mp_mut); } - - void release() {mp_mut = 0; } - - private: - pthread_mutex_t *mp_mut; - }; - - //!Makes initialized pthread_cond_t cleanup easy when using exceptions - class condition_initializer - { - public: - condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) - : mp_cond(&cond) - { - if(pthread_cond_init(mp_cond, &cond_attr)!= 0) - throw interprocess_exception("pthread_cond_init failed"); - } - - ~condition_initializer() { if(mp_cond) pthread_cond_destroy(mp_cond); } - - void release() { mp_cond = 0; } - - private: - pthread_cond_t *mp_cond; - }; - - #endif // #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED - - #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) - - //!Makes pthread_barrierattr_t cleanup easy when using exceptions - struct barrierattr_wrapper - { - //!Constructor - barrierattr_wrapper() - { - if(pthread_barrierattr_init(&m_attr)!=0 || - pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) - throw interprocess_exception("pthread_barrierattr_xxx failed"); - } - - //!Destructor - ~barrierattr_wrapper() { pthread_barrierattr_destroy(&m_attr); } - - //!This allows using mutexattr_wrapper as pthread_barrierattr_t - operator pthread_barrierattr_t&() { return m_attr; } - - pthread_barrierattr_t m_attr; - }; - - //!Makes initialized pthread_barrier_t cleanup easy when using exceptions - class barrier_initializer - { - public: - //!Constructor. Takes barrier attributes to initialize the barrier - barrier_initializer(pthread_barrier_t &mut, - pthread_barrierattr_t &mut_attr, - unsigned int count) - : mp_barrier(&mut) - { - if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0) - throw interprocess_exception("pthread_barrier_init failed"); - } - - ~barrier_initializer() { if(mp_barrier) pthread_barrier_destroy(mp_barrier); } - - void release() {mp_barrier = 0; } - - private: - pthread_barrier_t *mp_barrier; - }; - - #endif //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) - -}//namespace ipcdetail - -}//namespace interprocess - -}//namespace boost - -#include - -#endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp deleted file mode 100644 index 20e654e3ddc..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/recursive_mutex.hpp +++ /dev/null @@ -1,175 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// Parts of the pthread code come from Boost Threads code: -// -////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2003 -// William E. Kempf -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. William E. Kempf makes no representations -// about the suitability of this software for any purpose. -// It is provided "as is" without express or implied warranty. -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS -# include -# include -#endif -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class posix_recursive_mutex -{ - posix_recursive_mutex(const posix_recursive_mutex &); - posix_recursive_mutex &operator=(const posix_recursive_mutex &); - public: - - posix_recursive_mutex(); - ~posix_recursive_mutex(); - - void lock(); - bool try_lock(); - template bool timed_lock(const TimePoint &abs_time); - void unlock(); - - private: - pthread_mutex_t m_mut; -}; - -inline posix_recursive_mutex::posix_recursive_mutex() -{ - mutexattr_wrapper mut_attr(true); - mutex_initializer mut(m_mut, mut_attr); - mut.release(); -} - -inline posix_recursive_mutex::~posix_recursive_mutex() -{ - int res = pthread_mutex_destroy(&m_mut); - BOOST_ASSERT(res == 0);(void)res; -} - -inline void posix_recursive_mutex::lock() -{ - 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_recursive_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); -} - -template -inline bool posix_recursive_mutex::timed_lock(const TimePoint &abs_time) -{ - #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS - //Posix does not support infinity absolute time so handle it here - if(ipcdetail::is_pos_infinity(abs_time)){ - this->lock(); - return true; - } - - 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; - - #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS - - return ipcdetail::try_based_timed_lock(*this, abs_time); - - #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS -} - -inline void posix_recursive_mutex::unlock() -{ - int res = 0; - res = pthread_mutex_unlock(&m_mut); - BOOST_ASSERT(res == 0); (void)res; -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POSIX_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/semaphore.hpp b/extern/boost/boost/interprocess/sync/posix/semaphore.hpp deleted file mode 100644 index bf64d430da7..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/semaphore.hpp +++ /dev/null @@ -1,67 +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_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class posix_semaphore -{ - posix_semaphore(); - posix_semaphore(const posix_semaphore&); - posix_semaphore &operator= (const posix_semaphore &); - - public: - posix_semaphore(unsigned int initialCount) - { semaphore_init(&m_sem, initialCount); } - - ~posix_semaphore() - { semaphore_destroy(&m_sem); } - - void post() - { semaphore_post(&m_sem); } - - void wait() - { semaphore_wait(&m_sem); } - - bool try_wait() - { return semaphore_try_wait(&m_sem); } - - template - bool timed_wait(const TimePoint &abs_time) - { return semaphore_timed_wait(&m_sem, abs_time); } - - private: - sem_t m_sem; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp deleted file mode 100644 index c77397ae775..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ /dev/null @@ -1,254 +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_SEMAPHORE_WRAPPER_HPP -#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -#include //O_CREAT, O_*... -#include //close -#include //std::string -#include //sem_* family, SEM_VALUE_MAX -#include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, -#include - -#ifdef SEM_FAILED -#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(SEM_FAILED)) -#else -#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(-1)) -#endif - -#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS -#include -#else -#include -#include -#include -#endif - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES - -inline bool semaphore_open - (sem_t *&handle, create_enum_t type, const char *origname, - unsigned int count = 0, const permissions &perm = permissions()) -{ - std::string name; - #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES - add_leading_slash(origname, name); - #else - create_shared_dir_cleaning_old_and_get_filepath(origname, name); - #endif - - //Create new mapping - int oflag = 0; - switch(type){ - case DoOpen: - { - //No addition - handle = ::sem_open(name.c_str(), oflag); - } - break; - case DoOpenOrCreate: - case DoCreate: - { - while(1){ - oflag = (O_CREAT | O_EXCL); - handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count); - if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){ - //We can't change semaphore permissions! - //::fchmod(handle, perm.get_permissions()); - break; - } - else if(errno == EEXIST && type == DoOpenOrCreate){ - oflag = 0; - if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED - || (errno != ENOENT) ){ - break; - } - } - else{ - break; - } - } - } - break; - default: - { - error_info err(other_error); - throw interprocess_exception(err); - } - } - - //Check for error - if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){ - throw interprocess_exception(error_info(errno)); - } - - return true; -} - -inline void semaphore_close(sem_t *handle) -{ - int ret = sem_close(handle); - if(ret != 0){ - BOOST_ASSERT(0); - } -} - -inline bool semaphore_unlink(const char *semname) -{ - BOOST_TRY{ - std::string sem_str; - #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES - add_leading_slash(semname, sem_str); - #else - shared_filepath(semname, sem_str); - #endif - return 0 == sem_unlink(sem_str.c_str()); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END -} - -#endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES - -#ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES - -inline void semaphore_init(sem_t *handle, unsigned int initialCount) -{ - int ret = sem_init(handle, 1, initialCount); - //According to SUSV3 version 2003 edition, the return value of a successful - //sem_init call is not defined, but -1 is returned on failure. - //In the future, a successful call might be required to return 0. - if(ret == -1){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } -} - -inline void semaphore_destroy(sem_t *handle) -{ - int ret = sem_destroy(handle); - if(ret != 0){ - BOOST_ASSERT(0); - } -} - -#endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES - -inline void semaphore_post(sem_t *handle) -{ - int ret = sem_post(handle); - if(ret != 0){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } -} - -inline void semaphore_wait(sem_t *handle) -{ - int ret = sem_wait(handle); - if(ret != 0){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } -} - -inline bool semaphore_try_wait(sem_t *handle) -{ - int res = sem_trywait(handle); - if(res == 0) - return true; - if(system_error_code() == EAGAIN){ - return false; - } - error_info err = system_error_code(); - throw interprocess_exception(err); -} - -#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS - -struct semaphore_wrapper_try_wrapper -{ - explicit semaphore_wrapper_try_wrapper(sem_t *handle) - : m_handle(handle) - {} - - void wait() - { semaphore_wait(m_handle); } - - bool try_wait() - { return semaphore_try_wait(m_handle); } - - private: - sem_t *m_handle; -}; - -#endif - -template -inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time) -{ - #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS - //Posix does not support infinity absolute time so handle it here - if(ipcdetail::is_pos_infinity(abs_time)){ - semaphore_wait(handle); - return true; - } - - timespec tspec = timepoint_to_timespec(abs_time); - for (;;){ - int res = sem_timedwait(handle, &tspec); - if(res == 0) - return true; - if (res > 0){ - //buggy glibc, copy the returned error code to errno - errno = res; - } - if(system_error_code() == ETIMEDOUT){ - return false; - } - error_info err = system_error_code(); - throw interprocess_exception(err); - } - return false; - #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS - - semaphore_wrapper_try_wrapper swtw(handle); - ipcdetail::lock_to_wait lw(swtw); - return ipcdetail::try_based_timed_lock(lw, abs_time); - - #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP diff --git a/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp b/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp deleted file mode 100644 index 6f5d795cc2d..00000000000 --- a/extern/boost/boost/interprocess/sync/posix/timepoint_to_timespec.hpp +++ /dev/null @@ -1,91 +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_TIMEPOINT_TO_TIMESPEC_HPP -#define BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { - -namespace interprocess { - -namespace ipcdetail { - -template -inline timespec timepoint_to_timespec ( const TimePoint &tm - , typename enable_if_ptime::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(duration.total_seconds()); - ts.tv_nsec = static_cast(duration.total_nanoseconds() % 1000000000); - return ts; -} - -inline timespec timepoint_to_timespec (const ustime &tm) -{ - timespec ts; - const boost::uint64_t micros = tm.get_microsecs(); - ts.tv_sec = static_cast(micros /1000000u); - ts.tv_nsec = static_cast((micros%1000000u)*1000u); - return ts; -} - -template -inline timespec timepoint_to_timespec ( const TimePoint &tm - , typename enable_if_time_point::type * = 0) -{ - typedef typename TimePoint::duration duration_t; - duration_t d(tm.time_since_epoch()); - - timespec ts; - const typename duration_t::rep cnt = d.count(); - - BOOST_IF_CONSTEXPR(duration_t::period::num == 1 && duration_t::period::den == 1000000000) - { - - ts.tv_sec = static_cast(cnt /duration_t::period::den); - ts.tv_nsec = static_cast(cnt%duration_t::period::den); - } - else - { - const double factor = double(duration_t::period::num)/double(duration_t::period::den); - const double res = double(cnt)*factor; - ts.tv_sec = static_cast(res); - ts.tv_nsec = static_cast(1000000000.0*(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/extern/boost/boost/interprocess/sync/sharable_lock.hpp b/extern/boost/boost/interprocess/sync/sharable_lock.hpp deleted file mode 100644 index 7bdcd97b76d..00000000000 --- a/extern/boost/boost/interprocess/sync/sharable_lock.hpp +++ /dev/null @@ -1,351 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// This interface is inspired by Howard Hinnant's lock proposal. -// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP -#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes the upgradable_lock class that serves to acquire the upgradable -//!lock of a mutex. - -namespace boost { -namespace interprocess { - - -//!sharable_lock is meant to carry out the tasks for sharable-locking -//!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking -//!(recursive or not) for the Mutex. The Mutex need not supply all of this -//!functionality. If the client of sharable_lock does not use functionality which -//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among -//!sharable_locks, and a single upgradable_lock. sharable_lock does not support -//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock, -//!upgradable_lock and scoped_lock via transfer_lock syntax.*/ -template -class sharable_lock -{ - public: - typedef SharableMutex mutex_type; - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef sharable_lock this_type; - explicit sharable_lock(scoped_lock&); - typedef bool this_type::*unspecified_bool_type; - BOOST_MOVABLE_BUT_NOT_COPYABLE(sharable_lock) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Effects: Default constructs a sharable_lock. - //!Postconditions: owns() == false and mutex() == 0. - sharable_lock() BOOST_NOEXCEPT - : mp_mutex(0), m_locked(false) - {} - - //!Effects: m.lock_sharable(). - //!Postconditions: owns() == true and mutex() == &m. - //!Notes: The constructor will take sharable-ownership of the mutex. If - //! another thread already owns the mutex with exclusive ownership - //! (scoped_lock), this thread will block until the mutex is released. - //! If another thread owns the mutex with sharable or upgradable ownership, - //! then no blocking will occur. Whether or not this constructor handles - //! recursive locking depends upon the mutex. - explicit sharable_lock(mutex_type& m) - : mp_mutex(&m), m_locked(false) - { mp_mutex->lock_sharable(); m_locked = true; } - - //!Postconditions: owns() == false, and mutex() == &m. - //!Notes: The constructor will not take ownership of the mutex. There is no effect - //! required on the referenced mutex. - sharable_lock(mutex_type& m, defer_lock_type) - : mp_mutex(&m), m_locked(false) - {} - - //!Postconditions: owns() == true, and mutex() == &m. - //!Notes: The constructor will suppose that the mutex is already sharable - //! locked. There is no effect required on the referenced mutex. - sharable_lock(mutex_type& m, accept_ownership_type) - : mp_mutex(&m), m_locked(true) - {} - - //!Effects: m.try_lock_sharable() - //!Postconditions: mutex() == &m. owns() == the return value of the - //! m.try_lock_sharable() executed within the constructor. - //!Notes: The constructor will take sharable-ownership of the mutex if it - //! can do so without waiting. Whether or not this constructor handles - //! recursive locking depends upon the mutex. If the mutex_type does not - //! support try_lock_sharable, this constructor will fail at compile - //! time if instantiated, but otherwise have no effect. - sharable_lock(mutex_type& m, try_to_lock_type) - : mp_mutex(&m), m_locked(false) - { m_locked = mp_mutex->try_lock_sharable(); } - - //!Effects: m.timed_lock_sharable(abs_time) - //!Postconditions: mutex() == &m. owns() == the return value of the - //! m.timed_lock_sharable() executed within the constructor. - //!Notes: The constructor will take sharable-ownership of the mutex if it - //! can do so within the time specified. Whether or not this constructor - //! handles recursive locking depends upon the mutex. If the mutex_type - //! does not support timed_lock_sharable, this constructor will fail at - //! compile time if instantiated, but otherwise have no effect. - template - sharable_lock(mutex_type& m, const TimePoint& abs_time) - : mp_mutex(&m), m_locked(false) - { m_locked = mp_mutex->timed_lock_sharable(abs_time); } - - //!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns() - //! before the construction. upgr.owns() == false after the construction. - //!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this - //! sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then - //! neither will this sharable_lock. Only a moved sharable_lock's will match this - //! signature. An non-moved sharable_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. - sharable_lock(BOOST_RV_REF(sharable_lock) upgr) BOOST_NOEXCEPT - : mp_mutex(0), m_locked(upgr.owns()) - { mp_mutex = upgr.release(); } - - //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the - //! referenced mutex. - //!Postconditions: mutex() == the value upgr.mutex() had before the construction. - //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction. - //! upgr.owns() == false after the construction. - //!Notes: If upgr is locked, this constructor will lock this sharable_lock while - //! unlocking upgr. Only a moved sharable_lock's will match this - //! signature. An non-moved upgradable_lock can be moved with the expression: - //! "boost::move(lock);".*/ - template - sharable_lock(BOOST_RV_REF(upgradable_lock) upgr - , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) - : mp_mutex(0), m_locked(false) - { - upgradable_lock &u_lock = upgr; - if(u_lock.owns()){ - u_lock.mutex()->unlock_upgradable_and_lock_sharable(); - m_locked = true; - } - mp_mutex = u_lock.release(); - } - - //!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the - //! referenced mutex. - //!Postconditions: mutex() == the value scop.mutex() had before the construction. - //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the - //! construction, scop.owns() == false. - //!Notes: If scop is locked, this constructor will transfer the exclusive ownership - //! to a sharable-ownership of this sharable_lock. - //! Only a moved scoped_lock's will match this - //! signature. An non-moved scoped_lock can be moved with the expression: - //! "boost::move(lock);". - template - sharable_lock(BOOST_RV_REF(scoped_lock) scop - , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) - : mp_mutex(0), m_locked(false) - { - scoped_lock &e_lock = scop; - if(e_lock.owns()){ - e_lock.mutex()->unlock_and_lock_sharable(); - m_locked = true; - } - mp_mutex = e_lock.release(); - } - - //!Effects: if (owns()) mp_mutex->unlock_sharable(). - //!Notes: The destructor behavior ensures that the mutex lock is not leaked. - ~sharable_lock() - { - BOOST_TRY{ - if(m_locked && mp_mutex) mp_mutex->unlock_sharable(); - } - BOOST_CATCH(...){} BOOST_CATCH_END - } - - //!Effects: If owns() before the call, then unlock_sharable() is called on mutex(). - //! *this gets the state of upgr and upgr gets set to a default constructed state. - //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex - //! before the assignment. In this case, this will own the mutex after the assignment - //! (and upgr will not), but the mutex's lock count will be decremented by one. - sharable_lock &operator=(BOOST_RV_REF(sharable_lock) upgr) - { - if(this->owns()) - this->unlock(); - m_locked = upgr.owns(); - mp_mutex = upgr.release(); - return *this; - } - - //!Effects: If mutex() == 0 or already locked, throws a lock_exception() - //! exception. Calls lock_sharable() on the referenced mutex. - //!Postconditions: owns() == true. - //!Notes: The sharable_lock changes from a state of not owning the - //! mutex, to owning the mutex, blocking if necessary. - void lock() - { - if(!mp_mutex || m_locked) - throw lock_exception(); - mp_mutex->lock_sharable(); - m_locked = true; - } - - //!Effects: If mutex() == 0 or already locked, throws a lock_exception() - //! exception. Calls try_lock_sharable() on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->try_lock_sharable(). - //!Notes: The sharable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if blocking was not required. If the - //! mutex_type does not support try_lock_sharable(), this function will - //! fail at compile time if instantiated, but otherwise have no effect. - bool try_lock() - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->try_lock_sharable(); - return m_locked; - } - - //!Effects: If mutex() == 0 or already locked, throws a lock_exception() - //! exception. Calls timed_lock_sharable(abs_time) on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->timed_lock_sharable(elps_time). - //!Notes: The sharable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if it can obtain ownership within the - //! specified time interval. If the mutex_type does not support - //! timed_lock_sharable(), this function will fail at compile time if - //! instantiated, but otherwise have no effect. - template - bool timed_lock(const TimePoint& abs_time) - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->timed_lock_sharable(abs_time); - return m_locked; - } - - //!Effects: If mutex() == 0 or already locked, throws a lock_exception() - //! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->timed_lock_sharable(elps_time). - //!Notes: The sharable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if it can obtain ownership within the - //! specified time interval. If the mutex_type does not support - //! timed_lock_sharable(), this function will fail at compile time if - //! instantiated, but otherwise have no effect. - //! - //!Note: Similar to timed_lock, but with a std-like interface - template - bool try_lock_until(const TimePoint& abs_time) - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->try_lock_shared_until(abs_time); - return m_locked; - } - - //!Effects: If mutex() == 0 or already locked, throws a lock_exception() - //! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->timed_lock_sharable(elps_time). - //!Notes: The sharable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if it can obtain ownership within the - //! specified time interval. If the mutex_type does not support - //! timed_lock_sharable(), this function will fail at compile time if - //! instantiated, but otherwise have no effect. - //! - //!Note: Similar to timed_lock, but with a std-like interface - template - bool try_lock_for(const Duration& dur) - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->try_lock_shared_for(dur); - return m_locked; - } - - //!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception. - //! Calls unlock_sharable() on the referenced mutex. - //!Postconditions: owns() == false. - //!Notes: The sharable_lock changes from a state of owning the mutex, to - //! not owning the mutex. - void unlock() - { - if(!mp_mutex || !m_locked) - throw lock_exception(); - mp_mutex->unlock_sharable(); - m_locked = false; - } - - //!Effects: Returns true if this scoped_lock has - //!acquired the referenced mutex. - bool owns() const BOOST_NOEXCEPT - { return m_locked && mp_mutex; } - - //!Conversion to bool. - //!Returns owns(). - 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 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() BOOST_NOEXCEPT - { - mutex_type *mut = mp_mutex; - mp_mutex = 0; - m_locked = false; - return mut; - } - - //!Effects: Swaps state with moved lock. - //!Throws: Nothing. - void swap(sharable_lock &other) BOOST_NOEXCEPT - { - (simple_swap)(mp_mutex, other.mp_mutex); - (simple_swap)(m_locked, other.m_locked); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - mutex_type *mp_mutex; - bool m_locked; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} // namespace interprocess -} // namespace boost - -#include - -#endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_condition.hpp b/extern/boost/boost/interprocess/sync/shm/named_condition.hpp deleted file mode 100644 index c9e7550cf38..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_condition.hpp +++ /dev/null @@ -1,348 +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_SHM_NAMED_CONDITION_HPP -#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - #include - #include - #include -#else - #include -#endif - - -//!\file -//!Describes process-shared variables interprocess_condition class - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -class interprocess_tester; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//! A global condition variable that can be created by name. -//! This condition variable is designed to work with named_mutex and -//! can't be placed in shared memory or memory mapped files. -class shm_named_condition -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - shm_named_condition(); - shm_named_condition(const shm_named_condition &); - shm_named_condition &operator=(const shm_named_condition &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - shm_named_condition(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!shm_named_condition(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!shm_named_condition(open_only_t, ... ) - //!Does not throw - shm_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - shm_named_condition(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!shm_named_condition(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!shm_named_condition(open_only_t, ... ) - //!Does not throw - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - //! - //!Note: This function is only available on operating systems with - //! native wchar_t APIs (e.g. Windows). - shm_named_condition(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~shm_named_condition(); - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one(); - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all(); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock); - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time); - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred); - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - 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 - 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 - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } - - //!Erases a named condition 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 named condition 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) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - class internal_condition_members - { - public: - typedef interprocess_mutex mutex_type; - typedef interprocess_condition condvar_type; - - condvar_type& get_condvar() { return m_cond; } - mutex_type& get_mutex() { return m_mtx; } - - private: - mutex_type m_mtx; - condvar_type m_cond; - }; - - typedef ipcdetail::condition_any_wrapper internal_condition; - #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - typedef interprocess_condition internal_condition; - #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - - internal_condition &internal_cond() - { return *static_cast(m_shmem.get_user_address()); } - - friend class boost::interprocess::ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - - template friend class boost::interprocess::ipcdetail::named_creation_functor; - typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline shm_named_condition::~shm_named_condition() -{} - -inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate) - ,perm) -{} - -inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate) - ,perm) -{} - -inline shm_named_condition::shm_named_condition(open_only_t, const char *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline shm_named_condition::shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate) - ,perm) -{} - -inline shm_named_condition::shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate) - ,perm) -{} - -inline shm_named_condition::shm_named_condition(open_only_t, const wchar_t *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen)) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void shm_named_condition::dont_close_on_destruction() -{ interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline void shm_named_condition::notify_one() -{ this->internal_cond().notify_one(); } - -inline void shm_named_condition::notify_all() -{ this->internal_cond().notify_all(); } - -template -inline void shm_named_condition::wait(L& lock) -{ this->internal_cond().wait(lock); } - -template -inline void shm_named_condition::wait(L& lock, Pr pred) -{ this->internal_cond().wait(lock, pred); } - -template -inline bool shm_named_condition::timed_wait - (L& lock, const TimePoint &abs_time) -{ return this->internal_cond().timed_wait(lock, abs_time); } - -template -inline bool shm_named_condition::timed_wait - (L& lock, const TimePoint &abs_time, Pr pred) -{ return this->internal_cond().timed_wait(lock, abs_time, pred); } - -inline bool shm_named_condition::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool shm_named_condition::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif - - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp deleted file mode 100644 index 31f621313ba..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_condition_any.hpp +++ /dev/null @@ -1,226 +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_SHM_NAMED_CONDITION_ANY_HPP -#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes process-shared variables interprocess_condition class - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -class interprocess_tester; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -//! A global condition variable that can be created by name. -//! This condition variable is designed to work with named_mutex and -//! can't be placed in shared memory or memory mapped files. -class shm_named_condition_any -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - shm_named_condition_any(); - shm_named_condition_any(const shm_named_condition_any &); - shm_named_condition_any &operator=(const shm_named_condition_any &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - //!Creates a global condition with a name. - //!If the condition can't be created throws interprocess_exception - template - shm_named_condition_any(create_only_t, const CharT *name, const permissions &perm = permissions()) - : m_shmem (create_only_t() - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate) - ,perm) - {} - - //!Opens or creates a global condition with a name. - //!If the condition is created, this call is equivalent to - //!shm_named_condition_any(create_only_t, ... ) - //!If the condition is already created, this call is equivalent - //!shm_named_condition_any(open_only_t, ... ) - //!Does not throw - template - shm_named_condition_any(open_or_create_t, const CharT *name, const permissions &perm = permissions()) - : m_shmem (open_or_create_t() - ,name - ,sizeof(internal_condition) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate) - ,perm) - {} - - //!Opens a global condition with a name if that condition is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - template - shm_named_condition_any(open_only_t, const CharT *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen)) - {} - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~shm_named_condition_any() - {} - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one() - { this->internal_cond().notify_one(); } - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all() - { this->internal_cond().notify_all(); } - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock) - { this->internal_cond().wait(lock); } - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred) - { this->internal_cond().wait(lock, pred); } - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!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 - bool timed_wait(L& lock, const TimePoint &abs_time) - { return this->internal_cond().timed_wait(lock, abs_time); } - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { return this->internal_cond().timed_wait(lock, abs_time, pred); } - - //!Same as `timed_wait`, but this function is modeled after the - //!standard library interface. - template - 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 - 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 - 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 - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } - - //!Erases a named condition from the system. - //!Returns false on error. Never throws. - template - static bool remove(const CharT *name) - { return shared_memory_object::remove(name); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - class internal_condition_members - { - public: - typedef interprocess_mutex mutex_type; - typedef interprocess_condition condvar_type; - - condvar_type& get_condvar() { return m_cond; } - mutex_type& get_mutex() { return m_mtx; } - - private: - mutex_type m_mtx; - condvar_type m_cond; - }; - - typedef ipcdetail::condition_any_wrapper internal_condition; - - internal_condition &internal_cond() - { return *static_cast(m_shmem.get_user_address()); } - - friend class boost::interprocess::ipcdetail::interprocess_tester; - void dont_close_on_destruction() - { interprocess_tester::dont_close_on_destruction(m_shmem); } - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - - template friend class boost::interprocess::ipcdetail::named_creation_functor; - typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp b/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp deleted file mode 100644 index 137a1a8ea7d..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_creation_functor.hpp +++ /dev/null @@ -1,81 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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_SYNC_NAMED_CREATION_FUNCTOR_HPP -#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -struct named_creation_functor_no_arg{}; - -template -class named_creation_functor -{ - typedef named_creation_functor_no_arg no_arg_t; - public: - named_creation_functor(create_enum_t type, Arg arg = Arg()) - : m_creation_type(type), m_arg(arg){} - - template - void construct(void *address, typename enable_if_c::value>::type * = 0) const - { ::new(address, boost_container_new_t())T; } - - template - void construct(void *address, typename enable_if_c::value>::type * = 0) const - { ::new(address, boost_container_new_t())T(m_arg); } - - bool operator()(void *address, std::size_t, bool created) const - { - switch(m_creation_type){ - case DoOpen: - return true; - break; - case DoCreate: - case DoOpenOrCreate: - if(created){ - construct(address); - } - return true; - break; - - default: - return false; - break; - } - } - - static std::size_t get_min_size() - { return sizeof(T); } - - private: - create_enum_t m_creation_type; - Arg m_arg; -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#endif //BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp deleted file mode 100644 index 123f26ace2d..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_mutex.hpp +++ /dev/null @@ -1,259 +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_SHM_NAMED_MUTEX_HPP -#define BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -//!\file -//!Describes a named mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class named_condition; - -//!A mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named mutex. -class shm_named_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - shm_named_mutex(); - shm_named_mutex(const shm_named_mutex &); - shm_named_mutex &operator=(const shm_named_mutex &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Creates a global interprocess_mutex with a name. - //!Throws interprocess_exception on error. - shm_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global mutex with a name. - //!If the mutex is created, this call is equivalent to - //!shm_named_mutex(create_only_t, ... ) - //!If the mutex is already created, this call is equivalent - //!shm_named_mutex(open_only_t, ... ) - //!Does not throw - shm_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global mutex with a name if that mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - shm_named_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global interprocess_mutex with a name. - //!Throws interprocess_exception on error. - shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global mutex with a name. - //!If the mutex is created, this call is equivalent to - //!shm_named_mutex(create_only_t, ... ) - //!If the mutex is already created, this call is equivalent - //!shm_named_mutex(open_only_t, ... ) - //!Does not throw - shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global mutex with a name if that mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - shm_named_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~shm_named_mutex(); - - //!Unlocks a previously locked - //!interprocess_mutex. - void unlock(); - - //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked. - //!Throws interprocess_exception if a severe error is found - void lock(); - - //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex - //!is already locked, returns true when success. - //!Throws interprocess_exception if a severe error is found - bool try_lock(); - - //!Tries to lock the interprocess_mutex until time abs_time, - //!Returns false when timeout expires, returns true when locks. - //!Throws interprocess_exception if a severe error is found - template - bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - //!Erases a named mutex 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 named mutex from the system. - //!Returns false on error. Never throws. - static bool remove(const wchar_t *name); - - #endif - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - typedef interprocess_mutex internal_mutex_type; - interprocess_mutex &internal_mutex() - { return *static_cast(m_shmem.get_user_address()); } - - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void shm_named_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline shm_named_mutex::~shm_named_mutex() -{} - -inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only_t() - ,name - ,sizeof(interprocess_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create_t() - ,name - ,sizeof(interprocess_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline shm_named_mutex::shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm) - : m_shmem (create_only_t() - ,name - ,sizeof(interprocess_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline shm_named_mutex::shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_shmem (open_or_create_t() - ,name - ,sizeof(interprocess_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline shm_named_mutex::shm_named_mutex(open_only_t, const wchar_t *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void shm_named_mutex::lock() -{ this->internal_mutex().lock(); } - -inline void shm_named_mutex::unlock() -{ this->internal_mutex().unlock(); } - -inline bool shm_named_mutex::try_lock() -{ return this->internal_mutex().try_lock(); } - -template -inline bool shm_named_mutex::timed_lock(const TimePoint &abs_time) -{ return this->internal_mutex().timed_lock(abs_time); } - -inline bool shm_named_mutex::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool shm_named_mutex::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_SHM_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp deleted file mode 100644 index 437588ea2b8..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ /dev/null @@ -1,249 +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_SHM_NAMED_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a named shm_named_recursive_mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -class interprocess_tester; -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -class shm_named_recursive_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - shm_named_recursive_mutex(); - shm_named_recursive_mutex(const shm_named_recursive_mutex &); - shm_named_recursive_mutex &operator=(const shm_named_recursive_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global recursive_mutex with a name. - //!If the recursive_mutex can't be created throws interprocess_exception - shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global recursive_mutex with a name. - //!If the recursive_mutex is created, this call is equivalent to - //!shm_named_recursive_mutex(create_only_t, ... ) - //!If the recursive_mutex is already created, this call is equivalent - //!shm_named_recursive_mutex(open_only_t, ... ) - //!Does not throw - shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global recursive_mutex with a name if that recursive_mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - shm_named_recursive_mutex(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Creates a global recursive_mutex with a name. - //!If the recursive_mutex can't be created throws interprocess_exception - shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens or creates a global recursive_mutex with a name. - //!If the recursive_mutex is created, this call is equivalent to - //!shm_named_recursive_mutex(create_only_t, ... ) - //!If the recursive_mutex is already created, this call is equivalent - //!shm_named_recursive_mutex(open_only_t, ... ) - //!Does not throw - shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - //!Opens a global recursive_mutex with a name if that recursive_mutex is previously - //!created. If it is not previously created this function throws - //!interprocess_exception. - shm_named_recursive_mutex(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~shm_named_recursive_mutex(); - - //!Unlocks a previously locked - //!shm_named_recursive_mutex. - void unlock(); - - //!Locks shm_named_recursive_mutex, sleeps when shm_named_recursive_mutex is already locked. - //!Throws interprocess_exception if a severe error is found. - void lock(); - - //!Tries to lock the shm_named_recursive_mutex, returns false when shm_named_recursive_mutex - //!is already locked, returns true when success. - //!Throws interprocess_exception if a severe error is found. - bool try_lock(); - - //!Tries to lock the shm_named_recursive_mutex until time abs_time, - //!Returns false when timeout expires, returns true when locks. - //!Throws interprocess_exception if a severe error is found - template - bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - //!Erases a named recursive mutex - //!from the system - static bool remove(const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //!Erases a named recursive mutex - //!from the system - static bool remove(const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - - interprocess_recursive_mutex *mutex() const - { return static_cast(m_shmem.get_user_address()); } - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline shm_named_recursive_mutex::~shm_named_recursive_mutex() -{} - -inline void shm_named_recursive_mutex::dont_close_on_destruction() -{ interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only_t() - ,name - ,sizeof(interprocess_recursive_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate) - ,perm) -{} - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create_t() - ,name - ,sizeof(interprocess_recursive_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate) - ,perm) -{} - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const char *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) - : m_shmem (create_only_t() - ,name - ,sizeof(interprocess_recursive_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate) - ,perm) -{} - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) - : m_shmem (open_or_create_t() - ,name - ,sizeof(interprocess_recursive_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate) - ,perm) -{} - -inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const wchar_t *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen)) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void shm_named_recursive_mutex::lock() -{ this->mutex()->lock(); } - -inline void shm_named_recursive_mutex::unlock() -{ this->mutex()->unlock(); } - -inline bool shm_named_recursive_mutex::try_lock() -{ return this->mutex()->try_lock(); } - -template -inline bool shm_named_recursive_mutex::timed_lock(const TimePoint &abs_time) -{ return this->mutex()->timed_lock(abs_time); } - -inline bool shm_named_recursive_mutex::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool shm_named_recursive_mutex::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_SHM_NAMED_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp deleted file mode 100644 index 9977888bd89..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_semaphore.hpp +++ /dev/null @@ -1,198 +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_SHM_NAMED_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class shm_named_semaphore -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - shm_named_semaphore(); - shm_named_semaphore(const shm_named_semaphore &); - shm_named_semaphore &operator=(const shm_named_semaphore &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - shm_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - shm_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - shm_named_semaphore(open_only_t, const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - shm_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - shm_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - shm_named_semaphore(open_only_t, const wchar_t *name); - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - ~shm_named_semaphore(); - - void post(); - void wait(); - bool try_wait(); - template bool timed_wait(const TimePoint &abs_time); - - static bool remove(const char *name); - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - static bool remove(const wchar_t *name); - - #endif - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - - interprocess_semaphore *semaphore() const - { return static_cast(m_shmem.get_user_address()); } - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline shm_named_semaphore::~shm_named_semaphore() -{} - -inline void shm_named_semaphore::dont_close_on_destruction() -{ interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline shm_named_semaphore::shm_named_semaphore - (create_only_t, const char *name, unsigned int initialCount, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_semaphore) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate, initialCount) - ,perm) -{} - -inline shm_named_semaphore::shm_named_semaphore - (open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_semaphore) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate, initialCount) - ,perm) -{} - -inline shm_named_semaphore::shm_named_semaphore - (open_only_t, const char *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen, 0)) -{} - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline shm_named_semaphore::shm_named_semaphore - (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) - : m_shmem (create_only - ,name - ,sizeof(interprocess_semaphore) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoCreate, initialCount) - ,perm) -{} - -inline shm_named_semaphore::shm_named_semaphore - (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) - : m_shmem (open_or_create - ,name - ,sizeof(interprocess_semaphore) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(DoOpenOrCreate, initialCount) - ,perm) -{} - -inline shm_named_semaphore::shm_named_semaphore - (open_only_t, const wchar_t *name) - : m_shmem (open_only - ,name - ,read_write - ,0 - ,construct_func_t(DoOpen, 0)) -{} - -#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline void shm_named_semaphore::post() -{ semaphore()->post(); } - -inline void shm_named_semaphore::wait() -{ semaphore()->wait(); } - -inline bool shm_named_semaphore::try_wait() -{ return semaphore()->try_wait(); } - -template -inline bool shm_named_semaphore::timed_wait(const TimePoint &abs_time) -{ return semaphore()->timed_wait(abs_time); } - -inline bool shm_named_semaphore::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline bool shm_named_semaphore::remove(const wchar_t *name) -{ return shared_memory_object::remove(name); } - -#endif - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_SHM_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp deleted file mode 100644 index af21f983ba1..00000000000 --- a/extern/boost/boost/interprocess/sync/shm/named_upgradable_mutex.hpp +++ /dev/null @@ -1,360 +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_NAMED_UPGRADABLE_MUTEX_HPP -#define BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a named upgradable mutex class for inter-process synchronization - -namespace boost { -namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -class named_condition; - -//!A upgradable mutex with a global name, so it can be found from different -//!processes. This mutex can't be placed in shared memory, and -//!each process should have it's own named upgradable mutex. -class named_upgradable_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable - named_upgradable_mutex(); - named_upgradable_mutex(const named_upgradable_mutex &); - named_upgradable_mutex &operator=(const named_upgradable_mutex &); - friend class named_condition; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Creates a global upgradable mutex with a name. - //!If the upgradable mutex can't be created throws interprocess_exception - named_upgradable_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - //!Opens or creates a global upgradable mutex with a name, and an initial count. - //!If the upgradable mutex is created, this call is equivalent to - //!named_upgradable_mutex(create_only_t, ...) - //!If the upgradable mutex is already created, this call is equivalent to - //!named_upgradable_mutex(open_only_t, ... ). - named_upgradable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - //!Opens a global upgradable mutex with a name if that upgradable mutex - //!is previously. - //!created. If it is not previously created this function throws - //!interprocess_exception. - named_upgradable_mutex(open_only_t, const char *name); - - //!Destroys *this and indicates that the calling process is finished using - //!the resource. The destructor function will deallocate - //!any system resources allocated by the system for use by this process for - //!this resource. The resource can still be opened again calling - //!the open constructor overload. To erase the resource from the system - //!use remove(). - ~named_upgradable_mutex(); - - //Exclusive locking - - //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, - //! and if another thread has exclusive, sharable or upgradable ownership of - //! the mutex, it waits until it can obtain the ownership. - //!Throws: interprocess_exception on error. - void lock(); - - //!Effects: The calling thread tries to acquire exclusive ownership of the mutex - //! without waiting. If no other thread has exclusive, sharable or upgradable - //! ownership of the mutex this succeeds. - //!Returns: If it can acquire exclusive ownership immediately returns true. - //! If it has to wait, returns false. - //!Throws: interprocess_exception on error. - bool try_lock(); - - //!Effects: The calling thread tries to acquire exclusive ownership of the mutex - //! waiting if necessary until no other thread has exclusive, sharable or - //! upgradable ownership of the mutex or abs_time is reached. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: interprocess_exception on error. - template - bool timed_lock(const TimePoint &abs_time); - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The calling thread releases the exclusive ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock(); - - //Sharable locking - - //!Effects: The calling thread tries to obtain sharable ownership of the mutex, - //! and if another thread has exclusive ownership of the mutex, - //! waits until it can obtain the ownership. - //!Throws: interprocess_exception on error. - void lock_sharable(); - - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! without waiting. If no other thread has exclusive ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire sharable ownership immediately returns true. If it - //! has to wait, returns false. - //!Throws: interprocess_exception on error. - bool try_lock_sharable(); - - //!Effects: The calling thread tries to acquire sharable ownership of the mutex - //! waiting if necessary until no other thread has exclusive - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. - //!Throws: interprocess_exception on error. - template - bool timed_lock_sharable(const TimePoint &abs_time); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The calling thread releases the sharable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_sharable(); - - //Upgradable locking - - //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, - //! and if another thread has exclusive or upgradable ownership of the mutex, - //! waits until it can obtain the ownership. - //!Throws: interprocess_exception on error. - void lock_upgradable(); - - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! without waiting. If no other thread has exclusive or upgradable ownership - //! of the mutex this succeeds. - //!Returns: If it can acquire upgradable ownership immediately returns true. - //! If it has to wait, returns false. - //!Throws: interprocess_exception on error. - bool try_lock_upgradable(); - - //!Effects: The calling thread tries to acquire upgradable ownership of the mutex - //! waiting if necessary until no other thread has exclusive or upgradable - //! ownership of the mutex or abs_time is reached. - //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. - //!Throws: interprocess_exception on error. - template - bool timed_lock_upgradable(const TimePoint &abs_time); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The calling thread releases the upgradable ownership of the mutex. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable(); - - //Demotions - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! upgradable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_upgradable(); - - //!Precondition: The thread must have exclusive ownership of the mutex. - //!Effects: The thread atomically releases exclusive ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_and_lock_sharable(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! sharable ownership. This operation is non-blocking. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock_sharable(); - - //Promotions - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and acquires - //! exclusive ownership. This operation will block until all threads with - //! sharable ownership release it. - //!Throws: An exception derived from interprocess_exception on error. - void unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to - //! acquire exclusive ownership. This operation will fail if there are threads - //! with sharable ownership, but it will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_upgradable_and_lock(); - - //!Precondition: The thread must have upgradable ownership of the mutex. - //!Effects: The thread atomically releases upgradable ownership and tries to acquire - //! exclusive ownership, waiting if necessary until abs_time. This operation will - //! fail if there are threads with sharable ownership or timeout reaches, but it - //! will maintain upgradable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - template - bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time); - - //!Precondition: The thread must have sharable ownership of the mutex. - //!Effects: The thread atomically releases sharable ownership and tries to acquire - //! exclusive ownership. This operation will fail if there are threads with sharable - //! or upgradable ownership, but it will maintain sharable ownership. - //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. - //!Throws: An exception derived from interprocess_exception on error. - bool try_unlock_sharable_and_lock(); - - bool try_unlock_sharable_and_lock_upgradable(); - - //!Erases a named upgradable mutex from the system. - //!Returns false on error. Never throws. - static bool remove(const char *name); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class ipcdetail::interprocess_tester; - void dont_close_on_destruction(); - - interprocess_upgradable_mutex *mutex() const - { return static_cast(m_shmem.get_user_address()); } - - typedef ipcdetail::managed_open_or_create_impl open_create_impl_t; - open_create_impl_t m_shmem; - typedef ipcdetail::named_creation_functor construct_func_t; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline named_upgradable_mutex::~named_upgradable_mutex() -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (create_only_t, const char *name, const permissions &perm) - : m_shmem (create_only_t() - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_or_create_t, const char *name, const permissions &perm) - : m_shmem (open_or_create_t() - ,name - ,sizeof(interprocess_upgradable_mutex) + - open_create_impl_t::ManagedOpenOrCreateUserOffset - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpenOrCreate) - ,perm) -{} - -inline named_upgradable_mutex::named_upgradable_mutex - (open_only_t, const char *name) - : m_shmem (open_only_t() - ,name - ,read_write - ,0 - ,construct_func_t(ipcdetail::DoOpen)) -{} - -inline void named_upgradable_mutex::dont_close_on_destruction() -{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } - -inline void named_upgradable_mutex::lock() -{ this->mutex()->lock(); } - -inline void named_upgradable_mutex::unlock() -{ this->mutex()->unlock(); } - -inline bool named_upgradable_mutex::try_lock() -{ return this->mutex()->try_lock(); } - -template -inline bool named_upgradable_mutex::timed_lock(const TimePoint &abs_time) -{ return this->mutex()->timed_lock(abs_time); } - -inline void named_upgradable_mutex::lock_upgradable() -{ this->mutex()->lock_upgradable(); } - -inline void named_upgradable_mutex::unlock_upgradable() -{ this->mutex()->unlock_upgradable(); } - -inline bool named_upgradable_mutex::try_lock_upgradable() -{ return this->mutex()->try_lock_upgradable(); } - -template -inline bool named_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time) -{ return this->mutex()->timed_lock_upgradable(abs_time); } - -inline void named_upgradable_mutex::lock_sharable() -{ this->mutex()->lock_sharable(); } - -inline void named_upgradable_mutex::unlock_sharable() -{ this->mutex()->unlock_sharable(); } - -inline bool named_upgradable_mutex::try_lock_sharable() -{ return this->mutex()->try_lock_sharable(); } - -template -inline bool named_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time) -{ return this->mutex()->timed_lock_sharable(abs_time); } - -inline void named_upgradable_mutex::unlock_and_lock_upgradable() -{ this->mutex()->unlock_and_lock_upgradable(); } - -inline void named_upgradable_mutex::unlock_and_lock_sharable() -{ this->mutex()->unlock_and_lock_sharable(); } - -inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable() -{ this->mutex()->unlock_upgradable_and_lock_sharable(); } - -inline void named_upgradable_mutex::unlock_upgradable_and_lock() -{ this->mutex()->unlock_upgradable_and_lock(); } - -inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock() -{ return this->mutex()->try_unlock_upgradable_and_lock(); } - -template -inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time) -{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); } - -inline bool named_upgradable_mutex::try_unlock_sharable_and_lock() -{ return this->mutex()->try_unlock_sharable_and_lock(); } - -inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() -{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); } - -inline bool named_upgradable_mutex::remove(const char *name) -{ return shared_memory_object::remove(name); } - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_NAMED_UPGRADABLE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/condition.hpp b/extern/boost/boost/interprocess/sync/spin/condition.hpp deleted file mode 100644 index 5eead3e8296..00000000000 --- a/extern/boost/boost/interprocess/sync/spin/condition.hpp +++ /dev/null @@ -1,299 +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_SPIN_CONDITION_HPP -#define BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class spin_condition -{ - spin_condition(const spin_condition &); - spin_condition &operator=(const spin_condition &); - - public: - 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() - { this->notify(NOTIFY_ONE); } - - void notify_all() - { this->notify(NOTIFY_ALL); } - - template - void wait(L& lock) - { - if (!lock) - throw lock_exception(); - this->do_timed_wait_impl(ustime(0u), *lock.mutex()); - } - - template - void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - this->do_timed_wait_impl(ustime(0u), *lock.mutex()); - } - - template - 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(is_pos_infinity(abs_time)){ - this->wait(lock); - return true; - } - return this->do_timed_wait_impl(abs_time, *lock.mutex()); - } - - template - 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(is_pos_infinity(abs_time)){ - this->wait(lock, pred); - return true; - } - while (!pred()){ - if (!this->do_timed_wait_impl(abs_time, *lock.mutex())) - return pred(); - } - return true; - } - - template - 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 - bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) - { return this->timed_wait(lock, abs_time, pred); } - - template - cv_status wait_for(L& lock, const Duration &dur) - { return this->wait_until(lock, duration_to_ustime(dur)); } - - template - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, duration_to_ustime(dur), pred); } - - private: - - template - bool do_timed_wait_impl(const TimePoint &abs_time, InterprocessMutex &mut) - { - typedef boost::interprocess::scoped_lock 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_(), 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(&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 - spin_wait swait; - while(atomic_read32(&m_command) == SLEEP){ - swait.yield(); - - //Check for timeout - if(TimeoutEnabled){ - typedef typename microsec_clock::time_point time_point; - time_point now = get_now(bool_()); - - 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(TimeoutEnabled && timed_out){ - //Decrement wait count - atomic_dec32(const_cast(&m_num_waiters)); - unlock_enter_mut = true; - break; - } - else{ - boost::uint32_t result = atomic_cas32 - (const_cast(&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(&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(&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(&m_command), SLEEP, NOTIFY_ALL); - } - break; - } - } - } - - //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; - } - - template - static typename microsec_clock::time_point get_now(bool_) - { return microsec_clock::universal_time(); } - - template - static typename microsec_clock::time_point get_now(bool_) - { return typename microsec_clock::time_point(); } - - template - static void get_lock(bool_, Mutex &m, Lock &lck, const TimePoint &abs_time) - { - Lock dummy(m, abs_time); - lck = boost::move(dummy); - } - - template - static void get_lock(bool_, Mutex &m, Lock &lck, const TimePoint &) - { - Lock dummy(m); - lck = boost::move(dummy); - } - - void 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; - } - - //Notify that all threads should execute wait logic - spin_wait swait; - while(SLEEP != atomic_cas32(const_cast(&m_command), command, SLEEP)){ - swait.yield(); - } - //The enter mutex will rest locked until the last waiting thread unlocks it - } - - 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 -} //namespace boost - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_SPIN_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp b/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp deleted file mode 100644 index 0e7216aa704..00000000000 --- a/extern/boost/boost/interprocess/sync/spin/interprocess_barrier.hpp +++ /dev/null @@ -1,53 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2006. 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. -// -////////////////////////////////////////////////////////////////////////////// - -#include -#include - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -namespace boost { -namespace interprocess { - -inline barrier::barrier(unsigned int count) - : m_threshold(count), m_count(count), m_generation(0) -{ - if (count == 0) - throw std::invalid_argument("count cannot be zero."); -} - -inline barrier::~barrier(){} - -inline bool barrier::wait() -{ - scoped_lock lock(m_mutex); - unsigned int gen = m_generation; - - if (--m_count == 0){ - m_generation++; - m_count = m_threshold; - m_cond.notify_all(); - return true; - } - - while (gen == m_generation){ - m_cond.wait(lock); - } - return false; -} - -} //namespace interprocess { -} //namespace boost { diff --git a/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp deleted file mode 100644 index a2a85577957..00000000000 --- a/extern/boost/boost/interprocess/sync/spin/recursive_mutex.hpp +++ /dev/null @@ -1,185 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// Parts of the pthread code come from Boost Threads code: -// -////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2003 -// William E. Kempf -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. William E. Kempf makes no representations -// about the suitability of this software for any purpose. -// It is provided "as is" without express or implied warranty. -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class spin_recursive_mutex -{ - spin_recursive_mutex(const spin_recursive_mutex &); - spin_recursive_mutex &operator=(const spin_recursive_mutex &); - public: - - spin_recursive_mutex(); - ~spin_recursive_mutex(); - - void lock(); - bool try_lock(); - template - bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - void unlock(); - void take_ownership(); - private: - spin_mutex m_mutex; - unsigned int m_nLockCount; - volatile ipcdetail::OS_systemwide_thread_id_t m_nOwner; - volatile boost::uint32_t m_s; -}; - -inline spin_recursive_mutex::spin_recursive_mutex() - : m_nLockCount(0), m_nOwner(ipcdetail::get_invalid_systemwide_thread_id()){} - -inline spin_recursive_mutex::~spin_recursive_mutex(){} - -inline void spin_recursive_mutex::lock() -{ - typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); - handle_t old_id; - ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); - if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)){ - if((unsigned int)(m_nLockCount+1) == 0){ - //Overflow, throw an exception - throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } - ++m_nLockCount; - } - else{ - m_mutex.lock(); - ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); - m_nLockCount = 1; - } -} - -inline bool spin_recursive_mutex::try_lock() -{ - typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); - handle_t old_id; - ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); - if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it - if((unsigned int)(m_nLockCount+1) == 0){ - //Overflow, throw an exception - throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } - ++m_nLockCount; - return true; - } - if(m_mutex.try_lock()){ - ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); - m_nLockCount = 1; - return true; - } - return false; -} - -template -inline bool spin_recursive_mutex::timed_lock(const TimePoint &abs_time) -{ - typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); - handle_t old_id; - ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); - if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it - if((unsigned int)(m_nLockCount+1) == 0){ - //Overflow, throw an exception - throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow"); - } - ++m_nLockCount; - return true; - } - //m_mutex supports abs_time so no need to check it - if(m_mutex.timed_lock(abs_time)){ - ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); - m_nLockCount = 1; - return true; - } - return false; -} - -inline void spin_recursive_mutex::unlock() -{ - typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - handle_t old_id; - ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id); - const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); - (void)old_id; - (void)thr_id; - BOOST_ASSERT(ipcdetail::equal_systemwide_thread_id(thr_id, old_id)); - --m_nLockCount; - if(!m_nLockCount){ - const handle_t new_id(ipcdetail::get_invalid_systemwide_thread_id()); - ipcdetail::systemwide_thread_id_copy(new_id, m_nOwner); - m_mutex.unlock(); - } -} - -inline void spin_recursive_mutex::take_ownership() -{ - typedef ipcdetail::OS_systemwide_thread_id_t handle_t; - this->m_nLockCount = 1; - const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id()); - ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner); -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_SPIN_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/spin/semaphore.hpp b/extern/boost/boost/interprocess/sync/spin/semaphore.hpp deleted file mode 100644 index cd3c8662057..00000000000 --- a/extern/boost/boost/interprocess/sync/spin/semaphore.hpp +++ /dev/null @@ -1,94 +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_SPIN_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class spin_semaphore -{ - spin_semaphore(const spin_semaphore &); - spin_semaphore &operator=(const spin_semaphore &); - - public: - spin_semaphore(unsigned int initialCount); - ~spin_semaphore(); - - void post(); - void wait(); - bool try_wait(); - template bool timed_wait(const TimePoint &abs_time); - -// int get_count() const; - private: - volatile boost::uint32_t m_count; -}; - - -inline spin_semaphore::~spin_semaphore() -{} - -inline spin_semaphore::spin_semaphore(unsigned int initialCount) -{ ipcdetail::atomic_write32(&this->m_count, boost::uint32_t(initialCount)); } - -inline void spin_semaphore::post() -{ - ipcdetail::atomic_inc32(&m_count); -} - -inline void spin_semaphore::wait() -{ - ipcdetail::lock_to_wait lw(*this); - return ipcdetail::try_based_lock(lw); -} - -inline bool spin_semaphore::try_wait() -{ - return ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0)); -} - -template -inline bool spin_semaphore::timed_wait(const TimePoint &abs_time) -{ - ipcdetail::lock_to_wait lw(*this); - return ipcdetail::try_based_timed_lock(lw, abs_time); -} - -//inline int spin_semaphore::get_count() const -//{ - //return (int)ipcdetail::atomic_read32(&m_count); -//} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/upgradable_lock.hpp b/extern/boost/boost/interprocess/sync/upgradable_lock.hpp deleted file mode 100644 index 787cf16e1ff..00000000000 --- a/extern/boost/boost/interprocess/sync/upgradable_lock.hpp +++ /dev/null @@ -1,314 +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. -// -////////////////////////////////////////////////////////////////////////////// -// -// This interface is inspired by Howard Hinnant's lock proposal. -// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP -#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include - -//!\file -//!Describes the upgradable_lock class that serves to acquire the upgradable -//!lock of a mutex. - -namespace boost { -namespace interprocess { - -//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking, -//!try-read-locking and timed-read-locking (recursive or not) for the Mutex. -//!Additionally the upgradable_lock can transfer ownership to a scoped_lock -//!using transfer_lock syntax. The Mutex need not supply all of the functionality. -//!If the client of upgradable_lock does not use functionality which the -//!Mutex does not supply, no harm is done. Mutex ownership can be shared among -//!read_locks, and a single upgradable_lock. upgradable_lock does not support -//!copy semantics. However upgradable_lock supports ownership transfer from -//!a upgradable_locks or scoped_locks via transfer_lock syntax. -template -class upgradable_lock -{ - public: - typedef UpgradableMutex mutex_type; - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - typedef upgradable_lock this_type; - explicit upgradable_lock(scoped_lock&); - typedef bool this_type::*unspecified_bool_type; - BOOST_MOVABLE_BUT_NOT_COPYABLE(upgradable_lock) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - public: - - //!Effects: Default constructs a upgradable_lock. - //!Postconditions: owns() == false and mutex() == 0. - upgradable_lock() BOOST_NOEXCEPT - : mp_mutex(0), m_locked(false) - {} - - explicit upgradable_lock(mutex_type& m) - : mp_mutex(&m), m_locked(false) - { mp_mutex->lock_upgradable(); m_locked = true; } - - //!Postconditions: owns() == false, and mutex() == &m. - //!Notes: The constructor will not take ownership of the mutex. There is no effect - //! required on the referenced mutex. - upgradable_lock(mutex_type& m, defer_lock_type) - : mp_mutex(&m), m_locked(false) - {} - - //!Postconditions: owns() == true, and mutex() == &m. - //!Notes: The constructor will suppose that the mutex is already upgradable - //! locked. There is no effect required on the referenced mutex. - upgradable_lock(mutex_type& m, accept_ownership_type) - : mp_mutex(&m), m_locked(true) - {} - - //!Effects: m.try_lock_upgradable(). - //!Postconditions: mutex() == &m. owns() == the return value of the - //! m.try_lock_upgradable() executed within the constructor. - //!Notes: The constructor will take upgradable-ownership of the mutex - //! if it can do so without waiting. Whether or not this constructor - //! handles recursive locking depends upon the mutex. If the mutex_type - //! does not support try_lock_upgradable, this constructor will fail at - //! compile time if instantiated, but otherwise have no effect. - upgradable_lock(mutex_type& m, try_to_lock_type) - : mp_mutex(&m), m_locked(false) - { m_locked = mp_mutex->try_lock_upgradable(); } - - //!Effects: m.timed_lock_upgradable(abs_time) - //!Postconditions: mutex() == &m. owns() == the return value of the - //! m.timed_lock_upgradable() executed within the constructor. - //!Notes: The constructor will take upgradable-ownership of the mutex if it - //! can do so within the time specified. Whether or not this constructor - //! handles recursive locking depends upon the mutex. If the mutex_type - //! does not support timed_lock_upgradable, this constructor will fail - //! at compile time if instantiated, but otherwise have no effect. - template - upgradable_lock(mutex_type& m, const TimePoint& abs_time) - : mp_mutex(&m), m_locked(false) - { m_locked = mp_mutex->timed_lock_upgradable(abs_time); } - - //!Effects: No effects on the underlying mutex. - //!Postconditions: mutex() == the value upgr.mutex() had before the - //! construction. upgr.mutex() == 0. owns() == upgr.owns() before the - //! construction. upgr.owns() == false. - //!Notes: If upgr is locked, this constructor will lock this upgradable_lock - //! while unlocking upgr. If upgr is unlocked, then this upgradable_lock will - //! be unlocked as well. Only a moved upgradable_lock's will match this - //! signature. An non-moved upgradable_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. - upgradable_lock(BOOST_RV_REF(upgradable_lock) upgr) BOOST_NOEXCEPT - : mp_mutex(0), m_locked(upgr.owns()) - { mp_mutex = upgr.release(); } - - //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). - //!Postconditions: mutex() == the value scop.mutex() had before the construction. - //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the - //! construction, scop.owns() == false. - //!Notes: If scop is locked, this constructor will transfer the exclusive-ownership - //! to an upgradable-ownership of this upgradable_lock. - //! Only a moved sharable_lock's will match this - //! signature. An non-moved sharable_lock can be moved with the - //! expression: "boost::move(lock);". - template - upgradable_lock(BOOST_RV_REF(scoped_lock) scop - , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) - : mp_mutex(0), m_locked(false) - { - scoped_lock &u_lock = scop; - if(u_lock.owns()){ - u_lock.mutex()->unlock_and_lock_upgradable(); - m_locked = true; - } - mp_mutex = u_lock.release(); - } - - //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable() - //! on the referenced mutex. - //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex() - //! obtains the value from shar.release() and owns() is set to true. - //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is - //! unaffected and this upgradable_lock construction has the same - //! effects as a default construction. - //! c)Else shar.owns() is false. mutex() obtains the value from shar.release() - //! and owns() is set to false. - //!Notes: This construction will not block. It will try to obtain mutex - //! ownership from shar immediately, while changing the lock type from a - //! "read lock" to an "upgradable lock". If the "read lock" isn't held - //! in the first place, the mutex merely changes type to an unlocked - //! "upgradable lock". If the "read lock" is held, then mutex transfer - //! occurs only if it can do so in a non-blocking manner. - template - upgradable_lock( BOOST_RV_REF(sharable_lock) shar, try_to_lock_type - , typename ipcdetail::enable_if< ipcdetail::is_same >::type * = 0) - : mp_mutex(0), m_locked(false) - { - sharable_lock &s_lock = shar; - if(s_lock.owns()){ - if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){ - mp_mutex = s_lock.release(); - } - } - else{ - s_lock.release(); - } - } - - //!Effects: if (owns()) m_->unlock_upgradable(). - //!Notes: The destructor behavior ensures that the mutex lock is not leaked. - ~upgradable_lock() - { - BOOST_TRY{ - if(m_locked && mp_mutex) mp_mutex->unlock_upgradable(); - } - BOOST_CATCH(...){} BOOST_CATCH_END - } - - //!Effects: If owns(), then unlock_upgradable() is called on mutex(). - //! *this gets the state of upgr and upgr gets set to a default constructed state. - //!Notes: With a recursive mutex it is possible that both this and upgr own the - //! mutex before the assignment. In this case, this will own the mutex - //! after the assignment (and upgr will not), but the mutex's upgradable lock - //! count will be decremented by one. - upgradable_lock &operator=(BOOST_RV_REF(upgradable_lock) upgr) - { - if(this->owns()) - this->unlock(); - m_locked = upgr.owns(); - mp_mutex = upgr.release(); - return *this; - } - - //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() - //! exception. Calls lock_upgradable() on the referenced mutex. - //!Postconditions: owns() == true. - //!Notes: The sharable_lock changes from a state of not owning the mutex, - //! to owning the mutex, blocking if necessary. - void lock() - { - if(!mp_mutex || m_locked) - throw lock_exception(); - mp_mutex->lock_upgradable(); - m_locked = true; - } - - //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() - //! exception. Calls try_lock_upgradable() on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->try_lock_upgradable(). - //!Notes: The upgradable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if blocking was not required. If the - //! mutex_type does not support try_lock_upgradable(), this function will - //! fail at compile time if instantiated, but otherwise have no effect. - bool try_lock() - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->try_lock_upgradable(); - return m_locked; - } - - //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() - //! exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex. - //!Postconditions: owns() == the value returned from - //! mutex()->timed_lock_upgradable(abs_time). - //!Notes: The upgradable_lock changes from a state of not owning the mutex, - //! to owning the mutex, but only if it can obtain ownership within the - //! specified time. If the mutex_type does not support - //! timed_lock_upgradable(abs_time), this function will fail at compile - //! time if instantiated, but otherwise have no effect. - template - bool timed_lock(const TimePoint& abs_time) - { - if(!mp_mutex || m_locked) - throw lock_exception(); - m_locked = mp_mutex->timed_lock_upgradable(abs_time); - return m_locked; - } - - //!Effects: If mutex() == 0 or if not locked, throws a lock_exception() - //! exception. Calls unlock_upgradable() on the referenced mutex. - //!Postconditions: owns() == false. - //!Notes: The upgradable_lock changes from a state of owning the mutex, - //! to not owning the mutex. - void unlock() - { - if(!mp_mutex || !m_locked) - throw lock_exception(); - mp_mutex->unlock_upgradable(); - m_locked = false; - } - - //!Effects: Returns true if this scoped_lock has acquired the - //!referenced mutex. - bool owns() const BOOST_NOEXCEPT - { return m_locked && mp_mutex; } - - //!Conversion to bool. - //!Returns owns(). - 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 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() BOOST_NOEXCEPT - { - mutex_type *mut = mp_mutex; - mp_mutex = 0; - m_locked = false; - return mut; - } - - //!Effects: Swaps state with moved lock. - //!Throws: Nothing. - void swap(upgradable_lock &other) BOOST_NOEXCEPT - { - (simple_swap)(mp_mutex, other.mp_mutex); - (simple_swap)(m_locked, other.m_locked); - } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - mutex_type *mp_mutex; - bool m_locked; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} // namespace interprocess -} // namespace boost - -#include - -#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/condition.hpp b/extern/boost/boost/interprocess/sync/windows/condition.hpp deleted file mode 100644 index fca3f1f8dc8..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/condition.hpp +++ /dev/null @@ -1,147 +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_WINDOWS_CONDITION_HPP -#define BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class winapi_condition -{ - winapi_condition(const winapi_condition &); - winapi_condition &operator=(const winapi_condition &); - - public: - winapi_condition() - : m_condition_data() - {} - - ~winapi_condition() - { - //Notify all waiting threads - //to allow POSIX semantics on condition destruction - this->notify_all(); - } - - void notify_one() - { m_condition_data.notify_one(); } - - void notify_all() - { m_condition_data.notify_all(); } - - template - void wait(L& lock) - { m_condition_data.wait(lock); } - - template - void wait(L& lock, Pr pred) - { m_condition_data.wait(lock, pred); } - - - template - bool timed_wait(L& lock, const TimePoint &abs_time) - { return m_condition_data.timed_wait(lock, abs_time); } - - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { return m_condition_data.timed_wait(lock, abs_time, pred); } - - template - 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 - bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) - { return this->timed_wait(lock, abs_time, pred); } - - template - cv_status wait_for(L& lock, const Duration &dur) - { return this->wait_until(lock, duration_to_ustime(dur)); } - - template - 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 unsigned int integer_type; - typedef winapi_semaphore semaphore_type; - typedef winapi_mutex mutex_type; - - condition_data() - : m_nwaiters_blocked(0) - , m_nwaiters_gone(0) - , m_nwaiters_to_unblock(0) - , m_sem_block_queue(0) - , m_sem_block_lock(1) - , m_mtx_unblock_lock() - {} - - integer_type &get_nwaiters_blocked() - { return m_nwaiters_blocked; } - - integer_type &get_nwaiters_gone() - { return m_nwaiters_gone; } - - integer_type &get_nwaiters_to_unblock() - { return m_nwaiters_to_unblock; } - - semaphore_type &get_sem_block_queue() - { return m_sem_block_queue; } - - semaphore_type &get_sem_block_lock() - { return m_sem_block_lock; } - - mutex_type &get_mtx_unblock_lock() - { return 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 m_condition_data; -}; - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/mutex.hpp b/extern/boost/boost/interprocess/sync/windows/mutex.hpp deleted file mode 100644 index ce168f89b60..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/mutex.hpp +++ /dev/null @@ -1,126 +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_WINDOWS_MUTEX_HPP -#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class winapi_mutex -{ - winapi_mutex(const winapi_mutex &); - winapi_mutex &operator=(const winapi_mutex &); - public: - - winapi_mutex(); - ~winapi_mutex(); - - void lock(); - bool try_lock(); - template bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - void unlock(); - void take_ownership(){}; - - private: - const sync_id id_; -}; - -inline winapi_mutex::winapi_mutex() - : id_() -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //Create mutex with the initial count - bool 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 winapi_mutex::~winapi_mutex() -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - handles.destroy_handle(this->id_, this); -} - -inline void winapi_mutex::lock(void) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); - mut.lock(); -} - -inline bool winapi_mutex::try_lock(void) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); - return mut.try_lock(); -} - -template -inline bool winapi_mutex::timed_lock(const TimePoint &abs_time) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); - return mut.timed_lock(abs_time); -} - -inline void winapi_mutex::unlock(void) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_mutex_functions mut(handles.obtain_mutex(this->id_, this)); - return mut.unlock(); -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_condition.hpp b/extern/boost/boost/interprocess/sync/windows/named_condition.hpp deleted file mode 100644 index 2f9354c44e1..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_condition.hpp +++ /dev/null @@ -1,40 +0,0 @@ - ////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_CONDITION_HPP -#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -typedef winapi_named_condition_any winapi_named_condition; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp b/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp deleted file mode 100644 index f13a5f944f4..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_condition_any.hpp +++ /dev/null @@ -1,337 +0,0 @@ - ////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_CONDITION_ANY_HPP -#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -template -struct named_cond_callbacks_str; - -template<> -struct named_cond_callbacks_str -{ - static const char* ipc_cond() - { return "Global\\bipc.cond."; } - - static const char* bq() - { return "_bq"; } - - static const char* bl() - { return "_bl"; } - - static const char* ul() - { return "_ul"; } -}; - -template<> -struct named_cond_callbacks_str -{ - static const wchar_t* ipc_cond() - { return L"Global\\bipc.cond."; } - - static const wchar_t* bq() - { return L"_bq"; } - - static const wchar_t* bl() - { return L"_bl"; } - - static const wchar_t* ul() - { return L"_ul"; } -}; - -class winapi_named_condition_any -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - winapi_named_condition_any(); - winapi_named_condition_any(const winapi_named_condition_any &); - winapi_named_condition_any &operator=(const winapi_named_condition_any &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - winapi_named_condition_any - (create_only_t, const char *name, const permissions &perm = permissions()) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); - } - - winapi_named_condition_any - (open_or_create_t, const char *name, const permissions &perm = permissions()) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); - } - - winapi_named_condition_any(open_only_t, const char *name) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); - } - - #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - winapi_named_condition_any - (create_only_t, const wchar_t *name, const permissions &perm = permissions()) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); - } - - winapi_named_condition_any - (open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); - } - - winapi_named_condition_any(open_only_t, const wchar_t *name) - : m_condition_data() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); - } - - #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - ~winapi_named_condition_any() - { - named_cond_callbacks callbacks(m_condition_data.get_members()); - m_named_sync.close(callbacks); - } - - void notify_one() - { m_condition_data.notify_one(); } - - void notify_all() - { m_condition_data.notify_all(); } - - template - bool timed_wait(L& lock, const TimePoint &abs_time) - { return m_condition_data.timed_wait(lock, abs_time); } - - template - bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred) - { return m_condition_data.timed_wait(lock, abs_time, pred); } - - template - void wait(L& lock) - { m_condition_data.wait(lock); } - - template - void wait(L& lock, Pr pred) - { m_condition_data.wait(lock, pred); } - - template - 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 - bool wait_until(L& lock, const TimePoint &abs_time, Pr pred) - { return this->timed_wait(lock, abs_time, pred); } - - template - cv_status wait_for(L& lock, const Duration &dur) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); } - - template - bool wait_for(L& lock, const Duration &dur, Pr pred) - { return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); } - - static bool remove(const char *name) - { return windows_named_sync::remove(name); } - - static bool remove(const wchar_t *name) - { return windows_named_sync::remove(name); } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - void dont_close_on_destruction() - {} - - friend class interprocess_tester; - - struct condition_data - { - typedef boost::int32_t integer_type; - typedef winapi_semaphore_wrapper semaphore_type; - typedef winapi_mutex_wrapper mutex_type; - - integer_type &get_nwaiters_blocked() - { return m_nwaiters_blocked; } - - integer_type &get_nwaiters_gone() - { return m_nwaiters_gone; } - - integer_type &get_nwaiters_to_unblock() - { return m_nwaiters_to_unblock; } - - semaphore_type &get_sem_block_queue() - { return m_sem_block_queue; } - - semaphore_type &get_sem_block_lock() - { return m_sem_block_lock; } - - mutex_type &get_mtx_unblock_lock() - { return m_mtx_unblock_lock; } - - integer_type m_nwaiters_blocked; - integer_type m_nwaiters_gone; - integer_type m_nwaiters_to_unblock; - winapi_semaphore_wrapper m_sem_block_queue; - winapi_semaphore_wrapper m_sem_block_lock; - winapi_mutex_wrapper m_mtx_unblock_lock; - }; - - - class named_cond_callbacks : public windows_named_sync_interface - { - typedef __int64 sem_count_t; - mutable sem_count_t sem_counts [2]; - - public: - named_cond_callbacks(condition_data &cond_data) - : m_condition_data(cond_data) - {} - - virtual std::size_t get_data_size() const BOOST_OVERRIDE - { return sizeof(sem_counts); } - - virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE - { - sem_counts[0] = m_condition_data.m_sem_block_queue.value(); - sem_counts[1] = m_condition_data.m_sem_block_lock.value(); - return &sem_counts; - } - - virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE - { - sem_counts[0] = 0; - sem_counts[1] = 1; - return &sem_counts; - } - - virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE - { return &sem_counts; } - - virtual bool open(create_enum_t op, const char *id_name) BOOST_OVERRIDE - { return this->open_impl(op, id_name); } - - virtual bool open(create_enum_t op, const wchar_t *id_name) BOOST_OVERRIDE - { return this->open_impl(op, id_name); } - - virtual void close() BOOST_OVERRIDE - { - m_condition_data.m_sem_block_queue.close(); - m_condition_data.m_sem_block_lock.close(); - m_condition_data.m_mtx_unblock_lock.close(); - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - } - - virtual ~named_cond_callbacks() BOOST_OVERRIDE - {} - - private: - - template - bool open_impl(create_enum_t, const CharT *id_name) - { - typedef named_cond_callbacks_str str_t; - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - - //Now open semaphores and mutex. - //Use local variables + swap to guarantee consistent - //initialization and cleanup in case any opening fails - permissions perm; - perm.set_unrestricted(); - std::basic_string aux_str = str_t::ipc_cond(); - aux_str += id_name; - std::size_t pos = aux_str.size(); - - //sem_block_queue - aux_str += str_t::bq(); - winapi_semaphore_wrapper sem_block_queue; - bool created; - if(!sem_block_queue.open_or_create - (aux_str.c_str(), static_cast(sem_counts[0]), winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //sem_block_lock - aux_str += str_t::bl(); - winapi_semaphore_wrapper sem_block_lock; - if(!sem_block_lock.open_or_create - (aux_str.c_str(), static_cast(sem_counts[1]), winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //mtx_unblock_lock - aux_str += str_t::ul(); - winapi_mutex_wrapper mtx_unblock_lock; - if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) - return false; - - //All ok, commit data - m_condition_data.m_sem_block_queue.swap(sem_block_queue); - m_condition_data.m_sem_block_lock.swap(sem_block_lock); - m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); - return true; - } - - condition_data &m_condition_data; - }; - - windows_named_sync m_named_sync; - ipcdetail::condition_8a_wrapper m_condition_data; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp deleted file mode 100644 index 029eb61d5f3..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_mutex.hpp +++ /dev/null @@ -1,232 +0,0 @@ - ////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_MUTEX_HPP -#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - - - -class winapi_named_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - winapi_named_mutex(); - winapi_named_mutex(const winapi_named_mutex &); - winapi_named_mutex &operator=(const winapi_named_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - winapi_named_mutex(create_only_t, const char *name, const permissions &perm = permissions()); - - winapi_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()); - - winapi_named_mutex(open_only_t, const char *name); - - winapi_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); - - winapi_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); - - winapi_named_mutex(open_only_t, const wchar_t *name); - - ~winapi_named_mutex(); - - void unlock(); - void lock(); - bool try_lock(); - template bool timed_lock(const TimePoint &abs_time); - - template bool try_lock_until(const TimePoint &abs_time) - { return this->timed_lock(abs_time); } - - template bool try_lock_for(const Duration &dur) - { return this->timed_lock(duration_to_ustime(dur)); } - - static bool remove(const char *name); - - static bool remove(const wchar_t *name); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - winapi_mutex_wrapper m_mtx_wrapper; - windows_named_sync m_named_sync; - - class named_mut_callbacks : public windows_named_sync_interface - { - public: - named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper) - : m_mtx_wrapper(mtx_wrapper) - {} - - virtual std::size_t get_data_size() const BOOST_OVERRIDE - { return 0u; } - - virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE - { return 0; } - - virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE - { return 0; } - - virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE - { return 0; } - - virtual bool open(create_enum_t, const char *id_name) BOOST_OVERRIDE - { - std::string aux_str = "Global\\bipc.mut."; - aux_str += id_name; - // - permissions mut_perm; - mut_perm.set_unrestricted(); - return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); - } - - virtual bool open(create_enum_t, const wchar_t *id_name) BOOST_OVERRIDE - { - std::wstring aux_str = L"Global\\bipc.mut."; - aux_str += id_name; - // - permissions mut_perm; - mut_perm.set_unrestricted(); - return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm); - } - - virtual void close() BOOST_OVERRIDE - { - m_mtx_wrapper.close(); - } - - virtual ~named_mut_callbacks() BOOST_OVERRIDE - {} - - private: - winapi_mutex_wrapper& m_mtx_wrapper; - }; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline winapi_named_mutex::~winapi_named_mutex() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.close(callbacks); -} - -inline void winapi_named_mutex::dont_close_on_destruction() -{} - -inline winapi_named_mutex::winapi_named_mutex - (create_only_t, const char *name, const permissions &perm) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline winapi_named_mutex::winapi_named_mutex - (open_or_create_t, const char *name, const permissions &perm) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline winapi_named_mutex::winapi_named_mutex(open_only_t, const char *name) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline winapi_named_mutex::winapi_named_mutex - (create_only_t, const wchar_t *name, const permissions &perm) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline winapi_named_mutex::winapi_named_mutex - (open_or_create_t, const wchar_t *name, const permissions &perm) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline winapi_named_mutex::winapi_named_mutex(open_only_t, const wchar_t *name) - : m_mtx_wrapper() -{ - named_mut_callbacks callbacks(m_mtx_wrapper); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline void winapi_named_mutex::unlock() -{ - m_mtx_wrapper.unlock(); -} - -inline void winapi_named_mutex::lock() -{ - m_mtx_wrapper.lock(); -} - -inline bool winapi_named_mutex::try_lock() -{ - return m_mtx_wrapper.try_lock(); -} - -template -inline bool winapi_named_mutex::timed_lock(const TimePoint &abs_time) -{ - return m_mtx_wrapper.timed_lock(abs_time); -} - -inline bool winapi_named_mutex::remove(const char *name) -{ - return windows_named_sync::remove(name); -} - -inline bool winapi_named_mutex::remove(const wchar_t *name) -{ - return windows_named_sync::remove(name); -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP \ No newline at end of file diff --git a/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp deleted file mode 100644 index 3d564b5341f..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_recursive_mutex.hpp +++ /dev/null @@ -1,74 +0,0 @@ - ////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP -#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - - -class winapi_named_recursive_mutex - //Windows mutexes based on CreateMutex are already recursive... - : public winapi_named_mutex -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - winapi_named_recursive_mutex(); - winapi_named_recursive_mutex(const winapi_named_mutex &); - winapi_named_recursive_mutex &operator=(const winapi_named_mutex &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - winapi_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions()) - : winapi_named_mutex(create_only_t(), name, perm) - {} - - winapi_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions()) - : winapi_named_mutex(open_or_create_t(), name, perm) - {} - - winapi_named_recursive_mutex(open_only_t, const char *name) - : winapi_named_mutex(open_only_t(), name) - {} - - winapi_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()) - : winapi_named_mutex(create_only_t(), name, perm) - {} - - winapi_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) - : winapi_named_mutex(open_or_create_t(), name, perm) - {} - - winapi_named_recursive_mutex(open_only_t, const wchar_t *name) - : winapi_named_mutex(open_only_t(), name) - {} -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp b/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp deleted file mode 100644 index bd3cff37a6e..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_semaphore.hpp +++ /dev/null @@ -1,230 +0,0 @@ - ////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - - - -class winapi_named_semaphore -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - winapi_named_semaphore(); - winapi_named_semaphore(const winapi_named_semaphore &); - winapi_named_semaphore &operator=(const winapi_named_semaphore &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - winapi_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - winapi_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions()); - - winapi_named_semaphore(open_only_t, const char *name); - - winapi_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - winapi_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); - - winapi_named_semaphore(open_only_t, const wchar_t *name); - - ~winapi_named_semaphore(); - - void post(); - void wait(); - bool try_wait(); - template bool timed_wait(const TimePoint &abs_time); - - static bool remove(const char *name); - static bool remove(const wchar_t *name); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - winapi_semaphore_wrapper m_sem_wrapper; - windows_named_sync m_named_sync; - - class named_sem_callbacks : public windows_named_sync_interface - { - public: - typedef __int64 sem_count_t; - named_sem_callbacks(winapi_semaphore_wrapper &sem_wrapper, sem_count_t sem_cnt) - : m_sem_wrapper(sem_wrapper), m_sem_count(sem_cnt) - {} - - virtual std::size_t get_data_size() const BOOST_OVERRIDE - { return sizeof(sem_count_t); } - - virtual const void *buffer_with_final_data_to_file() BOOST_OVERRIDE - { return &m_sem_count; } - - virtual const void *buffer_with_init_data_to_file() BOOST_OVERRIDE - { return &m_sem_count; } - - virtual void *buffer_to_store_init_data_from_file() BOOST_OVERRIDE - { return &m_sem_count; } - - virtual bool open(create_enum_t, const char *id_name) BOOST_OVERRIDE - { - std::string aux_str = "Global\\bipc.sem."; - aux_str += id_name; - // - permissions sem_perm; - sem_perm.set_unrestricted(); - bool created; - return m_sem_wrapper.open_or_create - ( aux_str.c_str(), static_cast(m_sem_count) - , winapi_semaphore_wrapper::MaxCount, sem_perm, created); - } - - virtual bool open(create_enum_t, const wchar_t *id_name) BOOST_OVERRIDE - { - std::wstring aux_str = L"Global\\bipc.sem."; - aux_str += id_name; - // - permissions sem_perm; - sem_perm.set_unrestricted(); - bool created; - return m_sem_wrapper.open_or_create - ( aux_str.c_str(), static_cast(m_sem_count) - , winapi_semaphore_wrapper::MaxCount, sem_perm, created); - } - - virtual void close() BOOST_OVERRIDE - { - m_sem_wrapper.close(); - } - - virtual ~named_sem_callbacks() BOOST_OVERRIDE - {} - - private: - winapi_semaphore_wrapper& m_sem_wrapper; - sem_count_t m_sem_count; - }; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline winapi_named_semaphore::~winapi_named_semaphore() -{ - named_sem_callbacks callbacks(m_sem_wrapper, m_sem_wrapper.value()); - m_named_sync.close(callbacks); -} - -inline void winapi_named_semaphore::dont_close_on_destruction() -{} - -inline winapi_named_semaphore::winapi_named_semaphore - (create_only_t, const char *name, unsigned int initial_count, const permissions &perm) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, initial_count); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline winapi_named_semaphore::winapi_named_semaphore - (open_or_create_t, const char *name, unsigned int initial_count, const permissions &perm) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, initial_count); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline winapi_named_semaphore::winapi_named_semaphore(open_only_t, const char *name) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, 0); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline winapi_named_semaphore::winapi_named_semaphore - (create_only_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, initial_count); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline winapi_named_semaphore::winapi_named_semaphore - (open_or_create_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, initial_count); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline winapi_named_semaphore::winapi_named_semaphore(open_only_t, const wchar_t *name) - : m_sem_wrapper() -{ - named_sem_callbacks callbacks(m_sem_wrapper, 0); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline void winapi_named_semaphore::post() -{ - m_sem_wrapper.post(); -} - -inline void winapi_named_semaphore::wait() -{ - m_sem_wrapper.wait(); -} - -inline bool winapi_named_semaphore::try_wait() -{ - return m_sem_wrapper.try_wait(); -} - -template -inline bool winapi_named_semaphore::timed_wait(const TimePoint &abs_time) -{ - return m_sem_wrapper.timed_wait(abs_time); -} - -inline bool winapi_named_semaphore::remove(const char *name) -{ - return windows_named_sync::remove(name); -} - -inline bool winapi_named_semaphore::remove(const wchar_t *name) -{ - return windows_named_sync::remove(name); -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/named_sync.hpp b/extern/boost/boost/interprocess/sync/windows/named_sync.hpp deleted file mode 100644 index 28f498c6f73..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/named_sync.hpp +++ /dev/null @@ -1,237 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_SYNC_HPP -#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class windows_named_sync_interface -{ - public: - virtual std::size_t get_data_size() const = 0; - virtual const void *buffer_with_final_data_to_file() = 0; - virtual const void *buffer_with_init_data_to_file() = 0; - virtual void *buffer_to_store_init_data_from_file() = 0; - virtual bool open(create_enum_t creation_type, const char *id_name) = 0; - virtual bool open(create_enum_t creation_type, const wchar_t *id_name) = 0; - virtual void close() = 0; - virtual ~windows_named_sync_interface() = 0; -}; - -inline windows_named_sync_interface::~windows_named_sync_interface() -{} - -class windows_named_sync -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - - //Non-copyable - windows_named_sync(const windows_named_sync &); - windows_named_sync &operator=(const windows_named_sync &); - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - windows_named_sync(); - template - void open_or_create(create_enum_t creation_type, const CharT *name, const permissions &perm, windows_named_sync_interface &sync_interface); - void close(windows_named_sync_interface &sync_interface); - - static bool remove(const char *name); - static bool remove(const wchar_t *name); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - void *m_file_hnd; - - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -inline windows_named_sync::windows_named_sync() - : m_file_hnd(winapi::invalid_handle_value) -{} - -inline void windows_named_sync::close(windows_named_sync_interface &sync_interface) -{ - const std::size_t buflen = sync_interface.get_data_size(); - winapi::interprocess_overlapped overlapped; - if(winapi::lock_file_ex - (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){ - if(winapi::set_file_pointer(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ - const void *buf = sync_interface.buffer_with_final_data_to_file(); - - unsigned long written_or_read = 0; - if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){ - //... - } - } - } - sync_interface.close(); - //close_handle unlocks the lock - if(m_file_hnd != winapi::invalid_handle_value){ - winapi::close_handle(m_file_hnd); - m_file_hnd = winapi::invalid_handle_value; - } -} - -template -inline void windows_named_sync::open_or_create - ( create_enum_t creation_type - , const CharT *name - , const permissions &perm - , windows_named_sync_interface &sync_interface) -{ - std::basic_string aux_str(name); - m_file_hnd = winapi::invalid_handle_value; - //Use a file to emulate POSIX lifetime semantics. After this logic - //we'll obtain the ID of the native handle to open in aux_str - { - create_shared_dir_cleaning_old_and_get_filepath(name, aux_str); - //Create a file with required permissions. - m_file_hnd = winapi::create_file - ( aux_str.c_str() - , winapi::generic_read | winapi::generic_write - , creation_type == DoOpen ? winapi::open_existing : - (creation_type == DoCreate ? winapi::create_new : winapi::open_always) - , 0 - , (winapi::interprocess_security_attributes*)perm.get_permissions()); - - //Obtain OS error in case something has failed - error_info err; - bool success = false; - if(m_file_hnd != winapi::invalid_handle_value){ - //Now lock the file - const std::size_t buflen = sync_interface.get_data_size(); - typedef __int64 unique_id_type; - const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen; - winapi::interprocess_overlapped overlapped; - if(winapi::lock_file_ex - (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){ - __int64 filesize = 0; - //Obtain the unique id to open the native semaphore. - //If file size was created - if(winapi::get_file_size(m_file_hnd, filesize)){ - unsigned long written_or_read = 0; - unique_id_type unique_id_val; - if(static_cast(filesize) != sizeof_file_info){ - winapi::set_end_of_file(m_file_hnd); - winapi::query_performance_counter(&unique_id_val); - const void *buf = sync_interface.buffer_with_init_data_to_file(); - //Write unique ID in file. This ID will be used to calculate the semaphore name - if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && - written_or_read == sizeof(unique_id_val) && - winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) && - written_or_read == buflen ){ - success = true; - } - winapi::get_file_size(m_file_hnd, filesize); - BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info); - } - else{ - void *buf = sync_interface.buffer_to_store_init_data_from_file(); - if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) && - written_or_read == sizeof(unique_id_val) && - winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) && - written_or_read == buflen ){ - success = true; - } - } - if(success){ - //Now create a global semaphore name based on the unique id - CharT unique_id_name[sizeof(unique_id_val)*2+1]; - std::size_t name_suffix_length = sizeof(unique_id_name); - bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length); - success = sync_interface.open(creation_type, unique_id_name); - } - } - - //Obtain OS error in case something has failed - if(!success) - err = system_error_code(); - - //If this fails we have no possible rollback so don't check the return - if(!winapi::unlock_file_ex(m_file_hnd, 0, 1, 0, &overlapped)){ - err = system_error_code(); - } - } - else{ - //Obtain OS error in case something has failed - err = system_error_code(); - } - } - else{ - err = system_error_code(); - } - - if(!success){ - if(m_file_hnd != winapi::invalid_handle_value){ - winapi::close_handle(m_file_hnd); - m_file_hnd = winapi::invalid_handle_value; - } - //Throw as something went wrong - throw interprocess_exception(err); - } - } -} - -inline bool windows_named_sync::remove(const char *name) -{ - BOOST_TRY{ - //Make sure a temporary path is created for shared memory - std::string semfile; - ipcdetail::shared_filepath(name, semfile); - return winapi::unlink_file(semfile.c_str()); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END -} - -inline bool windows_named_sync::remove(const wchar_t *name) -{ - BOOST_TRY{ - //Make sure a temporary path is created for shared memory - std::wstring semfile; - ipcdetail::shared_filepath(name, semfile); - return winapi::unlink_file(semfile.c_str()); - } - BOOST_CATCH(...){ - return false; - } BOOST_CATCH_END -} - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp b/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp deleted file mode 100644 index 900904d809f..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/recursive_mutex.hpp +++ /dev/null @@ -1,47 +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_WINDOWS_RECURSIVE_MUTEX_HPP -#define BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -//Windows mutex is already recursive -class winapi_recursive_mutex - : public winapi_mutex -{ - winapi_recursive_mutex(const winapi_recursive_mutex &); - winapi_recursive_mutex &operator=(const winapi_recursive_mutex &); - public: - winapi_recursive_mutex() : winapi_mutex() {} -}; - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_RECURSIVE_MUTEX_HPP diff --git a/extern/boost/boost/interprocess/sync/windows/semaphore.hpp b/extern/boost/boost/interprocess/sync/windows/semaphore.hpp deleted file mode 100644 index 888ab71a0c2..00000000000 --- a/extern/boost/boost/interprocess/sync/windows/semaphore.hpp +++ /dev/null @@ -1,119 +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_WINDOWS_SEMAPHORE_HPP -#define BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace interprocess { -namespace ipcdetail { - -class winapi_semaphore -{ - winapi_semaphore(const winapi_semaphore &); - winapi_semaphore &operator=(const winapi_semaphore &); - public: - - winapi_semaphore(unsigned int initialCount); - ~winapi_semaphore(); - - void post(unsigned int release_count = 1); - void wait(); - bool try_wait(); - template bool timed_wait(const TimePoint &abs_time); - - private: - const sync_id id_; - const unsigned initial_count_; -}; - -inline winapi_semaphore::winapi_semaphore(unsigned int initialCount) - : id_(), initial_count_(initialCount) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //Force smeaphore creation with the initial count - bool 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 winapi_semaphore::~winapi_semaphore() -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - handles.destroy_handle(this->id_, this); -} - -inline void winapi_semaphore::wait() -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); - sem.wait(); -} - -inline bool winapi_semaphore::try_wait() -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); - return sem.try_wait(); -} - -template -inline bool winapi_semaphore::timed_wait(const TimePoint &abs_time) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - //This can throw - winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); - return sem.timed_wait(abs_time); -} - -inline void winapi_semaphore::post(unsigned release_count) -{ - sync_handles &handles = - windows_intermodule_singleton::get(); - winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_)); - sem.post(static_cast(release_count)); -} - - -} //namespace ipcdetail { -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_SEMAPHORE_HPP diff --git a/extern/boost/boost/interprocess/windows_shared_memory.hpp b/extern/boost/boost/interprocess/windows_shared_memory.hpp deleted file mode 100644 index eb4bdf926cf..00000000000 --- a/extern/boost/boost/interprocess/windows_shared_memory.hpp +++ /dev/null @@ -1,277 +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_WINDOWS_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_WINDOWS) -#error "This header can only be used in Windows operating systems" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -//!\file -//!Describes a class representing a native windows shared memory. - -namespace boost { -namespace interprocess { - -//!A class that wraps the native Windows shared memory -//!that is implemented as a file mapping of the paging file. -//!Unlike shared_memory_object, windows_shared_memory has -//!no kernel persistence and the shared memory is destroyed -//!when all processes destroy all their windows_shared_memory -//!objects and mapped regions for the same shared memory -//!or the processes end/crash. -//! -//!Warning: Windows native shared memory and interprocess portable -//!shared memory (boost::interprocess::shared_memory_object) -//!can't communicate between them. -class windows_shared_memory -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable and non-assignable - BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Default constructor. - //!Represents an empty windows_shared_memory. - windows_shared_memory() BOOST_NOEXCEPT; - - //!Creates a new native shared memory with name "name" and at least size "size", - //!with the access mode "mode". - //!If the file previously exists, throws an error. - windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } - - //!Tries to create a shared memory object with name "name" and at least size "size", with the - //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". - //!Otherwise throws an error. - windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, 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. - windows_shared_memory(open_only_t, const char *name, mode_t mode) - { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } - - //!Creates a new native shared memory with name "name" and at least size "size", - //!with the access mode "mode". - //!If the file previously exists, throws an error. - windows_shared_memory(create_only_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } - - //!Tries to create a shared memory object with name "name" and at least size "size", with the - //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". - //!Otherwise throws an error. - windows_shared_memory(open_or_create_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, 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. - windows_shared_memory(open_only_t, const wchar_t *name, mode_t mode) - { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } - - //!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 - windows_shared_memory(BOOST_RV_REF(windows_shared_memory) moved) BOOST_NOEXCEPT - : m_handle(0) - { this->swap(moved); } - - //!Moves the ownership of "moved"'s shared memory to *this. - //!After the call, "moved" does not represent any shared memory. - //!Does not throw - windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved) BOOST_NOEXCEPT - { - windows_shared_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps to shared_memory_objects. Does not throw - void swap(windows_shared_memory &other) BOOST_NOEXCEPT; - - //!Destroys *this. All mapped regions are still valid after - //!destruction. When all mapped regions and windows_shared_memory - //!objects referring the shared memory are destroyed, the - //!operating system will destroy the shared memory. - ~windows_shared_memory(); - - //!Returns the name of the shared memory. - const char *get_name() const BOOST_NOEXCEPT; - - //!Returns access mode - mode_t get_mode() const BOOST_NOEXCEPT; - - //!Returns the mapping handle. Never throws - mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; - - //!Returns the size of the windows shared memory. It will be a 4K rounded - //!size of the "size" passed in the constructor. - offset_t get_size() const BOOST_NOEXCEPT; - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - //!Closes a previously opened file mapping. Never throws. - void priv_close(); - - //!Closes a previously opened file mapping. Never throws. - template - bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm = permissions()); - - void * m_handle; - mode_t m_mode; - char_wchar_holder m_name; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline windows_shared_memory::windows_shared_memory() BOOST_NOEXCEPT - : m_handle(0) -{} - -inline windows_shared_memory::~windows_shared_memory() -{ this->priv_close(); } - -inline const char *windows_shared_memory::get_name() const BOOST_NOEXCEPT -{ return m_name.getn(); } - -inline void windows_shared_memory::swap(windows_shared_memory &other) BOOST_NOEXCEPT -{ - (simple_swap)(m_handle, other.m_handle); - (simple_swap)(m_mode, other.m_mode); - m_name.swap(other.m_name); -} - -inline mapping_handle_t windows_shared_memory::get_mapping_handle() const BOOST_NOEXCEPT -{ mapping_handle_t mhnd = { m_handle, true}; return mhnd; } - -inline mode_t windows_shared_memory::get_mode() const BOOST_NOEXCEPT -{ return m_mode; } - -inline offset_t windows_shared_memory::get_size() const BOOST_NOEXCEPT -{ - offset_t size; //This shall never fail - return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0; -} - -template -inline bool windows_shared_memory::priv_open_or_create - (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm) -{ - if (filename){ - m_name = filename; - } - else{ - m_name = ""; - } - - unsigned long protection = 0; - unsigned long map_access = 0; - - switch(mode) - { - //"protection" is for "create_file_mapping" - //"map_access" is for "open_file_mapping" - //Add section query (strange that read or access does not grant it...) - //to obtain the size of the mapping. copy_on_write is equal to section_query. - case read_only: - protection |= winapi::page_readonly; - map_access |= winapi::file_map_read | winapi::section_query; - break; - case read_write: - protection |= winapi::page_readwrite; - map_access |= winapi::file_map_write | winapi::section_query; - break; - case copy_on_write: - protection |= winapi::page_writecopy; - map_access |= winapi::file_map_copy; - break; - default: - { - error_info err(mode_error); - throw interprocess_exception(err); - } - break; - } - - switch(type){ - case ipcdetail::DoOpen: - m_handle = winapi::open_file_mapping(map_access, filename); - break; - case ipcdetail::DoCreate: - case ipcdetail::DoOpenOrCreate: - { - m_handle = winapi::create_file_mapping - ( winapi::invalid_handle_value, protection, size, filename - , (winapi::interprocess_security_attributes*)perm.get_permissions()); - } - break; - default: - { - error_info err = other_error; - throw interprocess_exception(err); - } - } - - if(!m_handle || (type == ipcdetail::DoCreate && winapi::get_last_error() == winapi::error_already_exists)){ - error_info err = system_error_code(); - this->priv_close(); - throw interprocess_exception(err); - } - - m_mode = mode; - return true; -} - -inline void windows_shared_memory::priv_close() -{ - if(m_handle){ - winapi::close_handle(m_handle); - m_handle = 0; - } -} - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP diff --git a/extern/boost/boost/interprocess/xsi_key.hpp b/extern/boost/boost/interprocess/xsi_key.hpp deleted file mode 100644 index 2dbfa66fc5a..00000000000 --- a/extern/boost/boost/interprocess/xsi_key.hpp +++ /dev/null @@ -1,101 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009. 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_XSI_KEY_HPP -#define BOOST_INTERPROCESS_XSI_KEY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include -#include - -#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) -#error "This header can't be used in operating systems without XSI (System V) shared memory support" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//!\file -//!Describes a class representing a xsi key type. - -namespace boost { -namespace interprocess { - -//!A class that wraps XSI (System V) key_t type. -//!This type calculates key_t from path and id using ftok, -//!sets key to a specified value, -//!or sets key to IPC_PRIVATE using the default constructor. -class xsi_key -{ - public: - - //!Default constructor. - //!Represents a private xsi_key. - xsi_key() - : m_key(IPC_PRIVATE) - {} - - //!Creates a new XSI key using a specified value. Constructor is explicit to avoid ambiguity with shmid. - explicit xsi_key(key_t key) - : m_key(key) - {} - - //!Creates a new XSI shared memory with a key obtained from a call to ftok (with path - //!"path" and id "id"), of size "size" and permissions "perm". - //!If the shared memory previously exists, throws an error. - xsi_key(const char *path, boost::uint8_t id) - { - key_t key; - if(path){ - key = ::ftok(path, id); - if(((key_t)-1) == key){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } - else{ - key = IPC_PRIVATE; - } - m_key = key; - } - - //!Returns the internal key_t value - key_t get_key() const - { return m_key; } - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - key_t m_key; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_XSI_KEY_HPP diff --git a/extern/boost/boost/interprocess/xsi_shared_memory.hpp b/extern/boost/boost/interprocess/xsi_shared_memory.hpp deleted file mode 100644 index 9479f0d0acc..00000000000 --- a/extern/boost/boost/interprocess/xsi_shared_memory.hpp +++ /dev/null @@ -1,215 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2009-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_XSI_SHARED_MEMORY_HPP -#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP - -#ifndef BOOST_CONFIG_HPP -# include -#endif -# -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include -#include - -#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) -#error "This header can't be used in operating systems without XSI (System V) shared memory support" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -// move -#include -// other boost -#include -// std -#include -// OS -#include - - -//!\file -//!Describes a class representing a native xsi shared memory. - -namespace boost { -namespace interprocess { - -//!A class that wraps XSI (System V) shared memory. -//!Unlike shared_memory_object, xsi_shared_memory needs a valid -//!xsi_key to identify a shared memory object. -//! -//!Warning: XSI shared memory and interprocess portable -//!shared memory (boost::interprocess::shared_memory_object) -//!can't communicate between them. -class xsi_shared_memory -{ - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - //Non-copyable and non-assignable - BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory) - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - - public: - //!Default constructor. - //!Represents an empty xsi_shared_memory. - xsi_shared_memory() BOOST_NOEXCEPT; - - //!Initializes *this with a shmid previously obtained (possibly from another process) - //!This lower-level initializer allows shared memory mapping without having a key. - xsi_shared_memory(open_only_t, int shmid) - : m_shmid (shmid) - {} - - //!Creates a new XSI shared memory from 'key', with size "size" and permissions "perm". - //!If the shared memory previously exists, throws an error. - xsi_shared_memory(create_only_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoCreate, key, perm, size); } - - //!Opens an existing shared memory with identifier 'key' or creates a new XSI shared memory from - //!identifier 'key', with size "size" and permissions "perm". - xsi_shared_memory(open_or_create_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) - { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, key, perm, size); } - - //!Tries to open a XSI shared memory with identifier 'key' - //!If the shared memory does not previously exist, it throws an error. - xsi_shared_memory(open_only_t, const xsi_key &key) - { this->priv_open_or_create(ipcdetail::DoOpen, key, permissions(), 0); } - - //!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 - xsi_shared_memory(BOOST_RV_REF(xsi_shared_memory) moved) BOOST_NOEXCEPT - : m_shmid(-1) - { this->swap(moved); } - - //!Moves the ownership of "moved"'s shared memory to *this. - //!After the call, "moved" does not represent any shared memory. - //!Does not throw - xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved) BOOST_NOEXCEPT - { - xsi_shared_memory tmp(boost::move(moved)); - this->swap(tmp); - return *this; - } - - //!Swaps two xsi_shared_memorys. Does not throw - void swap(xsi_shared_memory &other) BOOST_NOEXCEPT; - - //!Destroys *this. The shared memory won't be destroyed, just - //!this connection to it. Use remove() to destroy the shared memory. - ~xsi_shared_memory(); - - //!Returns the shared memory ID that - //!identifies the shared memory - int get_shmid() const BOOST_NOEXCEPT; - - //!Returns the mapping handle. - //!Never throws - mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT; - - //!Erases the XSI shared memory object identified by shmid - //!from the system. - //!Returns false on error. Never throws - static bool remove(int shmid); - - #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - private: - - //!Closes a previously opened file mapping. Never throws. - bool priv_open_or_create( ipcdetail::create_enum_t type - , const xsi_key &key - , const permissions& perm - , std::size_t size); - int m_shmid; - #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED -}; - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) - -inline xsi_shared_memory::xsi_shared_memory() BOOST_NOEXCEPT - : m_shmid(-1) -{} - -inline xsi_shared_memory::~xsi_shared_memory() -{} - -inline int xsi_shared_memory::get_shmid() const BOOST_NOEXCEPT -{ return m_shmid; } - -inline void xsi_shared_memory::swap(xsi_shared_memory &other) BOOST_NOEXCEPT -{ - (simple_swap)(m_shmid, other.m_shmid); -} - -inline mapping_handle_t xsi_shared_memory::get_mapping_handle() const BOOST_NOEXCEPT -{ mapping_handle_t mhnd = { m_shmid, true}; return mhnd; } - -inline bool xsi_shared_memory::priv_open_or_create - (ipcdetail::create_enum_t type, const xsi_key &key, const permissions& permissions, std::size_t size) -{ - int perm = (int)permissions.get_permissions(); - perm &= 0x01FF; - int shmflg = perm; - - switch(type){ - case ipcdetail::DoOpen: - shmflg |= 0; - break; - case ipcdetail::DoCreate: - shmflg |= IPC_CREAT | IPC_EXCL; - break; - case ipcdetail::DoOpenOrCreate: - shmflg |= IPC_CREAT; - break; - default: - { - error_info err = other_error; - throw interprocess_exception(err); - } - } - - int ret = ::shmget(key.get_key(), size, shmflg); - int shmid = ret; - if((type == ipcdetail::DoOpen) && (-1 != ret)){ - //Now get the size - ::shmid_ds xsi_ds; - ret = ::shmctl(ret, IPC_STAT, &xsi_ds); - size = xsi_ds.shm_segsz; - } - if(-1 == ret){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - - m_shmid = shmid; - return true; -} - -inline bool xsi_shared_memory::remove(int shmid) -{ return -1 != ::shmctl(shmid, IPC_RMID, 0); } - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - -} //namespace interprocess { -} //namespace boost { - -#include - -#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP