summaryrefslogtreecommitdiff
path: root/boost/interprocess
diff options
context:
space:
mode:
Diffstat (limited to 'boost/interprocess')
-rw-r--r--boost/interprocess/allocators/adaptive_pool.hpp468
-rw-r--r--boost/interprocess/allocators/allocator.hpp307
-rw-r--r--boost/interprocess/allocators/cached_adaptive_pool.hpp356
-rw-r--r--boost/interprocess/allocators/cached_node_allocator.hpp327
-rw-r--r--boost/interprocess/allocators/detail/adaptive_node_pool.hpp108
-rw-r--r--boost/interprocess/allocators/detail/allocator_common.hpp862
-rw-r--r--boost/interprocess/allocators/detail/node_pool.hpp109
-rw-r--r--boost/interprocess/allocators/detail/node_tools.hpp50
-rw-r--r--boost/interprocess/allocators/node_allocator.hpp452
-rw-r--r--boost/interprocess/allocators/private_adaptive_pool.hpp468
-rw-r--r--boost/interprocess/allocators/private_node_allocator.hpp445
-rw-r--r--boost/interprocess/anonymous_shared_memory.hpp119
-rw-r--r--boost/interprocess/containers/allocation_type.hpp40
-rw-r--r--boost/interprocess/containers/containers_fwd.hpp40
-rw-r--r--boost/interprocess/containers/deque.hpp33
-rw-r--r--boost/interprocess/containers/flat_map.hpp33
-rw-r--r--boost/interprocess/containers/flat_set.hpp33
-rw-r--r--boost/interprocess/containers/list.hpp33
-rw-r--r--boost/interprocess/containers/map.hpp33
-rw-r--r--boost/interprocess/containers/pair.hpp34
-rw-r--r--boost/interprocess/containers/set.hpp33
-rw-r--r--boost/interprocess/containers/slist.hpp32
-rw-r--r--boost/interprocess/containers/stable_vector.hpp32
-rw-r--r--boost/interprocess/containers/string.hpp33
-rw-r--r--boost/interprocess/containers/vector.hpp33
-rw-r--r--boost/interprocess/containers/version_type.hpp33
-rw-r--r--boost/interprocess/creation_tags.hpp77
-rw-r--r--boost/interprocess/detail/atomic.hpp593
-rw-r--r--boost/interprocess/detail/cast_tags.hpp29
-rw-r--r--boost/interprocess/detail/config_begin.hpp47
-rw-r--r--boost/interprocess/detail/config_end.hpp17
-rw-r--r--boost/interprocess/detail/file_wrapper.hpp202
-rw-r--r--boost/interprocess/detail/in_place_interface.hpp73
-rw-r--r--boost/interprocess/detail/intermodule_singleton.hpp1184
-rw-r--r--boost/interprocess/detail/interprocess_tester.hpp31
-rw-r--r--boost/interprocess/detail/intersegment_ptr.hpp1040
-rw-r--r--boost/interprocess/detail/managed_memory_impl.hpp750
-rw-r--r--boost/interprocess/detail/managed_multi_shared_memory.hpp408
-rw-r--r--boost/interprocess/detail/managed_open_or_create_impl.hpp483
-rw-r--r--boost/interprocess/detail/math_functions.hpp110
-rw-r--r--boost/interprocess/detail/min_max.hpp40
-rw-r--r--boost/interprocess/detail/move.hpp28
-rw-r--r--boost/interprocess/detail/mpl.hpp152
-rw-r--r--boost/interprocess/detail/multi_segment_services.hpp46
-rw-r--r--boost/interprocess/detail/named_proxy.hpp349
-rw-r--r--boost/interprocess/detail/os_file_functions.hpp696
-rw-r--r--boost/interprocess/detail/os_thread_functions.hpp211
-rw-r--r--boost/interprocess/detail/pointer_type.hpp74
-rw-r--r--boost/interprocess/detail/posix_time_types_wrk.hpp42
-rw-r--r--boost/interprocess/detail/preprocessor.hpp137
-rw-r--r--boost/interprocess/detail/ptime_wrk.hpp33
-rw-r--r--boost/interprocess/detail/robust_emulation.hpp439
-rw-r--r--boost/interprocess/detail/segment_manager_helper.hpp513
-rw-r--r--boost/interprocess/detail/tmp_dir_helpers.hpp174
-rw-r--r--boost/interprocess/detail/transform_iterator.hpp195
-rw-r--r--boost/interprocess/detail/type_traits.hpp145
-rw-r--r--boost/interprocess/detail/utilities.hpp160
-rw-r--r--boost/interprocess/detail/variadic_templates_tools.hpp153
-rw-r--r--boost/interprocess/detail/win32_api.hpp1766
-rw-r--r--boost/interprocess/detail/workaround.hpp148
-rw-r--r--boost/interprocess/detail/xsi_shared_memory_device.hpp392
-rw-r--r--boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp80
-rw-r--r--boost/interprocess/errors.hpp236
-rw-r--r--boost/interprocess/exceptions.hpp150
-rw-r--r--boost/interprocess/file_mapping.hpp184
-rw-r--r--boost/interprocess/indexes/flat_map_index.hpp78
-rw-r--r--boost/interprocess/indexes/iset_index.hpp150
-rw-r--r--boost/interprocess/indexes/iunordered_set_index.hpp368
-rw-r--r--boost/interprocess/indexes/map_index.hpp100
-rw-r--r--boost/interprocess/indexes/null_index.hpp68
-rw-r--r--boost/interprocess/indexes/unordered_map_index.hpp113
-rw-r--r--boost/interprocess/interprocess_fwd.hpp418
-rw-r--r--boost/interprocess/ipc/message_queue.hpp704
-rw-r--r--boost/interprocess/managed_external_buffer.hpp113
-rw-r--r--boost/interprocess/managed_heap_memory.hpp148
-rw-r--r--boost/interprocess/managed_mapped_file.hpp217
-rw-r--r--boost/interprocess/managed_shared_memory.hpp221
-rw-r--r--boost/interprocess/managed_windows_shared_memory.hpp194
-rw-r--r--boost/interprocess/managed_xsi_shared_memory.hpp198
-rw-r--r--boost/interprocess/mapped_region.hpp605
-rw-r--r--boost/interprocess/mem_algo/detail/mem_algo_common.hpp554
-rw-r--r--boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp61
-rw-r--r--boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp983
-rw-r--r--boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp1122
-rw-r--r--boost/interprocess/mem_algo/rbtree_best_fit.hpp1416
-rw-r--r--boost/interprocess/mem_algo/simple_seq_fit.hpp58
-rw-r--r--boost/interprocess/offset_ptr.hpp528
-rw-r--r--boost/interprocess/permissions.hpp132
-rw-r--r--boost/interprocess/segment_manager.hpp1365
-rw-r--r--boost/interprocess/shared_memory_object.hpp422
-rw-r--r--boost/interprocess/smart_ptr/deleter.hpp64
-rw-r--r--boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp44
-rw-r--r--boost/interprocess/smart_ptr/detail/shared_count.hpp338
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_base.hpp18
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp92
-rw-r--r--boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp155
-rw-r--r--boost/interprocess/smart_ptr/enable_shared_from_this.hpp79
-rw-r--r--boost/interprocess/smart_ptr/intrusive_ptr.hpp296
-rw-r--r--boost/interprocess/smart_ptr/scoped_ptr.hpp164
-rw-r--r--boost/interprocess/smart_ptr/shared_ptr.hpp417
-rw-r--r--boost/interprocess/smart_ptr/unique_ptr.hpp551
-rw-r--r--boost/interprocess/smart_ptr/weak_ptr.hpp260
-rw-r--r--boost/interprocess/streams/bufferstream.hpp444
-rw-r--r--boost/interprocess/streams/vectorstream.hpp601
-rw-r--r--boost/interprocess/sync/file_lock.hpp305
-rw-r--r--boost/interprocess/sync/interprocess_condition.hpp172
-rw-r--r--boost/interprocess/sync/interprocess_mutex.hpp170
-rw-r--r--boost/interprocess/sync/interprocess_recursive_mutex.hpp177
-rw-r--r--boost/interprocess/sync/interprocess_semaphore.hpp145
-rw-r--r--boost/interprocess/sync/interprocess_upgradable_mutex.hpp659
-rw-r--r--boost/interprocess/sync/lock_options.hpp55
-rw-r--r--boost/interprocess/sync/mutex_family.hpp56
-rw-r--r--boost/interprocess/sync/named_condition.hpp172
-rw-r--r--boost/interprocess/sync/named_mutex.hpp163
-rw-r--r--boost/interprocess/sync/named_recursive_mutex.hpp154
-rw-r--r--boost/interprocess/sync/named_semaphore.hpp168
-rw-r--r--boost/interprocess/sync/named_upgradable_mutex.hpp372
-rw-r--r--boost/interprocess/sync/null_mutex.hpp147
-rw-r--r--boost/interprocess/sync/posix/condition.hpp191
-rw-r--r--boost/interprocess/sync/posix/mutex.hpp152
-rw-r--r--boost/interprocess/sync/posix/named_mutex.hpp116
-rw-r--r--boost/interprocess/sync/posix/named_semaphore.hpp84
-rw-r--r--boost/interprocess/sync/posix/pthread_helpers.hpp168
-rw-r--r--boost/interprocess/sync/posix/ptime_to_timespec.hpp38
-rw-r--r--boost/interprocess/sync/posix/recursive_mutex.hpp142
-rw-r--r--boost/interprocess/sync/posix/semaphore.hpp63
-rw-r--r--boost/interprocess/sync/posix/semaphore_wrapper.hpp211
-rw-r--r--boost/interprocess/sync/scoped_lock.hpp372
-rw-r--r--boost/interprocess/sync/sharable_lock.hpp305
-rw-r--r--boost/interprocess/sync/shm/named_condition.hpp379
-rw-r--r--boost/interprocess/sync/shm/named_creation_functor.hpp68
-rw-r--r--boost/interprocess/sync/shm/named_mutex.hpp184
-rw-r--r--boost/interprocess/sync/shm/named_recursive_mutex.hpp175
-rw-r--r--boost/interprocess/sync/shm/named_semaphore.hpp141
-rw-r--r--boost/interprocess/sync/shm/named_upgradable_mutex.hpp372
-rw-r--r--boost/interprocess/sync/spin/condition.hpp295
-rw-r--r--boost/interprocess/sync/spin/interprocess_barrier.hpp46
-rw-r--r--boost/interprocess/sync/spin/mutex.hpp114
-rw-r--r--boost/interprocess/sync/spin/recursive_mutex.hpp175
-rw-r--r--boost/interprocess/sync/spin/semaphore.hpp110
-rw-r--r--boost/interprocess/sync/upgradable_lock.hpp309
-rw-r--r--boost/interprocess/sync/windows/condition.hpp383
-rw-r--r--boost/interprocess/sync/windows/mutex.hpp137
-rw-r--r--boost/interprocess/sync/windows/recursive_mutex.hpp43
-rw-r--r--boost/interprocess/sync/windows/semaphore.hpp137
-rw-r--r--boost/interprocess/sync/windows/sync_utils.hpp173
-rw-r--r--boost/interprocess/sync/xsi/advanced_xsi_semaphore.hpp193
-rw-r--r--boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp116
-rw-r--r--boost/interprocess/sync/xsi/xsi_named_mutex.hpp228
-rw-r--r--boost/interprocess/windows_shared_memory.hpp232
-rw-r--r--boost/interprocess/xsi_key.hpp87
-rw-r--r--boost/interprocess/xsi_shared_memory.hpp201
152 files changed, 39047 insertions, 0 deletions
diff --git a/boost/interprocess/allocators/adaptive_pool.hpp b/boost/interprocess/allocators/adaptive_pool.hpp
new file mode 100644
index 0000000..846df5d
--- /dev/null
+++ b/boost/interprocess/allocators/adaptive_pool.hpp
@@ -0,0 +1,468 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes adaptive_pool pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+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
+ <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t;
+
+ /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef ipcdetail::shared_adaptive_node_pool
+ < SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+ /// @endcond
+
+ BOOST_STATIC_ASSERT((Version <=2));
+
+ public:
+ //-------
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename segment_manager::size_type size_type;
+ typedef typename segment_manager::difference_type difference_type;
+
+ typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+ //!Obtains adaptive_pool_base from
+ //!adaptive_pool_base
+ template<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ /// @cond
+ private:
+ //!Not assignable from related adaptive_pool_base
+ template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
+ adaptive_pool_base& operator=
+ (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
+
+ /// @endcond
+
+ 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<typename node_pool<0>::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);
+ 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<class T2>
+ adaptive_pool_base
+ (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+ : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::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)
+ { ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
+
+ /// @cond
+ private:
+ void_pointer mp_node_pool;
+ /// @endcond
+};
+
+//!Equality test for same type
+//!of adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+ const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
+ { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type
+//!of adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+ const adaptive_pool_base<V, T, S, NPC, F, OP> &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<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ adaptive_pool_v1(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ adaptive_pool_v1
+ (const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail{
+
+/// @endcond
+
+//!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
+ /// @cond
+ : public ipcdetail::adaptive_pool_base
+ < 2
+ , T
+ , SegmentManager
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ /// @endcond
+{
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ typedef ipcdetail::adaptive_pool_base
+ < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
+ public:
+ typedef boost::interprocess::version_type<adaptive_pool, 2> version;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ adaptive_pool(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ adaptive_pool
+ (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related adaptive_pool
+ template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+ adaptive_pool& operator=
+ (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
+
+ //!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<class T2>
+ adaptive_pool
+ (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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);
+ #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
+
diff --git a/boost/interprocess/allocators/allocator.hpp b/boost/interprocess/allocators/allocator.hpp
new file mode 100644
index 0000000..aa4b22d
--- /dev/null
+++ b/boost/interprocess/allocators/allocator.hpp
@@ -0,0 +1,307 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/containers/allocation_type.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+#include <memory>
+#include <new>
+#include <algorithm>
+#include <cstddef>
+#include <stdexcept>
+
+//!\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 T, class SegmentManager>
+class allocator
+{
+ public:
+ //Segment manager
+ typedef SegmentManager segment_manager;
+ typedef typename SegmentManager::void_pointer void_pointer;
+
+ /// @cond
+ private:
+
+ //Self type
+ typedef allocator<T, SegmentManager> 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<aux_pointer_t>::template
+ rebind_pointer<const void>::type cvoid_ptr;
+
+ //Pointer to the allocator
+ typedef typename boost::intrusive::
+ pointer_traits<cvoid_ptr>::template
+ rebind_pointer<segment_manager>::type alloc_ptr_t;
+
+ //Not assignable from related allocator
+ template<class T2, class SegmentManager2>
+ allocator& operator=(const allocator<T2, SegmentManager2>&);
+
+ //Not assignable from other allocator
+ allocator& operator=(const allocator&);
+
+ //Pointer to the allocator
+ alloc_ptr_t mp_mngr;
+ /// @endcond
+
+ public:
+ typedef T value_type;
+ typedef typename boost::intrusive::
+ pointer_traits<cvoid_ptr>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename segment_manager::size_type size_type;
+ typedef typename segment_manager::difference_type difference_type;
+
+ typedef boost::interprocess::version_type<allocator, 2> version;
+
+ /// @cond
+
+ //Experimental. Don't use.
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+ /// @endcond
+
+ //!Obtains an allocator that allocates
+ //!objects of type T2
+ template<class T2>
+ struct rebind
+ {
+ typedef allocator<T2, SegmentManager> 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<class T2>
+ allocator(const allocator<T2, SegmentManager> &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(count > this->max_size())
+ throw bad_alloc();
+ return pointer(static_cast<value_type*>(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)
+ { ipcdetail::do_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);
+ }
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0)
+ {
+ return mp_mngr->allocation_command
+ (command, limit_size, preferred_size, received_size, ipcdetail::to_raw_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(...)
+ multiallocation_chain allocate_many
+ (size_type elem_size, size_type num_elements)
+ {
+ return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many
+ (const size_type *elem_sizes, size_type n_elements)
+ {
+ multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
+ }
+
+ //!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)
+ {
+ return mp_mngr->deallocate_many(chain.extract_multiallocation_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().
+ multiallocation_chain allocate_individual
+ (size_type num_elements)
+ { return this->allocate_many(1, 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)
+ { 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)
+ { return this->deallocate_many(boost::move(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)); }
+
+ //!Constructs an object
+ //!Throws if T's constructor throws
+ //!For backwards compatibility with libraries using C++03 allocators
+ template<class P>
+ void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
+ { ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p)); }
+
+ //!Destroys object. Throws if object's
+ //!destructor throws
+ void destroy(const pointer &ptr)
+ { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
+
+};
+
+//!Equality test for same type
+//!of allocator
+template<class T, class SegmentManager> inline
+bool operator==(const allocator<T , SegmentManager> &alloc1,
+ const allocator<T, SegmentManager> &alloc2)
+ { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); }
+
+//!Inequality test for same type
+//!of allocator
+template<class T, class SegmentManager> inline
+bool operator!=(const allocator<T, SegmentManager> &alloc1,
+ const allocator<T, SegmentManager> &alloc2)
+ { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
+
+} //namespace interprocess {
+
+/// @cond
+
+template<class T>
+struct has_trivial_destructor;
+
+template<class T, class SegmentManager>
+struct has_trivial_destructor
+ <boost::interprocess::allocator <T, SegmentManager> >
+{
+ static const bool value = true;
+};
+/// @endcond
+
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP
+
diff --git a/boost/interprocess/allocators/cached_adaptive_pool.hpp b/boost/interprocess/allocators/cached_adaptive_pool.hpp
new file mode 100644
index 0000000..bec1050
--- /dev/null
+++ b/boost/interprocess/allocators/cached_adaptive_pool.hpp
@@ -0,0 +1,356 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <cstddef>
+
+//!\file
+//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+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<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ , 1>
+{
+ public:
+ typedef ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_adaptive_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ , 1> base_t;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef cached_adaptive_pool_v1
+ <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> 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<class T2>
+ cached_adaptive_pool_v1
+ (const cached_adaptive_pool_v1
+ <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail{
+
+/// @endcond
+
+//!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
+ /// @cond
+ : public ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_adaptive_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ , 2>
+ /// @endcond
+{
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+ typedef ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_adaptive_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ , 2> base_t;
+
+ public:
+ typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef cached_adaptive_pool
+ <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> 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<class T2>
+ cached_adaptive_pool
+ (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related cached_adaptive_pool
+ template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+ cached_adaptive_pool& operator=
+ (const cached_adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
+
+ //!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<class T2>
+ cached_adaptive_pool
+ (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
+bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of cached_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
+bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
+
diff --git a/boost/interprocess/allocators/cached_node_allocator.hpp b/boost/interprocess/allocators/cached_node_allocator.hpp
new file mode 100644
index 0000000..0339815
--- /dev/null
+++ b/boost/interprocess/allocators/cached_node_allocator.hpp
@@ -0,0 +1,327 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <cstddef>
+
+//!\file
+//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+
+/// @cond
+
+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<T>::value
+ , NodesPerBlock
+ >
+ , 1>
+{
+ public:
+ typedef ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ >
+ , 1> base_t;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef cached_node_allocator_v1
+ <T2, SegmentManager, NodesPerBlock> 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<class T2>
+ cached_node_allocator_v1
+ (const cached_node_allocator_v1
+ <T2, SegmentManager, NodesPerBlock> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail{
+
+/// @endcond
+
+template < class T
+ , class SegmentManager
+ , std::size_t NodesPerBlock
+ >
+class cached_node_allocator
+ /// @cond
+ : public ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ >
+ , 2>
+ /// @endcond
+{
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ public:
+ typedef ipcdetail::cached_allocator_impl
+ < T
+ , ipcdetail::shared_node_pool
+ < SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ >
+ , 2> base_t;
+
+ public:
+ typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
+ typedef typename base_t::size_type size_type;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock> 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<class T2>
+ cached_node_allocator
+ (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef cached_node_allocator<T2, SegmentManager> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related cached_node_allocator
+ template<class T2, class SegmentManager2, std::size_t N2>
+ cached_node_allocator& operator=
+ (const cached_node_allocator<T2, SegmentManager2, N2>&);
+
+ //!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<class T2>
+ cached_node_allocator
+ (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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<class T, class S, std::size_t NPC> inline
+bool operator==(const cached_node_allocator<T, S, NPC> &alloc1,
+ const cached_node_allocator<T, S, NPC> &alloc2);
+
+//!Inequality test for same type
+//!of cached_node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1,
+ const cached_node_allocator<T, S, NPC> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
+
diff --git a/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
new file mode 100644
index 0000000..4ccc920
--- /dev/null
+++ b/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
@@ -0,0 +1,108 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/math_functions.hpp>
+#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/slist.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <cstddef>
+#include <boost/config/no_tr1/cmath.hpp>
+#include <boost/container/detail/adaptive_node_pool_impl.hpp>
+#include <boost/assert.hpp>
+
+//!\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::container_detail::private_adaptive_node_pool_impl
+ <typename SegmentManager::segment_manager_base_type>
+{
+ typedef boost::container::container_detail::private_adaptive_node_pool_impl
+ <typename SegmentManager::segment_manager_base_type> 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;
+
+ //Deprecated, use node_per_block
+ static const size_type nodes_per_chunk = 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<segment_manager*>(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
+ <SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+ >
+{
+ typedef ipcdetail::shared_pool_impl
+ < private_adaptive_node_pool
+ <SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+ > base_t;
+ public:
+ shared_adaptive_node_pool(SegmentManager *segment_mgnr)
+ : base_t(segment_mgnr)
+ {}
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
diff --git a/boost/interprocess/allocators/detail/allocator_common.hpp b/boost/interprocess/allocators/detail/allocator_common.hpp
new file mode 100644
index 0000000..ea660b1
--- /dev/null
+++ b/boost/interprocess/allocators/detail/allocator_common.hpp
@@ -0,0 +1,862 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/detail/utilities.hpp> //to_raw_pointer
+#include <boost/utility/addressof.hpp> //boost::addressof
+#include <boost/assert.hpp> //BOOST_ASSERT
+#include <boost/interprocess/exceptions.hpp> //bad_alloc
+#include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
+#include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
+#include <boost/interprocess/detail/segment_manager_helper.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <algorithm> //std::swap
+#include <utility> //std::pair
+#include <new>
+
+namespace boost {
+namespace interprocess {
+
+template <class T>
+struct sizeof_value
+{
+ static const std::size_t value = sizeof(T);
+};
+
+template <>
+struct sizeof_value<void>
+{
+ static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<const void>
+{
+ static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<volatile void>
+{
+ static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<const volatile void>
+{
+ 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<class NodePool>
+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
+ <NodePool>(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<class NodePool>
+inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr)
+{
+ ipcdetail::get_or_create_node_pool_func<NodePool> 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<class NodePool>
+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<NodePool>(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<class NodePool>
+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_func<NodePool>func(pool);
+ mngr->atomic_func(func);
+}
+
+template<class NodePool>
+class cache_impl
+{
+ typedef typename NodePool::segment_manager::
+ void_pointer void_pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<NodePool>::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<NodePool>(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()){
+ m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2);
+ }
+ void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front());
+ m_cached_nodes.pop_front();
+ return ret;
+ }
+
+ multiallocation_chain 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.front());
+ m_cached_nodes.pop_front();
+ chain.push_back(ret);
+ ++allocated;
+ }
+
+ if(allocated != n){
+ multiallocation_chain chain2(mp_node_pool->allocate_nodes(n - allocated));
+ chain.splice_after(chain.last(), chain2, chain2.before_begin(), chain2.last(), n - allocated);
+ }
+ return boost::move(chain);
+ }
+ BOOST_CATCH(...){
+ this->cached_deallocation(boost::move(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(boost::move(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(boost::move(chain));
+ }
+
+ public:
+ void swap(cache_impl &other)
+ {
+ ipcdetail::do_swap(mp_node_pool, other.mp_node_pool);
+ m_cached_nodes.swap(other.m_cached_nodes);
+ ipcdetail::do_swap(m_max_cached_nodes, other.m_max_cached_nodes);
+ }
+};
+
+template<class Derived, class T, class SegmentManager>
+class array_allocation_impl
+{
+ const Derived *derived() const
+ { return static_cast<const Derived*>(this); }
+ Derived *derived()
+ { return static_cast<Derived*>(this); }
+
+ typedef typename SegmentManager::void_pointer void_pointer;
+
+ public:
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename SegmentManager::size_type size_type;
+ typedef typename SegmentManager::difference_type difference_type;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>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);
+ }
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0)
+ {
+ return this->derived()->get_segment_manager()->allocation_command
+ (command, limit_size, preferred_size, received_size, ipcdetail::to_raw_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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements)
+ {
+ return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements);
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
+ {
+ return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
+ }
+
+ //!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)
+ { return this->derived()->get_segment_manager()->deallocate_many(boost::move(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<class P>
+ void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
+ { ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p)); }
+
+ //!Destroys object. Throws if object's
+ //!destructor throws
+ void destroy(const pointer &ptr)
+ { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
+};
+
+
+template<class Derived, unsigned int Version, class T, class SegmentManager>
+class node_pool_allocation_impl
+ : public array_allocation_impl
+ < Derived
+ , T
+ , SegmentManager>
+{
+ const Derived *derived() const
+ { return static_cast<const Derived*>(this); }
+ Derived *derived()
+ { return static_cast<Derived*>(this); }
+
+ typedef typename SegmentManager::void_pointer void_pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const void>::type cvoid_pointer;
+
+ public:
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename SegmentManager::size_type size_type;
+ typedef typename SegmentManager::difference_type difference_type;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+
+ template <int Dummy>
+ struct node_pool
+ {
+ typedef typename Derived::template node_pool<0>::type type;
+ static type *get(void *p)
+ { return static_cast<type*>(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(count > this->max_size())
+ throw bad_alloc();
+ else if(Version == 1 && count == 1)
+ return pointer(static_cast<value_type*>
+ (pool->allocate_node()));
+ else
+ return pointer(static_cast<value_type*>
+ (pool->get_segment_manager()->allocate(sizeof(T)*count)));
+ }
+
+ //!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<value_type*>(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().
+ multiallocation_chain allocate_individual(size_type num_elements)
+ {
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+ return multiallocation_chain(pool->allocate_nodes(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)
+ {
+ 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.extract_multiallocation_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 T, class NodePool, unsigned int Version>
+class cached_allocator_impl
+ : public array_allocation_impl
+ <cached_allocator_impl<T, NodePool, Version>, T, typename NodePool::segment_manager>
+{
+ cached_allocator_impl & operator=(const cached_allocator_impl& other);
+ typedef array_allocation_impl
+ < cached_allocator_impl
+ <T, NodePool, Version>
+ , 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<void_pointer>::template
+ rebind_pointer<const void>::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<class T2, class NodePool2>
+ cached_allocator_impl
+ (const cached_allocator_impl
+ <T2, NodePool2, Version> &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(count > this->max_size())
+ throw bad_alloc();
+ else if(Version == 1 && count == 1){
+ ret = m_cache.cached_allocation();
+ }
+ else{
+ ret = this->get_segment_manager()->allocate(sizeof(T)*count);
+ }
+ return pointer(static_cast<T*>(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<value_type*>(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().
+ multiallocation_chain allocate_individual(size_type num_elements)
+ { return multiallocation_chain(this->m_cache.cached_allocation(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)
+ { 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)
+ {
+ typename node_pool_t::multiallocation_chain mem
+ (chain.extract_multiallocation_chain());
+ m_cache.cached_deallocation(boost::move(mem));
+ }
+
+ //!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)
+ { alloc1.m_cache.swap(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(); }
+
+ /// @cond
+ private:
+ cache_impl<node_pool_t> m_cache;
+};
+
+//!Equality test for same type of
+//!cached_allocator_impl
+template<class T, class N, unsigned int V> inline
+bool operator==(const cached_allocator_impl<T, N, V> &alloc1,
+ const cached_allocator_impl<T, N, V> &alloc2)
+ { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type of
+//!cached_allocator_impl
+template<class T, class N, unsigned int V> inline
+bool operator!=(const cached_allocator_impl<T, N, V> &alloc1,
+ const cached_allocator_impl<T, N, V> &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 private_node_allocator_t>
+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<mutex_type> 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<mutex_type> guard(m_header);
+ //-----------------------
+ private_node_allocator_t::deallocate_node(ptr);
+ }
+/*
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ //!can throw boost::interprocess::bad_alloc
+ void allocate_nodes(multiallocation_chain &nodes, size_type n)
+ {
+ //-----------------------
+ boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(nodes, n);
+ }
+*/
+ //!Allocates n nodes.
+ //!Can throw boost::interprocess::bad_alloc
+ multiallocation_chain allocate_nodes(const size_type n)
+ {
+ //-----------------------
+ boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(n);
+ }
+
+ //!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<mutex_type> 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<mutex_type> guard(m_header);
+ //-----------------------
+ private_node_allocator_t::deallocate_nodes(boost::move(chain));
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ //-----------------------
+ boost::interprocess::scoped_lock<mutex_type> 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<mutex_type> 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<mutex_type> 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<mutex_type> 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<mutex_type> guard(m_header);
+ //-----------------------
+ private_node_allocator_t::deallocate_free_blocks();
+ }
+
+ //!Deprecated, use purge_blocks.
+ void purge_chunks()
+ {
+ //-----------------------
+ boost::interprocess::scoped_lock<mutex_type> 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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
diff --git a/boost/interprocess/allocators/detail/node_pool.hpp b/boost/interprocess/allocators/detail/node_pool.hpp
new file mode 100644
index 0000000..7327ff9
--- /dev/null
+++ b/boost/interprocess/allocators/detail/node_pool.hpp
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/slist.hpp>
+#include <boost/math/common_factor_ct.hpp>
+
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/container/detail/node_pool_impl.hpp>
+#include <cstddef>
+
+
+//!\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::container_detail::
+ private_node_pool_impl<typename SegmentManager::segment_manager_base_type>
+{
+ typedef boost::container::container_detail::private_node_pool_impl
+ <typename SegmentManager::segment_manager_base_type> 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<segment_manager*>(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
+ <SegmentManager, NodeSize, NodesPerBlock>
+ >
+{
+ typedef ipcdetail::shared_pool_impl
+ < private_node_pool
+ <SegmentManager, NodeSize, NodesPerBlock>
+ > base_t;
+ public:
+ shared_node_pool(SegmentManager *segment_mgnr)
+ : base_t(segment_mgnr)
+ {}
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
diff --git a/boost/interprocess/allocators/detail/node_tools.hpp b/boost/interprocess/allocators/detail/node_tools.hpp
new file mode 100644
index 0000000..da7e466
--- /dev/null
+++ b/boost/interprocess/allocators/detail/node_tools.hpp
@@ -0,0 +1,50 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/slist.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+template<class VoidPointer>
+struct node_slist
+{
+ //This hook will be used to chain the individual nodes
+ typedef typename bi::make_slist_base_hook
+ <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::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
+ <node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
diff --git a/boost/interprocess/allocators/node_allocator.hpp b/boost/interprocess/allocators/node_allocator.hpp
new file mode 100644
index 0000000..f1c3259
--- /dev/null
+++ b/boost/interprocess/allocators/node_allocator.hpp
@@ -0,0 +1,452 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes node_allocator pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+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
+ <Version, T, SegmentManager, NodesPerBlock> self_t;
+
+ /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef ipcdetail::shared_node_pool
+ < SegmentManager, sizeof_value<T>::value, NodesPerBlock> type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+ /// @endcond
+
+ BOOST_STATIC_ASSERT((Version <=2));
+
+ public:
+ //-------
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename segment_manager::size_type size_type;
+ typedef typename segment_manager::difference_type difference_type;
+
+ typedef boost::interprocess::version_type<node_allocator_base, Version> version;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+ //!Obtains node_allocator_base from
+ //!node_allocator_base
+ template<class T2>
+ struct rebind
+ {
+ typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ /// @cond
+ private:
+ //!Not assignable from related node_allocator_base
+ template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2>
+ node_allocator_base& operator=
+ (const node_allocator_base<Version2, T2, SegmentManager2, N2>&);
+
+ //!Not assignable from other node_allocator_base
+ //node_allocator_base& operator=(const node_allocator_base&);
+ /// @endcond
+
+ 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<typename node_pool<0>::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<class T2>
+ node_allocator_base
+ (const node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> &other)
+ : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::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);
+ 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)
+ { ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
+
+ /// @cond
+ private:
+ void_pointer mp_node_pool;
+ /// @endcond
+};
+
+//!Equality test for same type
+//!of node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1,
+ const node_allocator_base<V, T, S, NPC> &alloc2)
+ { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type
+//!of node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1,
+ const node_allocator_base<V, T, S, NPC> &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<class T2>
+ struct rebind
+ {
+ typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ node_allocator_v1(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ node_allocator_v1
+ (const node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail{
+
+/// @endcond
+
+//!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
+//!needs runs out of nodes
+template < class T
+ , class SegmentManager
+ , std::size_t NodesPerBlock
+ >
+class node_allocator
+ /// @cond
+ : public ipcdetail::node_allocator_base
+ < 2
+ , T
+ , SegmentManager
+ , NodesPerBlock
+ >
+ /// @endcond
+{
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ typedef ipcdetail::node_allocator_base
+ < 2, T, SegmentManager, NodesPerBlock> base_t;
+ public:
+ typedef boost::interprocess::version_type<node_allocator, 2> version;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ node_allocator(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ node_allocator
+ (const node_allocator<T2, SegmentManager, NodesPerBlock> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related node_allocator
+ template<class T2, class SegmentManager2, std::size_t N2>
+ node_allocator& operator=
+ (const node_allocator<T2, SegmentManager2, N2>&);
+
+ //!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<class T2>
+ node_allocator
+ (const node_allocator<T2, SegmentManager, NodesPerBlock> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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);
+ #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator<T, S, NPC> &alloc1,
+ const node_allocator<T, S, NPC> &alloc2);
+
+//!Inequality test for same type
+//!of node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator<T, S, NPC> &alloc1,
+ const node_allocator<T, S, NPC> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
diff --git a/boost/interprocess/allocators/private_adaptive_pool.hpp b/boost/interprocess/allocators/private_adaptive_pool.hpp
new file mode 100644
index 0000000..301fb92
--- /dev/null
+++ b/boost/interprocess/allocators/private_adaptive_pool.hpp
@@ -0,0 +1,468 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+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;
+
+ /// @cond
+ private:
+ typedef private_adaptive_pool_base
+ < Version, T, SegmentManager, NodesPerBlock
+ , MaxFreeBlocks, OverheadPercent> self_t;
+ typedef ipcdetail::private_adaptive_node_pool
+ <SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ > node_pool_t;
+
+ BOOST_STATIC_ASSERT((Version <=2));
+
+ /// @endcond
+
+ public:
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename segment_manager::size_type size_type;
+ typedef typename segment_manager::size_type difference_type;
+ typedef boost::interprocess::version_type
+ <private_adaptive_pool_base, Version> version;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+ //!Obtains node_allocator from other node_allocator
+ template<class T2>
+ struct rebind
+ {
+ typedef private_adaptive_pool_base
+ <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef ipcdetail::private_adaptive_node_pool
+ <SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ > type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+
+ private:
+ //!Not assignable from related private_adaptive_pool_base
+ template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
+ private_adaptive_pool_base& operator=
+ (const private_adaptive_pool_base<Version2, T2, MemoryAlgorithm2, N2, F2, OP2>&);
+
+ //!Not assignable from other private_adaptive_pool_base
+ private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
+ /// @endcond
+
+ 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<class T2>
+ private_adaptive_pool_base
+ (const private_adaptive_pool_base
+ <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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<node_pool_t*>(&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)
+ { alloc1.m_node_pool.swap(alloc2.m_node_pool); }
+
+ /// @cond
+ private:
+ node_pool_t m_node_pool;
+ /// @endcond
+};
+
+//!Equality test for same type of private_adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
+{ return &alloc1 == &alloc2; }
+
+//!Inequality test for same type of private_adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &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<class T2>
+ struct rebind
+ {
+ typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ private_adaptive_pool_v1(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ private_adaptive_pool_v1
+ (const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail {
+
+/// @endcond
+
+//!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
+ /// @cond
+ : public ipcdetail::private_adaptive_pool_base
+ < 2
+ , T
+ , SegmentManager
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ >
+ /// @endcond
+{
+
+ #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<private_adaptive_pool, 2> version;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef private_adaptive_pool
+ <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ private_adaptive_pool(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ private_adaptive_pool
+ (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef private_adaptive_pool
+ <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related private_adaptive_pool
+ template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+ private_adaptive_pool& operator=
+ (const private_adaptive_pool<T2, SegmentManager2, N2, F2>&);
+
+ //!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<class T2>
+ private_adaptive_pool
+ (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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);
+ #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of private_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of private_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
+
diff --git a/boost/interprocess/allocators/private_node_allocator.hpp b/boost/interprocess/allocators/private_node_allocator.hpp
new file mode 100644
index 0000000..f202e31
--- /dev/null
+++ b/boost/interprocess/allocators/private_node_allocator.hpp
@@ -0,0 +1,445 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes private_node_allocator_base pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+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;
+
+ /// @cond
+ private:
+ typedef private_node_allocator_base
+ < Version, T, SegmentManager, NodesPerBlock> self_t;
+ typedef ipcdetail::private_node_pool
+ <SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ > node_pool_t;
+
+ BOOST_STATIC_ASSERT((Version <=2));
+
+ /// @endcond
+
+ public:
+
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::
+ pointer_traits<void_pointer>::template
+ rebind_pointer<const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename ipcdetail::add_reference
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::type const_reference;
+ typedef typename segment_manager::size_type size_type;
+ typedef typename segment_manager::difference_type difference_type;
+ typedef boost::interprocess::version_type
+ <private_node_allocator_base, Version> version;
+ typedef boost::container::container_detail::transform_multiallocation_chain
+ <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+ //!Obtains node_allocator from other node_allocator
+ template<class T2>
+ struct rebind
+ {
+ typedef private_node_allocator_base
+ <Version, T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ /// @cond
+ template <int dummy>
+ struct node_pool
+ {
+ typedef ipcdetail::private_node_pool
+ <SegmentManager
+ , sizeof_value<T>::value
+ , NodesPerBlock
+ > type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+
+ private:
+ //!Not assignable from related private_node_allocator_base
+ template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2>
+ private_node_allocator_base& operator=
+ (const private_node_allocator_base<Version2, T2, MemoryAlgorithm2, N2>&);
+
+ //!Not assignable from other private_node_allocator_base
+ private_node_allocator_base& operator=(const private_node_allocator_base&);
+ /// @endcond
+
+ 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<class T2>
+ private_node_allocator_base
+ (const private_node_allocator_base
+ <Version, T2, SegmentManager, NodesPerBlock> &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<node_pool_t*>(&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)
+ { alloc1.m_node_pool.swap(alloc2.m_node_pool); }
+
+ /// @cond
+ private:
+ node_pool_t m_node_pool;
+ /// @endcond
+};
+
+//!Equality test for same type of private_node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+ const private_node_allocator_base<V, T, S, NPC> &alloc2)
+{ return &alloc1 == &alloc2; }
+
+//!Inequality test for same type of private_node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+ const private_node_allocator_base<V, T, S, NPC> &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<class T2>
+ struct rebind
+ {
+ typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ private_node_allocator_v1(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ private_node_allocator_v1
+ (const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
+ : base_t(other)
+ {}
+};
+
+} //namespace ipcdetail {
+
+/// @endcond
+
+//!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
+ /// @cond
+ : public ipcdetail::private_node_allocator_base
+ < 2
+ , T
+ , SegmentManager
+ , NodesPerBlock
+ >
+ /// @endcond
+{
+
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ typedef ipcdetail::private_node_allocator_base
+ < 2, T, SegmentManager, NodesPerBlock> base_t;
+ public:
+ typedef boost::interprocess::version_type<private_node_allocator, 2> version;
+
+ template<class T2>
+ struct rebind
+ {
+ typedef private_node_allocator
+ <T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ private_node_allocator(SegmentManager *segment_mngr)
+ : base_t(segment_mngr)
+ {}
+
+ template<class T2>
+ private_node_allocator
+ (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &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
+ <value_type>::type reference;
+ typedef typename ipcdetail::add_reference
+ <const value_type>::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<class T2>
+ struct rebind
+ {
+ typedef private_node_allocator
+ <T2, SegmentManager, NodesPerBlock> other;
+ };
+
+ private:
+ //!Not assignable from
+ //!related private_node_allocator
+ template<class T2, class SegmentManager2, std::size_t N2>
+ private_node_allocator& operator=
+ (const private_node_allocator<T2, SegmentManager2, N2>&);
+
+ //!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<class T2>
+ private_node_allocator
+ (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &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;
+
+ std::pair<pointer, bool>
+ allocation_command(boost::interprocess::allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, const pointer &reuse = 0);
+
+ //!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(...)
+ multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+ //!contiguous block
+ //!of memory. The elements must be deallocated
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+ //!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);
+ #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of private_node_allocator
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of private_node_allocator
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
+ const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
+
diff --git a/boost/interprocess/anonymous_shared_memory.hpp b/boost/interprocess/anonymous_shared_memory.hpp
new file mode 100644
index 0000000..7184306
--- /dev/null
+++ b/boost/interprocess/anonymous_shared_memory.hpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <cstddef>
+
+#if (!defined(BOOST_INTERPROCESS_WINDOWS))
+# include <fcntl.h> //open, O_CREAT, O_*...
+# include <sys/mman.h> //mmap
+# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
+#else
+#include <boost/interprocess/windows_shared_memory.hpp>
+#endif
+
+
+//!\file
+//!Describes a function that creates anonymous shared memory that can be
+//!shared between forked processes
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail{
+
+ class raw_mapped_region_creator
+ {
+ public:
+ static mapped_region
+ create_posix_mapped_region(void *address, offset_t offset, std::size_t size)
+ {
+ mapped_region region;
+ region.m_base = address;
+ region.m_offset = offset;
+ region.m_extra_offset = 0;
+ region.m_size = size;
+ return region;
+ }
+ };
+}
+
+/// @endcond
+
+//!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
+static 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, 0, size);
+}
+#else
+{
+ windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
+ return mapped_region(anonymous_mapping, read_write, 0, size, address);
+}
+
+#endif
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
diff --git a/boost/interprocess/containers/allocation_type.hpp b/boost/interprocess/containers/allocation_type.hpp
new file mode 100644
index 0000000..660b6cb
--- /dev/null
+++ b/boost/interprocess/containers/allocation_type.hpp
@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+typedef int allocation_type;
+/// @endcond
+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 <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
diff --git a/boost/interprocess/containers/containers_fwd.hpp b/boost/interprocess/containers/containers_fwd.hpp
new file mode 100644
index 0000000..7852bbc
--- /dev/null
+++ b/boost/interprocess/containers/containers_fwd.hpp
@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_CONTAINERS_CONTAINERS_FWD_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
+
+/// @cond
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/container_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::ordered_range;
+using boost::container::ordered_unique_range;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+/// @endcond
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
diff --git a/boost/interprocess/containers/deque.hpp b/boost/interprocess/containers/deque.hpp
new file mode 100644
index 0000000..30ca432
--- /dev/null
+++ b/boost/interprocess/containers/deque.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::deque;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
+
diff --git a/boost/interprocess/containers/flat_map.hpp b/boost/interprocess/containers/flat_map.hpp
new file mode 100644
index 0000000..f18a006
--- /dev/null
+++ b/boost/interprocess/containers/flat_map.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::flat_map;
+using boost::container::flat_multimap;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
diff --git a/boost/interprocess/containers/flat_set.hpp b/boost/interprocess/containers/flat_set.hpp
new file mode 100644
index 0000000..1b2bf9b
--- /dev/null
+++ b/boost/interprocess/containers/flat_set.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::flat_set;
+using boost::container::flat_multiset;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
diff --git a/boost/interprocess/containers/list.hpp b/boost/interprocess/containers/list.hpp
new file mode 100644
index 0000000..a75b975
--- /dev/null
+++ b/boost/interprocess/containers/list.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/list.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::list;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
+
diff --git a/boost/interprocess/containers/map.hpp b/boost/interprocess/containers/map.hpp
new file mode 100644
index 0000000..2e45ec0
--- /dev/null
+++ b/boost/interprocess/containers/map.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/map.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::map;
+using boost::container::multimap;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
diff --git a/boost/interprocess/containers/pair.hpp b/boost/interprocess/containers/pair.hpp
new file mode 100644
index 0000000..8ba6d04
--- /dev/null
+++ b/boost/interprocess/containers/pair.hpp
@@ -0,0 +1,34 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::container_detail::pair;
+using boost::container::container_detail::piecewise_construct;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
+
diff --git a/boost/interprocess/containers/set.hpp b/boost/interprocess/containers/set.hpp
new file mode 100644
index 0000000..db06afe
--- /dev/null
+++ b/boost/interprocess/containers/set.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/set.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::set;
+using boost::container::multiset;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP
diff --git a/boost/interprocess/containers/slist.hpp b/boost/interprocess/containers/slist.hpp
new file mode 100644
index 0000000..f93379c
--- /dev/null
+++ b/boost/interprocess/containers/slist.hpp
@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::slist;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
diff --git a/boost/interprocess/containers/stable_vector.hpp b/boost/interprocess/containers/stable_vector.hpp
new file mode 100644
index 0000000..ae09e6b
--- /dev/null
+++ b/boost/interprocess/containers/stable_vector.hpp
@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+ namespace interprocess {
+
+ using boost::container::stable_vector;
+
+ } //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
diff --git a/boost/interprocess/containers/string.hpp b/boost/interprocess/containers/string.hpp
new file mode 100644
index 0000000..a11bb90
--- /dev/null
+++ b/boost/interprocess/containers/string.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/string.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::basic_string;
+using boost::container::string;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
diff --git a/boost/interprocess/containers/vector.hpp b/boost/interprocess/containers/vector.hpp
new file mode 100644
index 0000000..3a6b411
--- /dev/null
+++ b/boost/interprocess/containers/vector.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::vector;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
+
diff --git a/boost/interprocess/containers/version_type.hpp b/boost/interprocess/containers/version_type.hpp
new file mode 100644
index 0000000..247f800
--- /dev/null
+++ b/boost/interprocess/containers/version_type.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::container_detail::version_type;
+using boost::container::container_detail::version;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
+
diff --git a/boost/interprocess/creation_tags.hpp b/boost/interprocess/creation_tags.hpp
new file mode 100644
index 0000000..374829a
--- /dev/null
+++ b/boost/interprocess/creation_tags.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_CREATION_TAGS_HPP
+#define BOOST_INTERPROCESS_CREATION_TAGS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost {
+namespace interprocess {
+
+//!Tag to indicate that the resource must
+//!be only created
+struct create_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened
+struct open_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened for reading
+struct open_read_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened privately for reading
+struct open_read_private_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened for reading
+struct open_copy_on_write_t {};
+
+//!Tag to indicate that the resource must
+//!be created. If already created, it must be opened.
+struct open_or_create_t {};
+
+//!Value to indicate that the resource must
+//!be only created
+static const create_only_t create_only = create_only_t();
+
+//!Value to indicate that the resource must
+//!be only opened
+static const open_only_t open_only = open_only_t();
+
+//!Value to indicate that the resource must
+//!be only opened for reading
+static const open_read_only_t open_read_only = open_read_only_t();
+
+//!Value to indicate that the resource must
+//!be created. If already created, it must be opened.
+static const open_or_create_t open_or_create = open_or_create_t();
+
+//!Value to indicate that the resource must
+//!be only opened for reading
+static const open_copy_on_write_t open_copy_on_write = open_copy_on_write_t();
+
+namespace ipcdetail {
+
+enum create_enum_t
+{ DoCreate, DoOpen, DoOpenOrCreate };
+
+} //namespace ipcdetail {
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
+
diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp
new file mode 100644
index 0000000..f7551f3
--- /dev/null
+++ b/boost/interprocess/detail/atomic.hpp
@@ -0,0 +1,593 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2011
+// (C) Copyright Markus Schoepflin 2007
+// (C) Copyright Bryce Lelbach 2010
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file 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_ATOMIC_HPP
+#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically increment an boost::uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem);
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with": what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+#include <boost/interprocess/detail/win32_api.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with": what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{ return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+ boost::uint32_t prev = cmp;
+ // This version by Mans Rullgard of Pathscale
+ __asm__ __volatile__ ( "lock\n\t"
+ "cmpxchg %2,%0"
+ : "+m"(*mem), "+a"(prev)
+ : "r"(with)
+ : "cc");
+
+ return prev;
+/*
+ asm volatile( "lock\n\t"
+ "cmpxchg %3,%1"
+ : "=a" (prev), "=m" (*(mem))
+ : "0" (prev), "r" (with)
+ : "memory", "cc");
+*/
+/*
+ boost::uint32_t prev;
+
+ asm volatile ("lock; cmpxchgl %1, %2"
+ : "=a" (prev)
+ : "r" (with), "m" (*(mem)), "0"(cmp));
+ asm volatile("" : : : "memory");
+
+ return prev;
+*/
+}
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+ (volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+ // int r = *pw;
+ // *mem += val;
+ // return r;
+ int r;
+
+ asm volatile
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "+m"( *mem ), "=r"( r ): // outputs (%0, %1)
+ "1"( val ): // inputs (%2 == %1)
+ "memory", "cc" // clobbers
+ );
+
+ return r;
+/*
+ asm volatile( "lock\n\t; xaddl %0,%1"
+ : "=r"(val), "=m"(*mem)
+ : "0"(val), "m"(*mem));
+ asm volatile("" : : : "memory");
+
+ return val;
+*/
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, 1); }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, (boost::uint32_t)-1); }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+ boost::uint32_t prev, temp;
+
+ asm volatile ("0:\n\t" // retry local label
+ "lwarx %0,0,%2\n\t" // load prev and reserve
+ "add %1,%0,%3\n\t" // temp = prev + val
+ "stwcx. %1,0,%2\n\t" // conditionally store
+ "bne- 0b" // start over if we lost
+ // the reservation
+ //XXX find a cleaner way to define the temp
+ //it's not an output
+ : "=&r" (prev), "=&r" (temp) // output, temp
+ : "b" (mem), "r" (val) // inputs
+ : "memory", "cc"); // clobbered
+ return prev;
+}
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+ boost::uint32_t prev;
+
+ asm volatile ("0:\n\t" // retry local label
+ "lwarx %0,0,%1\n\t" // load prev and reserve
+ "cmpw %0,%3\n\t" // does it match cmp?
+ "bne- 1f\n\t" // ...no, bail out
+ "stwcx. %2,0,%1\n\t" // ...yes, conditionally
+ // store with
+ "bne- 0b\n\t" // start over if we lost
+ // the reservation
+ "1:" // exit local label
+
+ : "=&r"(prev) // output
+ : "b" (mem), "r" (with), "r"(cmp) // inputs
+ : "memory", "cc"); // clobbered
+ return prev;
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, 1); }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, boost::uint32_t(-1u)); }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+ (volatile boost::uint32_t *mem, boost::uint32_t val)
+{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, 1); }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, (boost::uint32_t)-1); }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif (defined(sun) || defined(__sun))
+
+#include <atomic.h>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{ return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with); }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif defined(__osf__) && defined(__DECCXX)
+
+#include <machine/builtins.h>
+#include <c_asm.h>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically decrement a uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+//! Acquire, memory barrier after decrement.
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; }
+
+//! Atomically increment a uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+//! Release, memory barrier before increment.
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
+
+// Rational for the implementation of the atomic read and write functions.
+//
+// 1. The Alpha Architecture Handbook requires that access to a byte,
+// an aligned word, an aligned longword, or an aligned quadword is
+// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
+//
+// 2. The CXX User's Guide states that volatile quantities are accessed
+// with single assembler instructions, and that a compilation error
+// occurs when declaring a quantity as volatile which is not properly
+// aligned.
+
+//! Atomically read an boost::uint32_t from memory
+//! Acquire, memory barrier after load.
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ boost::uint32_t old_val = *mem; __MB(); return old_val; }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+//! Release, memory barrier before store.
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ __MB(); *mem = val; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+//! Memory barrier between load and store.
+inline boost::uint32_t atomic_cas32(
+ volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+ // Note:
+ //
+ // Branch prediction prefers backward branches, and the Alpha Architecture
+ // Handbook explicitely states that the loop should not be implemented like
+ // it is below. (See chapter 4.2.5.) Therefore the code should probably look
+ // like this:
+ //
+ // return asm(
+ // "10: ldl_l %v0,(%a0) ;"
+ // " cmpeq %v0,%a2,%t0 ;"
+ // " beq %t0,20f ;"
+ // " mb ;"
+ // " mov %a1,%t0 ;"
+ // " stl_c %t0,(%a0) ;"
+ // " beq %t0,30f ;"
+ // "20: ret ;"
+ // "30: br 10b;",
+ // mem, with, cmp);
+ //
+ // But as the compiler always transforms this into the form where a backward
+ // branch is taken on failure, we can as well implement it in the straight
+ // forward form, as this is what it will end up in anyway.
+
+ return asm(
+ "10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem
+ " cmpeq %v0,%a2,%t0 ;" // compare with given value
+ " beq %t0,20f ;" // if not equal, we're done
+ " mb ;" // memory barrier
+ " mov %a1,%t0 ;" // load new value into scratch register
+ " stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch)
+ " beq %t0,10b ;" // store failed because lock has been stolen, retry
+ "20: ",
+ mem, with, cmp);
+}
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX)
+
+#include <builtins.h>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting
+//all the functions with casts
+
+//! From XLC documenation :
+//! This function can be used with a subsequent stwcxu call to implement a
+//! read-modify-write on a specified memory location. The two functions work
+//! together to ensure that if the store is successfully performed, no other
+//! processor or mechanism can modify the target doubleword between the time
+//! lwarxu function is executed and the time the stwcxu functio ncompletes.
+//! "mem" : pointer to the object
+//! Returns the value at pointed to by mem
+inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem)
+{
+ return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem)));
+}
+
+//! "mem" : pointer to the object
+//! "val" : the value to store
+//! Returns true if the update of mem is successful and false if it is
+//!unsuccessful
+inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val)
+{
+ return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0);
+}
+
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+ (volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+ boost::uint32_t oldValue;
+ do
+ {
+ oldValue = lwarxu(mem);
+ }while (!stwcxu(mem, oldValue+val));
+ return oldValue;
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, 1); }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, (boost::uint32_t)-1); }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+ boost::uint32_t oldValue;
+ boost::uint32_t valueToStore;
+ do
+ {
+ oldValue = lwarxu(mem);
+ } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue));
+
+ return oldValue;
+}
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#else
+
+#error No atomic operations implemented for this platform, sorry!
+
+#endif
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+inline bool atomic_add_unless32
+ (volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this)
+{
+ boost::uint32_t old, c(atomic_read32(mem));
+ while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){
+ c = old;
+ }
+ return c != unless_this;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
diff --git a/boost/interprocess/detail/cast_tags.hpp b/boost/interprocess/detail/cast_tags.hpp
new file mode 100644
index 0000000..bd91d1b
--- /dev/null
+++ b/boost/interprocess/detail/cast_tags.hpp
@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_CAST_TAGS_HPP
+#define BOOST_INTERPROCESS_CAST_TAGS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+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 {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
+
diff --git a/boost/interprocess/detail/config_begin.hpp b/boost/interprocess/detail/config_begin.hpp
new file mode 100644
index 0000000..559331a
--- /dev/null
+++ b/boost/interprocess/detail/config_begin.hpp
@@ -0,0 +1,47 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_CONFIG_INCLUDED
+#define BOOST_INTERPROCESS_CONFIG_INCLUDED
+#include <boost/config.hpp>
+#endif
+
+#ifdef BOOST_MSVC
+ #ifndef _CRT_SECURE_NO_DEPRECATE
+ #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+ #define _CRT_SECURE_NO_DEPRECATE
+ #endif
+ #pragma warning (push)
+ #pragma warning (disable : 4702) // unreachable code
+ #pragma warning (disable : 4706) // assignment within conditional expression
+ #pragma warning (disable : 4127) // conditional expression is constant
+ #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
+ #pragma warning (disable : 4284) // odd return type for operator->
+ #pragma warning (disable : 4244) // possible loss of data
+ #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
+ #pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
+ #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
+ #pragma warning (disable : 4355) // "this" : used in base member initializer list
+ #pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
+ #pragma warning (disable : 4511) // copy constructor could not be generated
+ #pragma warning (disable : 4512) // assignment operator could not be generated
+ #pragma warning (disable : 4514) // unreferenced inline removed
+ #pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
+ #pragma warning (disable : 4522) // "class" : multiple assignment operators specified
+ #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
+ #pragma warning (disable : 4710) // function not inlined
+ #pragma warning (disable : 4711) // function selected for automatic inline expansion
+ #pragma warning (disable : 4786) // identifier truncated in debug info
+ #pragma warning (disable : 4996) // "function": was declared deprecated
+ #pragma warning (disable : 4197) // top-level volatile in cast is ignored
+ #pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
+ // with /GR-; unpredictable behavior may result
+ #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
+ #pragma warning (disable : 4671) // the copy constructor is inaccessible
+#endif
diff --git a/boost/interprocess/detail/config_end.hpp b/boost/interprocess/detail/config_end.hpp
new file mode 100644
index 0000000..422458e
--- /dev/null
+++ b/boost/interprocess/detail/config_end.hpp
@@ -0,0 +1,17 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined BOOST_MSVC
+ #pragma warning (pop)
+ #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+ #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+ #undef _CRT_SECURE_NO_DEPRECATE
+ #endif
+#endif
+
diff --git a/boost/interprocess/detail/file_wrapper.hpp b/boost/interprocess/detail/file_wrapper.hpp
new file mode 100644
index 0000000..7b53f36
--- /dev/null
+++ b/boost/interprocess/detail/file_wrapper.hpp
@@ -0,0 +1,202 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_DETAIL_FILE_WRAPPER_HPP
+#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+class file_wrapper
+{
+ /// @cond
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper)
+ /// @endcond
+ 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()); }
+
+ //!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.
+ bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
+
+ file_handle_t m_handle;
+ mode_t m_mode;
+ std::string m_filename;
+};
+
+inline file_wrapper::file_wrapper()
+ : m_handle(file_handle_t(ipcdetail::invalid_file()))
+{}
+
+inline file_wrapper::~file_wrapper()
+{ this->priv_close(); }
+
+inline const char *file_wrapper::get_name() const
+{ return m_filename.c_str(); }
+
+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)
+{
+ std::swap(m_handle, other.m_handle);
+ std::swap(m_mode, other.m_mode);
+ m_filename.swap(other.m_filename);
+}
+
+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; }
+
+inline bool file_wrapper::priv_open_or_create
+ (ipcdetail::create_enum_t type,
+ const char *filename,
+ mode_t mode,
+ const permissions &perm = permissions())
+{
+ m_filename = filename;
+
+ 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()){
+ throw interprocess_exception(error_info(system_error_code()));
+ }
+
+ 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, 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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
diff --git a/boost/interprocess/detail/in_place_interface.hpp b/boost/interprocess/detail/in_place_interface.hpp
new file mode 100644
index 0000000..0e69452
--- /dev/null
+++ b/boost/interprocess/detail/in_place_interface.hpp
@@ -0,0 +1,73 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <typeinfo> //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, std::size_t &constructed) = 0;
+ virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0;
+ virtual ~in_place_interface(){}
+};
+
+template<class T>
+struct placement_destroy : public in_place_interface
+{
+ placement_destroy()
+ : in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name())
+ {}
+
+ virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
+ {
+ T* memory = static_cast<T*>(mem);
+ for(destroyed = 0; destroyed < num; ++destroyed)
+ (memory++)->~T();
+ }
+
+ virtual void construct_n(void *, std::size_t, std::size_t &) {}
+
+ private:
+ void destroy(void *mem)
+ { static_cast<T*>(mem)->~T(); }
+};
+
+}
+}
+} //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
diff --git a/boost/interprocess/detail/intermodule_singleton.hpp b/boost/interprocess/detail/intermodule_singleton.hpp
new file mode 100644
index 0000000..4bffbe9
--- /dev/null
+++ b/boost/interprocess/detail/intermodule_singleton.hpp
@@ -0,0 +1,1184 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+#include <boost/interprocess/windows_shared_memory.hpp>
+#endif
+
+#include <boost/interprocess/shared_memory_object.hpp>
+
+#include <boost/interprocess/offset_ptr.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+#include <fcntl.h>
+#include <io.h>
+
+#include <sys/locking.h>
+#else
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
+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/main executables
+ typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo;
+ template<class Device, bool FileBased>
+ struct open_or_create
+ {
+ typedef managed_open_or_create_impl
+ <Device, mem_algo::Alignment, FileBased> type;
+ };
+};
+
+template<class Device, bool FileBased>
+class basic_managed_global_memory
+ : public basic_managed_memory_impl
+ < char
+ , intermodule_types::mem_algo
+ , iset_index
+ , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset
+ >
+ , private intermodule_types::open_or_create<Device, FileBased>::type
+{
+ /// @cond
+ typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t;
+
+ typedef basic_managed_memory_impl
+ < char
+ , intermodule_types::mem_algo
+ , iset_index
+ , base2_t::ManagedOpenOrCreateUserOffset
+ > base_t;
+
+ typedef create_open_func<base_t> 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)
+ /// @endcond
+
+ public: //functions
+/*
+ basic_managed_global_memory()
+ {}
+
+ basic_managed_global_memory(create_only_t create_only, 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(), DoCreate), perm)
+ {}
+*/
+ basic_managed_global_memory (open_or_create_t open_or_create,
+ 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(),
+ DoOpenOrCreate), perm)
+ {}
+
+ basic_managed_global_memory (open_only_t open_only, const char* name,
+ const void *addr = 0)
+ : base_t()
+ , base2_t(open_only, name, read_write, addr,
+ create_open_func_t(get_this_pointer(),
+ DoOpen))
+ {}
+
+/*
+ basic_managed_global_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(),
+ DoOpen))
+ {}
+
+ //!Connects to a created shared memory and its segment manager.
+ //!in read-only mode.
+ //!This can throw.
+ basic_managed_global_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(),
+ DoOpen))
+ {}
+
+ //!Moves the ownership of "moved"'s managed memory to *this.
+ //!Does not throw
+ basic_managed_global_memory(BOOST_RV_REF(basic_managed_global_memory) moved)
+ {
+ basic_managed_global_memory tmp;
+ this->swap(moved);
+ tmp.swap(moved);
+ }
+
+ //!Moves the ownership of "moved"'s managed memory to *this.
+ //!Does not throw
+ basic_managed_global_memory &operator=(BOOST_RV_REF(basic_managed_global_memory) moved)
+ {
+ basic_managed_global_memory tmp(boost::move(moved));
+ this->swap(tmp);
+ return *this;
+ }*/
+};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+typedef basic_managed_global_memory<windows_shared_memory, false> windows_managed_global_memory;
+#endif
+
+typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory;
+
+namespace file_locking_helpers {
+
+inline void get_pid_creation_time_str(std::string &s)
+{
+ std::stringstream stream;
+ stream << get_current_process_id() << '_';
+ stream.precision(6);
+ stream << std::fixed << get_current_process_creation_time();
+ s = stream.str();
+}
+
+inline 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_tmp_and_clean_old(s);
+ s += "/";
+ s += subdir_name;
+ if(!open_or_create_directory(s.c_str())){
+ throw interprocess_exception(error_info(system_error_code()));
+ }
+ 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;
+ }
+}
+
+inline 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);
+ }
+}
+
+} //file_locking_helpers
+
+namespace intermodule_singleton_helpers {
+
+const int GMemMarkToBeRemoved = -1;
+const int GMemNotPresent = -2;
+
+inline const char *get_lock_file_subdir_name()
+{ return "gmem"; }
+
+inline const char *get_lock_file_base_name()
+{ return "lck"; }
+
+inline void create_and_get_singleton_lock_file_path(std::string &s)
+{
+ file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
+ (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
+}
+
+inline const char *get_shm_base_name()
+{ return "bip.gmem.shm."; }
+
+inline void get_shm_name(std::string &shm_name)
+{
+ file_locking_helpers::get_pid_creation_time_str(shm_name);
+ shm_name.insert(0, get_shm_base_name());
+}
+
+inline std::size_t get_shm_size()
+{ return 65536; }
+
+template<class ManagedShMem>
+struct managed_sh_dependant
+{
+ static void apply_gmem_erase_logic(const char *filepath, const char *filename);
+
+ static bool remove_old_gmem()
+ {
+ std::string refcstrRootDirectory;
+ tmp_folder(refcstrRootDirectory);
+ refcstrRootDirectory += "/";
+ refcstrRootDirectory += get_lock_file_subdir_name();
+ return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
+ }
+};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+template<>
+struct managed_sh_dependant<windows_managed_global_memory>
+{
+ static void apply_gmem_erase_logic(const char *, const char *){}
+
+ static bool remove_old_gmem()
+ { return true; }
+};
+
+
+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
+
+template<class ManagedShMem>
+struct gmem_erase_func
+{
+ gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, ManagedShMem & shm)
+ :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
+ {}
+
+ void operator()()
+ {
+ locking_file_serial_id *pserial_id = shm_.template find<locking_file_serial_id>("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_;
+ ManagedShMem & shm_;
+};
+
+//This function applies shared memory erasure logic based on the passed lock file.
+template<class ManagedShMem>
+void managed_sh_dependant<ManagedShMem>::
+ apply_gmem_erase_logic(const char *filepath, const char *filename)
+{
+ int fd = GMemMarkToBeRemoved;
+ try{
+ std::string str;
+ //If the filename is current process lock file, then avoid it
+ if(file_locking_helpers::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_shm_base_name());
+ try{
+ ManagedShMem shm(open_only, str.c_str());
+ gmem_erase_func<ManagedShMem> func(str.c_str(), filepath, shm);
+ shm.try_atomic_func(func);
+ }
+ 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);
+ }
+ }
+ }
+ catch(...){
+
+ }
+ if(fd >= 0){
+ close_lock_file(fd);
+ }
+}
+
+} //namespace intermodule_singleton_helpers {
+
+
+
+namespace intermodule_singleton_helpers {
+
+//The lock file logic creates uses a unique instance to a file
+template <class ManagedShMem>
+struct lock_file_logic
+{
+ lock_file_logic(ManagedShMem &shm)
+ : mshm(shm)
+ { shm.atomic_func(*this); }
+
+ void operator()(void)
+ {
+ retry_with_new_shm = false;
+
+ //First find the file locking descriptor id
+ locking_file_serial_id *pserial_id =
+ mshm.template find<locking_file_serial_id>("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 = intermodule_singleton_helpers::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 < 0){
+ this->register_lock_file(GMemMarkToBeRemoved);
+ std::string s;
+ get_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ retry_with_new_shm = true;
+ }
+ //If successful, register the file descriptor
+ else{
+ this->register_lock_file(fd);
+ }
+ }
+ //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_shm = 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_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ retry_with_new_shm = 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);
+ }
+ }
+
+ private:
+ locking_file_serial_id * register_lock_file(int fd)
+ {
+ locking_file_serial_id *pinfo = mshm.template construct<locking_file_serial_id>("lock_file_fd")();
+ fill_file_serial_id(fd, *pinfo);
+ return pinfo;
+ }
+
+ public:
+ ManagedShMem &mshm;
+ bool retry_with_new_shm;
+};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+template<>
+struct lock_file_logic<windows_managed_global_memory>
+{
+ lock_file_logic(windows_managed_global_memory &)
+ : retry_with_new_shm(false)
+ {}
+
+ void operator()(void){}
+ const bool retry_with_new_shm;
+};
+
+#endif
+
+} //namespace intermodule_singleton_helpers {
+
+//This class contains common code for all singleton types, so that we instantiate this
+//code just once per module. This class also holds a reference counted shared memory
+//to be used by all instances
+
+template<class ManagedShMem>
+class intermodule_singleton_common
+{
+ public:
+ typedef void*(singleton_constructor_t)(ManagedShMem &);
+ typedef void (singleton_destructor_t)(void *, ManagedShMem &);
+
+ static const ::boost::uint32_t Uninitialized = 0u;
+ static const ::boost::uint32_t Initializing = 1u;
+ static const ::boost::uint32_t Initialized = 2u;
+ static const ::boost::uint32_t Broken = 3u;
+
+ static void finalize_singleton_logic(void *ptr, singleton_destructor_t destructor)
+ {
+ if(ptr)
+ destructor(ptr, get_shm());
+ //If this is the last singleton of this module
+ //apply shm destruction.
+ //Note: singletons are destroyed when the module is unloaded
+ //so no threads should be executing or holding references
+ //to this module
+ if(1 == atomic_dec32(&this_module_singleton_count)){
+ destroy_shm();
+ }
+ }
+
+ static void initialize_singleton_logic
+ (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t ini_func);
+
+ private:
+ static ManagedShMem &get_shm()
+ {
+ return *static_cast<ManagedShMem *>(static_cast<void *>(&mem_holder.shm_mem));
+ }
+
+ static void initialize_shm();
+ static void destroy_shm();
+ //Static data, zero-initalized without any dependencies
+ //this_module_singleton_count is the number of singletons used by this module
+ static volatile boost::uint32_t this_module_singleton_count;
+ //this_module_shm_initialized is the state of this module's shm class object
+ static volatile boost::uint32_t this_module_shm_initialized;
+ static struct mem_holder_t
+ {
+ ::boost::detail::max_align aligner;
+ char shm_mem [sizeof(ManagedShMem)];
+ } mem_holder;
+};
+
+template<class ManagedShMem>
+volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_singleton_count;
+
+template<class ManagedShMem>
+volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_shm_initialized;
+
+template<class ManagedShMem>
+typename intermodule_singleton_common<ManagedShMem>::mem_holder_t
+ intermodule_singleton_common<ManagedShMem>::mem_holder;
+
+template<class ManagedShMem>
+void intermodule_singleton_common<ManagedShMem>::initialize_shm()
+{
+ //Obtain unique shm name and size
+ std::string s;
+ while(1){
+ //Try to pass shm state to initializing
+ ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized);
+ if(tmp >= Initialized){
+ break;
+ }
+ //If some other thread is doing the work wait
+ else if(tmp == Initializing){
+ thread_yield();
+ }
+ else{ //(tmp == Uninitialized)
+ //If not initialized try it again?
+ try{
+ //Remove old shared memory from the system
+ intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::remove_old_gmem();
+ //
+ if(s.empty()){
+ intermodule_singleton_helpers::get_shm_name(s);
+ }
+ const char *ShmName = s.c_str();
+ const std::size_t ShmSize = intermodule_singleton_helpers::get_shm_size();;
+
+ //in-place construction of the shared memory class
+ ::new (&get_shm())ManagedShMem(open_or_create, ShmName, ShmSize);
+ //Use shared memory internal lock to initialize the lock file
+ //that will mark this gmem as "in use".
+ intermodule_singleton_helpers::lock_file_logic<ManagedShMem> f(get_shm());
+ //If function failed (maybe a competing process has erased the shared
+ //memory between creation and file locking), retry with a new instance.
+ if(f.retry_with_new_shm){
+ get_shm().~ManagedShMem();
+ atomic_write32(&this_module_shm_initialized, Uninitialized);
+ }
+ else{
+ //Locking succeeded, so this shared memory module-instance is ready
+ atomic_write32(&this_module_shm_initialized, Initialized);
+ break;
+ }
+ }
+ catch(...){
+ //
+ throw;
+ }
+ }
+ }
+}
+
+template<class ManagedShMem>
+struct unlink_shmlogic
+{
+ unlink_shmlogic(ManagedShMem &mshm)
+ : mshm_(mshm)
+ { mshm.atomic_func(*this); }
+ void operator()()
+ {
+ intermodule_singleton_helpers::locking_file_serial_id *pserial_id =
+ mshm_.template find<intermodule_singleton_helpers::locking_file_serial_id>
+ ("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 = intermodule_singleton_helpers::GMemMarkToBeRemoved;
+ std::string s;
+ intermodule_singleton_helpers::create_and_get_singleton_lock_file_path(s);
+ delete_file(s.c_str());
+ intermodule_singleton_helpers::close_lock_file(fd);
+ intermodule_singleton_helpers::get_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ }
+ }
+ }
+ ManagedShMem &mshm_;
+};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+template<>
+struct unlink_shmlogic<windows_managed_global_memory>
+{
+ unlink_shmlogic(windows_managed_global_memory &)
+ {}
+ void operator()(){}
+};
+
+#endif
+
+
+template<class ManagedShMem>
+void intermodule_singleton_common<ManagedShMem>::destroy_shm()
+{
+ if(!atomic_read32(&this_module_singleton_count)){
+ //This module is being unloaded, so destroy
+ //the shared memory object of this module
+ //and unlink the shared memory if it's the last
+ unlink_shmlogic<ManagedShMem> f(get_shm());
+ (get_shm()).~ManagedShMem();
+ atomic_write32(&this_module_shm_initialized, Uninitialized);
+ //Do some cleanup for other processes old gmem instances
+ intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::remove_old_gmem();
+ }
+}
+
+//Initialize this_module_singleton_ptr, creates the shared memory if needed and also creates an unique
+//opaque type in shared memory through a singleton_constructor_t function call,
+//initializing the passed pointer to that unique instance.
+//
+//We have two concurrency types here. a)the shared memory/singleton creation must
+//be safe between threads of this process but in different modules/dlls. b)
+//the pointer to the singleton is per-module, so we have to protect this
+//initization between threads of the same module.
+//
+//All static variables declared here are shared between inside a module
+//so atomic operations will synchronize only threads of the same module.
+template<class ManagedShMem>
+void intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
+ (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor)
+{
+ //If current module is not initialized enter to lock free logic
+ if(atomic_read32(&this_module_singleton_initialized) != Initialized){
+ //Now a single thread of the module will succeed in this CAS.
+ //trying to pass from Uninitialized to Initializing
+ ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32
+ (&this_module_singleton_initialized, Initializing, Uninitialized);
+ //If the thread succeeded the CAS (winner) it will compete with other
+ //winner threads from other modules to create the shared memory
+ if(previous_module_singleton_initialized == Uninitialized){
+ try{
+ //Now initialize shm, this function solves concurrency issues
+ //between threads of several modules
+ initialize_shm();
+ //Increment the module reference count that reflects how many
+ //singletons this module holds, so that we can safely destroy
+ //module shared memory object when no singleton is left
+ atomic_inc32(&this_module_singleton_count);
+ //Now try to create the singleton in shared memory.
+ //This function solves concurrency issues
+ //between threads of several modules
+ void *tmp = constructor(get_shm());
+ //Insert a barrier before assigning the pointer to
+ //make sure this assignment comes after the initialization
+ atomic_write32(&this_module_singleton_initialized, Initializing);
+ //Assign the singleton address to the module-local pointer
+ ptr = tmp;
+ //Memory barrier inserted, all previous operations should complete
+ //before this one. Now marked as initialized
+ atomic_inc32(&this_module_singleton_initialized);
+ }
+ catch(...){
+ //Mark singleton failed to initialize
+ atomic_write32(&this_module_singleton_initialized, Broken);
+ throw;
+ }
+ }
+ //If previous state was initializing, this means that another winner thread is
+ //trying to initialize the singleton. Just wait until completes its work.
+ else if(previous_module_singleton_initialized == Initializing){
+ while(1){
+ previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
+ if(previous_module_singleton_initialized >= Initialized){
+ //Already initialized, or exception thrown by initializer thread
+ break;
+ }
+ else if(previous_module_singleton_initialized == Initializing){
+ thread_yield();
+ }
+ else{
+ //This can't be happening!
+ BOOST_ASSERT(0);
+ }
+ }
+ }
+ else if(previous_module_singleton_initialized == Initialized){
+ //Nothing to do here, the singleton is ready
+ }
+ //If previous state was greater than initialized, then memory is broken
+ //trying to initialize the singleton.
+ else{//(previous_module_singleton_initialized > Initialized)
+ throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
+ }
+ }
+ BOOST_ASSERT(ptr != 0);
+}
+
+//Now this class is a singleton, initializing the singleton in
+//the first get() function call if LazyInit is false. If true
+//then the singleton will be initialized when loading the module.
+template<typename C, bool LazyInit, class ManagedShMem>
+class intermodule_singleton_impl
+{
+ public:
+ static C& get() //Let's make inlining easy
+ {
+ if(!this_module_singleton_ptr){
+ if(lifetime.dummy_function()) //This forces lifetime instantiation, for reference counted destruction
+ intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
+ (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
+ }
+ return *static_cast<C*>(this_module_singleton_ptr);
+ }
+
+ private:
+
+ struct ref_count_ptr
+ {
+ ref_count_ptr(C *p, boost::uint32_t count)
+ : ptr(p), singleton_ref_count(count)
+ {}
+ C *ptr;
+ //This reference count serves to count the number of attached
+ //modules to this singleton
+ volatile boost::uint32_t singleton_ref_count;
+ };
+
+ //These statics will be zero-initialized without any constructor call dependency
+ //this_module_singleton_ptr will be a module-local pointer to the singleton
+ static void* this_module_singleton_ptr;
+ //this_module_singleton_count will be used to synchronize threads of the same module
+ //for access to a singleton instance, and to flag the state of the
+ //singleton.
+ static volatile boost::uint32_t this_module_singleton_initialized;
+
+ //This class destructor will trigger singleton destruction
+ struct lifetime_type_lazy
+ {
+ bool dummy_function()
+ { return m_dummy == 0; }
+
+ ~lifetime_type_lazy()
+ {
+ intermodule_singleton_common<ManagedShMem>::finalize_singleton_logic
+ (this_module_singleton_ptr, singleton_destructor);
+ }
+ //Dummy volatile so that the compiler can't resolve its value at compile-time
+ //and can't avoid lifetime_type instantiation if dummy_function() is called.
+ static volatile int m_dummy;
+ };
+
+ struct lifetime_type_static
+ : public lifetime_type_lazy
+ {
+ lifetime_type_static()
+ {
+ intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
+ (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
+ }
+ };
+
+ typedef typename if_c
+ <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
+
+ static lifetime_type lifetime;
+
+ //A functor to be executed inside shared memory lock that just
+ //searches for the singleton in shm and if not present creates a new one.
+ //If singleton constructor throws, the exception is propagated
+ struct init_atomic_func
+ {
+ init_atomic_func(ManagedShMem &m)
+ : mshm(m)
+ {}
+
+ void operator()()
+ {
+ ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ if(!rcount){
+ C *p = new C();
+ try{
+ rcount = mshm.template construct<ref_count_ptr>(unique_instance)(p, 0u);
+ }
+ catch(...){
+ delete p;
+ throw;
+ }
+ }
+ atomic_inc32(&rcount->singleton_ref_count);
+ ret_ptr = rcount->ptr;
+ }
+ ManagedShMem &mshm;
+ void *ret_ptr;
+ };
+
+ //A functor to be executed inside shared memory lock that just
+ //deletes the singleton in shm if the attached count reaches to zero
+ struct fini_atomic_func
+ {
+ fini_atomic_func(ManagedShMem &m)
+ : mshm(m)
+ {}
+
+ void operator()()
+ {
+ ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ //The object must exist
+ BOOST_ASSERT(rcount);
+ //Check if last reference
+ if(atomic_dec32(&rcount->singleton_ref_count) == 1){
+ //If last, destroy the object
+ BOOST_ASSERT(rcount->ptr != 0);
+ delete rcount->ptr;
+ //Now destroy shm entry
+ bool destroyed = mshm.template destroy<ref_count_ptr>(unique_instance);
+ (void)destroyed; BOOST_ASSERT(destroyed == true);
+ }
+ }
+ ManagedShMem &mshm;
+ void *ret_ptr;
+ };
+
+ //A wrapper to execute init_atomic_func
+ static void *singleton_constructor(ManagedShMem &mshm)
+ {
+ init_atomic_func f(mshm);
+ mshm.atomic_func(f);
+ return f.ret_ptr;
+ }
+
+ //A wrapper to execute fini_atomic_func
+ static void singleton_destructor(void *p, ManagedShMem &mshm)
+ { (void)p;
+ fini_atomic_func f(mshm);
+ mshm.atomic_func(f);
+ }
+};
+
+template <typename C, bool L, class ManagedShMem>
+volatile int intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type_lazy::m_dummy = 0;
+
+//These will be zero-initialized by the loader
+template <typename C, bool L, class ManagedShMem>
+void *intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_ptr = 0;
+
+template <typename C, bool L, class ManagedShMem>
+volatile boost::uint32_t intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_initialized = 0;
+
+template <typename C, bool L, class ManagedShMem>
+typename intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type
+ intermodule_singleton_impl<C, L, ManagedShMem>::lifetime;
+
+template<typename C, bool LazyInit = false>
+class portable_intermodule_singleton
+ : public intermodule_singleton_impl<C, LazyInit, managed_global_memory>
+{};
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+template<typename C, bool LazyInit = false>
+class windows_intermodule_singleton
+ : public intermodule_singleton_impl
+ < C
+ , LazyInit
+ , windows_managed_global_memory
+ >
+{};
+
+#endif
+
+//Now this class is a singleton, initializing the singleton in
+//the first get() function call if LazyInit is false. If true
+//then the singleton will be initialized when loading the module.
+template<typename C, bool LazyInit = false>
+class intermodule_singleton
+ #ifdef BOOST_INTERPROCESS_WINDOWS
+ : public windows_intermodule_singleton<C, LazyInit>
+ #else
+ : public portable_intermodule_singleton<C, LazyInit>
+ #endif
+{};
+
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif
diff --git a/boost/interprocess/detail/interprocess_tester.hpp b/boost/interprocess/detail/interprocess_tester.hpp
new file mode 100644
index 0000000..2581776
--- /dev/null
+++ b/boost/interprocess/detail/interprocess_tester.hpp
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+class interprocess_tester
+{
+ public:
+ template<class T>
+ 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/boost/interprocess/detail/intersegment_ptr.hpp b/boost/interprocess/detail/intersegment_ptr.hpp
new file mode 100644
index 0000000..9297092
--- /dev/null
+++ b/boost/interprocess/detail/intersegment_ptr.hpp
@@ -0,0 +1,1040 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_INTERSEGMENT_PTR_HPP
+#define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/math_functions.hpp>
+#include <boost/interprocess/detail/cast_tags.hpp>
+#include <boost/assert.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/containers/flat_map.hpp>
+#include <boost/interprocess/containers/vector.hpp> //vector
+#include <boost/interprocess/containers/set.hpp> //set
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <climits>
+#include <iterator>
+#include <boost/static_assert.hpp> //BOOST_STATIC_ASSERT
+#include <climits> //CHAR_BIT
+#include <boost/integer/static_log2.hpp>
+#include <boost/assert.hpp> //BOOST_ASSERT
+#include <boost/interprocess/detail/multi_segment_services.hpp>
+
+//!\file
+//!
+namespace boost {
+
+//Predeclarations
+template <class T>
+struct has_trivial_constructor;
+
+template <class T>
+struct has_trivial_destructor;
+
+namespace interprocess {
+
+template <class T>
+struct is_multisegment_ptr;
+
+struct intersegment_base
+{
+ typedef intersegment_base self_t;
+ BOOST_STATIC_ASSERT((sizeof(std::size_t) == sizeof(void*)));
+ BOOST_STATIC_ASSERT((sizeof(void*)*CHAR_BIT == 32 || sizeof(void*)*CHAR_BIT == 64));
+ static const std::size_t size_t_bits = (sizeof(void*)*CHAR_BIT == 32) ? 32 : 64;
+ static const std::size_t ctrl_bits = 2;
+ static const std::size_t align_bits = 12;
+ static const std::size_t align = std::size_t(1) << align_bits;
+ static const std::size_t max_segment_size_bits = size_t_bits - 2;
+ static const std::size_t max_segment_size = std::size_t(1) << max_segment_size_bits;
+
+ static const std::size_t begin_bits = max_segment_size_bits - align_bits;
+ static const std::size_t pow_size_bits_helper = static_log2<max_segment_size_bits>::value;
+ static const std::size_t pow_size_bits =
+ (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ?
+ pow_size_bits_helper : pow_size_bits_helper + 1;
+ static const std::size_t frc_size_bits =
+ size_t_bits - ctrl_bits - begin_bits - pow_size_bits;
+
+ BOOST_STATIC_ASSERT(((size_t_bits - pow_size_bits - frc_size_bits) >= ctrl_bits ));
+
+ static const std::size_t relative_size_bits =
+ size_t_bits - max_segment_size_bits - ctrl_bits;
+
+ static const std::size_t is_pointee_outside = 0;
+ static const std::size_t is_in_stack = 1;
+ static const std::size_t is_relative = 2;
+ static const std::size_t is_segmented = 3;
+ static const std::size_t is_max_mode = 4;
+
+ intersegment_base()
+ {
+ this->set_mode(is_pointee_outside);
+ this->set_null();
+ }
+
+ struct relative_addressing
+ {
+ std::size_t ctrl : 2;
+ std::size_t pow : pow_size_bits;
+ std::size_t frc : frc_size_bits;
+ std::size_t beg : begin_bits;
+ std::ptrdiff_t off : sizeof(std::ptrdiff_t)*CHAR_BIT - 2;
+ std::ptrdiff_t bits : 2;
+ };
+
+ struct direct_addressing
+ {
+ std::size_t ctrl : 2;
+ std::size_t dummy : sizeof(std::size_t)*CHAR_BIT - 2;
+ void * addr;
+ };
+
+ struct segmented_addressing
+ {
+ std::size_t ctrl : 2;
+ std::size_t segment : sizeof(std::size_t)*CHAR_BIT - 2;
+ std::size_t off : sizeof(std::size_t)*CHAR_BIT - 2;
+ std::size_t bits : 2;
+ };
+
+ union members_t{
+ relative_addressing relative;
+ direct_addressing direct;
+ segmented_addressing segmented;
+ } members;
+
+ BOOST_STATIC_ASSERT(sizeof(members_t) == 2*sizeof(std::size_t));
+
+ void *relative_calculate_begin_addr() const
+ {
+ const std::size_t mask = ~(align - 1);
+ std::size_t beg = this->members.relative.beg;
+ return reinterpret_cast<void*>((((std::size_t)this) & mask) - (beg << align_bits));
+ }
+
+ void relative_set_begin_from_base(void *addr)
+ {
+ BOOST_ASSERT(addr < static_cast<void*>(this));
+ std::size_t off = reinterpret_cast<char*>(this) - reinterpret_cast<char*>(addr);
+ members.relative.beg = off >> align_bits;
+ }
+
+ //!Obtains the address pointed by the
+ //!object
+ std::size_t relative_size() const
+ {
+ std::size_t pow = members.relative.pow;
+ std::size_t size = (std::size_t(1u) << pow);
+ BOOST_ASSERT(pow >= frc_size_bits);
+ size |= members.relative.frc << (pow - frc_size_bits);
+ return size;
+ }
+
+ static std::size_t calculate_size(std::size_t orig_size, std::size_t &pow, std::size_t &frc)
+ {
+ if(orig_size < align)
+ orig_size = align;
+ orig_size = ipcdetail::get_rounded_size_po2(orig_size, align);
+ pow = ipcdetail::floor_log2(orig_size);
+ std::size_t low_size = (std::size_t(1) << pow);
+ std::size_t diff = orig_size - low_size;
+ BOOST_ASSERT(pow >= frc_size_bits);
+ std::size_t rounded = ipcdetail::get_rounded_size_po2
+ (diff, (std::size_t)(1u << (pow - frc_size_bits)));
+ if(rounded == low_size){
+ ++pow;
+ frc = 0;
+ rounded = 0;
+ }
+ else{
+ frc = rounded >> (pow - frc_size_bits);
+ }
+ BOOST_ASSERT(((frc << (pow - frc_size_bits)) & (align-1))==0);
+ return low_size + rounded;
+ }
+
+ std::size_t get_mode()const
+ { return members.direct.ctrl; }
+
+ void set_mode(std::size_t mode)
+ {
+ BOOST_ASSERT(mode < is_max_mode);
+ members.direct.ctrl = mode;
+ }
+
+ //!Returns true if object represents
+ //!null pointer
+ bool is_null() const
+ {
+ return (this->get_mode() < is_relative) &&
+ !members.direct.dummy &&
+ !members.direct.addr;
+ }
+
+ //!Sets the object to represent
+ //!the null pointer
+ void set_null()
+ {
+ if(this->get_mode() >= is_relative){
+ this->set_mode(is_pointee_outside);
+ }
+ members.direct.dummy = 0;
+ members.direct.addr = 0;
+ }
+
+ static std::size_t round_size(std::size_t orig_size)
+ {
+ std::size_t pow, frc;
+ return calculate_size(orig_size, pow, frc);
+ }
+};
+
+
+
+//!Configures intersegment_ptr with the capability to address:
+//!2^(sizeof(std::size_t)*CHAR_BIT/2) segment groups
+//!2^(sizeof(std::size_t)*CHAR_BIT/2) segments per group.
+//!2^(sizeof(std::size_t)*CHAR_BIT/2)-1 bytes maximum per segment.
+//!The mapping is implemented through flat_maps synchronized with mutexes.
+template <class Mutex>
+struct flat_map_intersegment
+ : public intersegment_base
+{
+ typedef flat_map_intersegment<Mutex> self_t;
+
+ void set_from_pointer(const volatile void *ptr)
+ { this->set_from_pointer(const_cast<const void *>(ptr)); }
+
+ //!Obtains the address pointed
+ //!by the object
+ void *to_raw_pointer() const
+ {
+ if(is_null()){
+ return 0;
+ }
+ switch(this->get_mode()){
+ case is_relative:
+ return const_cast<char*>(reinterpret_cast<const char*>(this)) + members.relative.off;
+ break;
+ case is_segmented:
+ {
+ segment_info_t segment_info;
+ std::size_t offset;
+ void *this_base;
+ get_segment_info_and_offset(this, segment_info, offset, this_base);
+ char *base = static_cast<char*>(segment_info.group->address_of(this->members.segmented.segment));
+ return base + this->members.segmented.off;
+ }
+ break;
+ case is_in_stack:
+ case is_pointee_outside:
+ return members.direct.addr;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ }
+
+ //!Calculates the distance between two basic_intersegment_ptr-s.
+ //!This only works with two basic_intersegment_ptr pointing
+ //!to the same segment. Otherwise undefined
+ std::ptrdiff_t diff(const self_t &other) const
+ { return static_cast<char*>(this->to_raw_pointer()) - static_cast<char*>(other.to_raw_pointer()); }
+
+ //!Returns true if both point to
+ //!the same object
+ bool equal(const self_t &y) const
+ { return this->to_raw_pointer() == y.to_raw_pointer(); }
+
+ //!Returns true if *this is less than other.
+ //!This only works with two basic_intersegment_ptr pointing
+ //!to the same segment group. Otherwise undefined. Never throws
+ bool less(const self_t &y) const
+ { return this->to_raw_pointer() < y.to_raw_pointer(); }
+
+ void swap(self_t &other)
+ {
+ void *ptr_this = this->to_raw_pointer();
+ void *ptr_other = other.to_raw_pointer();
+ other.set_from_pointer(ptr_this);
+ this->set_from_pointer(ptr_other);
+ }
+
+ //!Sets the object internals to represent the
+ //!address pointed by ptr
+ void set_from_pointer(const void *ptr)
+ {
+ if(!ptr){
+ this->set_null();
+ return;
+ }
+
+ std::size_t mode = this->get_mode();
+ if(mode == is_in_stack){
+ members.direct.addr = const_cast<void*>(ptr);
+ return;
+ }
+ if(mode == is_relative){
+ char *beg_addr = static_cast<char*>(this->relative_calculate_begin_addr());
+ std::size_t seg_size = this->relative_size();
+ if(ptr >= beg_addr && ptr < (beg_addr + seg_size)){
+ members.relative.off = static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this);
+ return;
+ }
+ }
+ std::size_t ptr_offset;
+ std::size_t this_offset;
+ segment_info_t ptr_info;
+ segment_info_t this_info;
+ void *ptr_base;
+ void *this_base;
+ get_segment_info_and_offset(this, this_info, this_offset, this_base);
+
+ if(!this_info.group){
+ this->set_mode(is_in_stack);
+ this->members.direct.addr = const_cast<void*>(ptr);
+ }
+ else{
+ get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base);
+
+ if(ptr_info.group != this_info.group){
+ this->set_mode(is_pointee_outside);
+ this->members.direct.addr = const_cast<void*>(ptr);
+ }
+ else if(ptr_info.id == this_info.id){
+ this->set_mode(is_relative);
+ members.relative.off = (static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
+ this->relative_set_begin_from_base(this_base);
+ std::size_t pow, frc;
+ std::size_t s = calculate_size(this_info.size, pow, frc);
+ (void)s;
+ BOOST_ASSERT(this_info.size == s);
+ this->members.relative.pow = pow;
+ this->members.relative.frc = frc;
+ }
+ else{
+ this->set_mode(is_segmented);
+ this->members.segmented.segment = ptr_info.id;
+ this->members.segmented.off = ptr_offset;
+ }
+ }
+ }
+
+ //!Sets the object internals to represent the address pointed
+ //!by another flat_map_intersegment
+ void set_from_other(const self_t &other)
+ {
+ this->set_from_pointer(other.to_raw_pointer());
+ }
+
+ //!Increments internal
+ //!offset
+ void inc_offset(std::ptrdiff_t bytes)
+ {
+ this->set_from_pointer(static_cast<char*>(this->to_raw_pointer()) + bytes);
+ }
+
+ //!Decrements internal
+ //!offset
+ void dec_offset(std::ptrdiff_t bytes)
+ {
+ this->set_from_pointer(static_cast<char*>(this->to_raw_pointer()) - bytes);
+ }
+
+ //////////////////////////////////////
+ //////////////////////////////////////
+ //////////////////////////////////////
+
+ flat_map_intersegment()
+ : intersegment_base()
+ {}
+
+ ~flat_map_intersegment()
+ {}
+
+ private:
+
+ class segment_group_t
+ {
+ struct segment_data
+ {
+ void *addr;
+ std::size_t size;
+ };
+ vector<segment_data> m_segments;
+ multi_segment_services &m_ms_services;
+
+ public:
+ segment_group_t(multi_segment_services &ms_services)
+ : m_ms_services(ms_services)
+ {}
+
+ void push_back(void *addr, std::size_t size)
+ {
+ segment_data d = { addr, size };
+ m_segments.push_back(d);
+ }
+
+ void pop_back()
+ {
+ BOOST_ASSERT(!m_segments.empty());
+ m_segments.erase(--m_segments.end());
+ }
+
+
+ void *address_of(std::size_t segment_id)
+ {
+ BOOST_ASSERT(segment_id < (std::size_t)m_segments.size());
+ return m_segments[segment_id].addr;
+ }
+
+ void clear_segments()
+ { m_segments.clear(); }
+
+ std::size_t get_size() const
+ { return m_segments.size(); }
+
+ multi_segment_services &get_multi_segment_services() const
+ { return m_ms_services; }
+
+ friend bool operator< (const segment_group_t&l, const segment_group_t &r)
+ { return &l.m_ms_services < &r.m_ms_services; }
+ };
+
+ struct segment_info_t
+ {
+ std::size_t size;
+ std::size_t id;
+ segment_group_t *group;
+ segment_info_t()
+ : size(0), id(0), group(0)
+ {}
+ };
+
+ typedef set<segment_group_t> segment_groups_t;
+
+ typedef boost::interprocess::flat_map
+ <const void *
+ ,segment_info_t
+ ,std::less<const void *> > ptr_to_segment_info_t;
+
+ struct mappings_t : Mutex
+ {
+ //!Mutex to preserve integrity in multi-threaded
+ //!enviroments
+ typedef Mutex mutex_type;
+ //!Maps base addresses and segment information
+ //!(size and segment group and id)*
+
+ ptr_to_segment_info_t m_ptr_to_segment_info;
+
+ ~mappings_t()
+ {
+ //Check that all mappings have been erased
+ BOOST_ASSERT(m_ptr_to_segment_info.empty());
+ }
+ };
+
+ //Static members
+ static mappings_t s_map;
+ static segment_groups_t s_groups;
+ public:
+
+ typedef segment_group_t* segment_group_id;
+
+ //!Returns the segment and offset
+ //!of an address
+ static void get_segment_info_and_offset(const void *ptr, segment_info_t &segment, std::size_t &offset, void *&base)
+ {
+ //------------------------------------------------------------------
+ boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
+ //------------------------------------------------------------------
+ base = 0;
+ if(s_map.m_ptr_to_segment_info.empty()){
+ segment = segment_info_t();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
+ return;
+ }
+ //Find the first base address greater than ptr
+ typename ptr_to_segment_info_t::iterator it
+ = s_map.m_ptr_to_segment_info.upper_bound(ptr);
+ if(it == s_map.m_ptr_to_segment_info.begin()){
+ segment = segment_info_t();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char *>(0);
+ }
+ //Go to the previous one
+ --it;
+ char * segment_base = const_cast<char*>(reinterpret_cast<const char*>(it->first));
+ std::size_t segment_size = it->second.size;
+
+ if(segment_base <= reinterpret_cast<const char*>(ptr) &&
+ (segment_base + segment_size) >= reinterpret_cast<const char*>(ptr)){
+ segment = it->second;
+ offset = reinterpret_cast<const char*>(ptr) - segment_base;
+ base = segment_base;
+ }
+ else{
+ segment = segment_info_t();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
+ }
+ }
+
+ //!Associates a segment defined by group/id with a base address and size.
+ //!Returns false if the group is not found or there is an error
+ static void insert_mapping(segment_group_id group_id, void *ptr, std::size_t size)
+ {
+ //------------------------------------------------------------------
+ boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
+ //------------------------------------------------------------------
+
+ typedef typename ptr_to_segment_info_t::value_type value_type;
+ typedef typename ptr_to_segment_info_t::iterator iterator;
+ typedef std::pair<iterator, bool> it_b_t;
+
+ segment_info_t info;
+ info.group = group_id;
+ info.size = size;
+ info.id = group_id->get_size();
+
+ it_b_t ret = s_map.m_ptr_to_segment_info.insert(value_type(ptr, info));
+ BOOST_ASSERT(ret.second);
+
+ value_eraser<ptr_to_segment_info_t> v_eraser(s_map.m_ptr_to_segment_info, ret.first);
+ group_id->push_back(ptr, size);
+ v_eraser.release();
+ }
+
+ static bool erase_last_mapping(segment_group_id group_id)
+ {
+ //------------------------------------------------------------------
+ boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
+ //------------------------------------------------------------------
+ if(!group_id->get_size()){
+ return false;
+ }
+ else{
+ void *addr = group_id->address_of(group_id->get_size()-1);
+ group_id->pop_back();
+ std::size_t erased = s_map.m_ptr_to_segment_info.erase(addr);
+ (void)erased;
+ BOOST_ASSERT(erased);
+ return true;
+ }
+ }
+
+ static segment_group_id new_segment_group(multi_segment_services *services)
+ {
+ { //------------------------------------------------------------------
+ boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
+ //------------------------------------------------------------------
+ typedef typename segment_groups_t::iterator iterator;
+ std::pair<iterator, bool> ret =
+ s_groups.insert(segment_group_t(*services));
+ BOOST_ASSERT(ret.second);
+ return &*ret.first;
+ }
+ }
+
+ static bool delete_group(segment_group_id id)
+ {
+ { //------------------------------------------------------------------
+ boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
+ //------------------------------------------------------------------
+ bool success = 1u == s_groups.erase(segment_group_t(*id));
+ if(success){
+ typedef typename ptr_to_segment_info_t::iterator ptr_to_segment_info_it;
+ ptr_to_segment_info_it it(s_map.m_ptr_to_segment_info.begin());
+ while(it != s_map.m_ptr_to_segment_info.end()){
+ if(it->second.group == id){
+ it = s_map.m_ptr_to_segment_info.erase(it);
+ }
+ else{
+ ++it;
+ }
+ }
+ }
+ return success;
+ }
+ }
+};
+
+//!Static map-segment_info associated with
+//!flat_map_intersegment<>
+template <class Mutex>
+typename flat_map_intersegment<Mutex>::mappings_t
+ flat_map_intersegment<Mutex>::s_map;
+
+//!Static segment group container associated with
+//!flat_map_intersegment<>
+template <class Mutex>
+typename flat_map_intersegment<Mutex>::segment_groups_t
+ flat_map_intersegment<Mutex>::s_groups;
+
+//!A smart pointer that can point to a pointee that resides in another memory
+//!memory mapped or shared memory segment.
+template <class T>
+class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
+{
+ typedef flat_map_intersegment<interprocess_mutex> PT;
+ typedef intersegment_ptr<T> self_t;
+ typedef PT base_t;
+
+ void unspecified_bool_type_func() const {}
+ typedef void (self_t::*unspecified_bool_type)() const;
+
+ public:
+ typedef T * pointer;
+ typedef typename ipcdetail::add_reference<T>::type reference;
+ typedef T value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+
+ public: //Public Functions
+
+ //!Constructor from raw pointer (allows "0" pointer conversion).
+ //!Never throws.
+ intersegment_ptr(pointer ptr = 0)
+ { base_t::set_from_pointer(ptr); }
+
+ //!Constructor from other pointer.
+ //!Never throws.
+ template <class U>
+ intersegment_ptr(U *ptr){ base_t::set_from_pointer(pointer(ptr)); }
+
+ //!Constructor from other intersegment_ptr
+ //!Never throws
+ intersegment_ptr(const intersegment_ptr& ptr)
+ { base_t::set_from_other(ptr); }
+
+ //!Constructor from other intersegment_ptr. If pointers of pointee types are
+ //!convertible, intersegment_ptrs will be convertibles. Never throws.
+ template<class T2>
+ intersegment_ptr(const intersegment_ptr<T2> &ptr)
+ { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); }
+
+ //!Emulates static_cast operator.
+ //!Never throws.
+ template<class U>
+ intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::static_cast_tag)
+ { base_t::set_from_pointer(static_cast<T*>(r.get())); }
+
+ //!Emulates const_cast operator.
+ //!Never throws.
+ template<class U>
+ intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::const_cast_tag)
+ { base_t::set_from_pointer(const_cast<T*>(r.get())); }
+
+ //!Emulates dynamic_cast operator.
+ //!Never throws.
+ template<class U>
+ intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::dynamic_cast_tag)
+ { base_t::set_from_pointer(dynamic_cast<T*>(r.get())); }
+
+ //!Emulates reinterpret_cast operator.
+ //!Never throws.
+ template<class U>
+ intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::reinterpret_cast_tag)
+ { base_t::set_from_pointer(reinterpret_cast<T*>(r.get())); }
+
+ //!Obtains raw pointer from offset.
+ //!Never throws.
+ pointer get()const
+ { return static_cast<pointer>(base_t::to_raw_pointer()); }
+
+ //!Pointer-like -> operator. It can return 0 pointer.
+ //!Never throws.
+ pointer operator->() const
+ { return self_t::get(); }
+
+ //!Dereferencing operator, if it is a null intersegment_ptr behavior
+ //!is undefined. Never throws.
+ reference operator* () const
+ { return *(self_t::get()); }
+
+ //!Indexing operator.
+ //!Never throws.
+ reference operator[](std::ptrdiff_t idx) const
+ { return self_t::get()[idx]; }
+
+ //!Assignment from pointer (saves extra conversion).
+ //!Never throws.
+ intersegment_ptr& operator= (pointer from)
+ { base_t::set_from_pointer(from); return *this; }
+
+ //!Assignment from other intersegment_ptr.
+ //!Never throws.
+ intersegment_ptr& operator= (const intersegment_ptr &ptr)
+ { base_t::set_from_other(ptr); return *this; }
+
+ //!Assignment from related intersegment_ptr. If pointers of pointee types
+ //!are assignable, intersegment_ptrs will be assignable. Never throws.
+ template <class T2>
+ intersegment_ptr& operator= (const intersegment_ptr<T2> & ptr)
+ {
+ pointer p(ptr.get()); (void)p;
+ base_t::set_from_other(ptr); return *this;
+ }
+
+ //!intersegment_ptr + std::ptrdiff_t.
+ //!Never throws.
+ intersegment_ptr operator+ (std::ptrdiff_t idx) const
+ {
+ intersegment_ptr result (*this);
+ result.inc_offset(idx*sizeof(T));
+ return result;
+ }
+
+ //!intersegment_ptr - std::ptrdiff_t.
+ //!Never throws.
+ intersegment_ptr operator- (std::ptrdiff_t idx) const
+ {
+ intersegment_ptr result (*this);
+ result.dec_offset(idx*sizeof(T));
+ return result;
+ }
+
+ //!intersegment_ptr += std::ptrdiff_t.
+ //!Never throws.
+ intersegment_ptr &operator+= (std::ptrdiff_t offset)
+ { base_t::inc_offset(offset*sizeof(T)); return *this; }
+
+ //!intersegment_ptr -= std::ptrdiff_t.
+ //!Never throws.
+ intersegment_ptr &operator-= (std::ptrdiff_t offset)
+ { base_t::dec_offset(offset*sizeof(T)); return *this; }
+
+ //!++intersegment_ptr.
+ //!Never throws.
+ intersegment_ptr& operator++ (void)
+ { base_t::inc_offset(sizeof(T)); return *this; }
+
+ //!intersegment_ptr++.
+ //!Never throws.
+ intersegment_ptr operator++ (int)
+ { intersegment_ptr temp(*this); ++*this; return temp; }
+
+ //!--intersegment_ptr.
+ //!Never throws.
+ intersegment_ptr& operator-- (void)
+ { base_t::dec_offset(sizeof(T)); return *this; }
+
+ //!intersegment_ptr--.
+ //!Never throws.
+ intersegment_ptr operator-- (int)
+ { intersegment_ptr temp(*this); --*this; return temp; }
+
+ //!Safe bool conversion operator.
+ //!Never throws.
+ operator unspecified_bool_type() const
+ { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; }
+
+ //!Not operator. Not needed in theory, but improves portability.
+ //!Never throws.
+ bool operator! () const
+ { return base_t::is_null(); }
+
+ //!Swaps two intersegment_ptr-s. More efficient than std::swap.
+ //!Never throws.
+ void swap(intersegment_ptr &other)
+ { base_t::swap(other); }
+
+ //!Calculates the distance between two intersegment_ptr-s.
+ //!This only works with two basic_intersegment_ptr pointing
+ //!to the same segment. Otherwise undefined
+ template <class T2>
+ std::ptrdiff_t _diff(const intersegment_ptr<T2> &other) const
+ { return base_t::diff(other); }
+
+ //!Returns true if both point to the
+ //!same object
+ template <class T2>
+ bool _equal(const intersegment_ptr<T2>&other) const
+ { return base_t::equal(other); }
+
+ //!Returns true if *this is less than other.
+ //!This only works with two basic_intersegment_ptr pointing
+ //!to the same segment group. Otherwise undefined. Never throws
+ template <class T2>
+ bool _less(const intersegment_ptr<T2> &other) const
+ { return base_t::less(other); }
+};
+
+//!Compares the equality of two intersegment_ptr-s.
+//!Never throws.
+template <class T1, class T2> inline
+bool operator ==(const intersegment_ptr<T1> &left,
+ const intersegment_ptr<T2> &right)
+{
+ //Make sure both pointers can be compared
+ bool e = typename intersegment_ptr<T1>::pointer(0) ==
+ typename intersegment_ptr<T2>::pointer(0);
+ (void)e;
+ return left._equal(right);
+}
+
+//!Returns true if *this is less than other.
+//!This only works with two basic_intersegment_ptr pointing
+//!to the same segment group. Otherwise undefined. Never throws
+template <class T1, class T2> inline
+bool operator <(const intersegment_ptr<T1> &left,
+ const intersegment_ptr<T2> &right)
+{
+ //Make sure both pointers can be compared
+ bool e = typename intersegment_ptr<T1>::pointer(0) <
+ typename intersegment_ptr<T2>::pointer(0);
+ (void)e;
+ return left._less(right);
+}
+
+template<class T1, class T2> inline
+bool operator!= (const intersegment_ptr<T1> &pt1,
+ const intersegment_ptr<T2> &pt2)
+{ return !(pt1 ==pt2); }
+
+//!intersegment_ptr<T1> <= intersegment_ptr<T2>.
+//!Never throws.
+template<class T1, class T2> inline
+bool operator<= (const intersegment_ptr<T1> &pt1,
+ const intersegment_ptr<T2> &pt2)
+{ return !(pt1 > pt2); }
+
+//!intersegment_ptr<T1> > intersegment_ptr<T2>.
+//!Never throws.
+template<class T1, class T2> inline
+bool operator> (const intersegment_ptr<T1> &pt1,
+ const intersegment_ptr<T2> &pt2)
+{ return (pt2 < pt1); }
+
+//!intersegment_ptr<T1> >= intersegment_ptr<T2>.
+//!Never throws.
+template<class T1, class T2> inline
+bool operator>= (const intersegment_ptr<T1> &pt1,
+ const intersegment_ptr<T2> &pt2)
+{ return !(pt1 < pt2); }
+
+//!operator<<
+template<class E, class T, class U> inline
+std::basic_ostream<E, T> & operator<<
+ (std::basic_ostream<E, T> & os, const intersegment_ptr<U> & p)
+{ return os << p.get(); }
+
+//!operator>>
+template<class E, class T, class U> inline
+std::basic_istream<E, T> & operator>>
+ (std::basic_istream<E, T> & os, intersegment_ptr<U> & p)
+{ U * tmp; return os >> tmp; p = tmp; }
+
+//!std::ptrdiff_t + intersegment_ptr.
+//!The result is another pointer of the same segment
+template<class T> inline
+intersegment_ptr<T> operator+
+ (std::ptrdiff_t diff, const intersegment_ptr<T>& right)
+{ return right + diff; }
+
+//!intersegment_ptr - intersegment_ptr.
+//!This only works with two intersegment_ptr-s that point to the
+//!same segment
+template <class T, class T2> inline
+std::ptrdiff_t operator- (const intersegment_ptr<T> &pt,
+ const intersegment_ptr<T2> &pt2)
+{ return pt._diff(pt2)/sizeof(T); }
+
+//! swap specialization
+template<class T> inline
+void swap (boost::interprocess::intersegment_ptr<T> &pt,
+ boost::interprocess::intersegment_ptr<T> &pt2)
+{ pt.swap(pt2); }
+
+//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr.
+//!Never throws.
+template<class T> inline
+T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p)
+{ return p.get(); }
+
+//!Simulation of static_cast between pointers.
+//!Never throws.
+template<class T, class U> inline
+boost::interprocess::intersegment_ptr<T> static_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
+{ return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::static_cast_tag()); }
+
+//!Simulation of const_cast between pointers.
+//!Never throws.
+template<class T, class U> inline
+boost::interprocess::intersegment_ptr<T> const_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
+{ return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::const_cast_tag()); }
+
+//!Simulation of dynamic_cast between pointers.
+//!Never throws.
+template<class T, class U> inline
+boost::interprocess::intersegment_ptr<T> dynamic_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
+{ return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::dynamic_cast_tag()); }
+
+//!Simulation of reinterpret_cast between pointers.
+//!Never throws.
+template<class T, class U> inline
+boost::interprocess::intersegment_ptr<T> reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
+{ return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); }
+
+//!Trait class to detect if an smart pointer has
+//!multi-segment addressing capabilities.
+template <class T>
+struct is_multisegment_ptr
+ <boost::interprocess::intersegment_ptr<T> >
+{
+ static const bool value = true;
+};
+
+} //namespace interprocess {
+
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+//!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr.
+//!Never throws.
+template<class T> inline
+T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p)
+{ return p.get(); }
+#endif
+
+//!has_trivial_constructor<> == true_type specialization
+//!for optimizations
+template <class T>
+struct has_trivial_constructor
+ < boost::interprocess::intersegment_ptr<T> >
+ : public true_type{};
+
+//!has_trivial_destructor<> == true_type specialization
+//!for optimizations
+template <class T>
+struct has_trivial_destructor
+ < boost::interprocess::intersegment_ptr<T> >
+ : public true_type{};
+
+} //namespace boost {
+
+#if 0
+
+//bits
+//-> is_segmented
+//-> is_relative
+//-> is_in_stack
+//-> is_pointee_outside
+
+//Data
+
+
+
+
+//segmented:
+//
+// std::size_t ctrl : CTRL_BITS;
+// std::size_t segment : MAX_SEGMENT_BITS;
+// std::size_t offset;
+
+//RELATIVE_SIZE_BITS = SIZE_T_BITS -
+// MAX_SEGMENT_BITS -
+// CTRL_BITS 10 10
+//MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52
+
+//SIZE_T_BITS - 1 - ALIGN_BITS 19 51
+//POW_SIZE_BITS = upper_log2
+// (SIZE_T_BITS - 1 - ALIGN_BITS) 5 6
+//FRC_SIZE_BITS = SIZE_T_BITS - CTRL_BITS
+// MAX_SEGMENT_SIZE_ALIGNBITS - POW_SIZE_BITS 6 5
+
+//relative:
+//
+// std::size_t ctrl : CTRL_BITS; 2 2
+// std::size_t size_pow : POW_SIZE_BITS 5 6
+// std::size_t size_frc : FRC_SIZE_BITS; 6 5
+// std::size_t start : MAX_SEGMENT_SIZE_ALIGNBITS;19 51
+// std::ptrdiff_t distance : SIZE_T_BITS; 32 64
+
+//direct:
+//
+// std::size_t ctrl : CTRL_BITS; 2 2
+// std::size_t dummy : SIZE_T_BITS - CTRL_BITS 30 62
+// void *addr : SIZE_T_BITS; 32 64
+
+//32 bits systems:
+//Page alignment: 2**12
+//
+
+//!Obtains the address pointed by the
+//!object
+void *to_raw_pointer() const
+{
+ if(this->is_pointee_outside() || this->is_in_stack()){
+ return raw_address();
+ }
+ else if(this->is_relative()){
+ return (const_cast<char*>(reinterpret_cast<const char*>(this))) + this->relative_pointee_offset();
+ }
+ else{
+ group_manager *m = get_segment_group_manager(addr);
+ char *base = static_cast<char*>(m->get_id_address(this->segmented_id()));
+ return base + this->segmented_offset();
+ }
+}
+
+void set_from_pointer(const void *ptr)
+{
+ if(!ptr){
+ this->set_pointee_outside();
+ this->raw_address(ptr);
+ }
+ else if(this->is_in_stack()){
+ this->raw_address(ptr);
+ }
+ else if(this->is_relative() &&
+ ( (ptr >= this->relative_start())
+ &&(ptr < this->relative_start() + this->relative_size()))
+ ){
+ this->relative_offset(ptr - this);
+ }
+ else{
+ segment_info_t ptr_info = get_id_from_addr(ptr);
+ segment_info_t this_info = get_id_from_addr(this);
+ if(ptr_info.segment_group != this_info.segment_group){
+ if(!ptr_info.segment_group){
+ this->set_in_stack();
+ }
+ else{
+ this->set_pointee_outside();
+ }
+ }
+ else if(ptr_info.segment_id == this_info.segment_id){
+ set_relative();
+ this->relative_size (ptr_info.size);
+ this->relative_offset(static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
+ this->relative_start (ptr_info.base);
+ }
+ }
+}
+
+void set_from_other(const self_t &other)
+{ this->set_from_pointer(other.to_raw_pointer()); }
+
+#endif
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
diff --git a/boost/interprocess/detail/managed_memory_impl.hpp b/boost/interprocess/detail/managed_memory_impl.hpp
new file mode 100644
index 0000000..31c3804
--- /dev/null
+++ b/boost/interprocess/detail/managed_memory_impl.hpp
@@ -0,0 +1,750 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/segment_manager.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+//
+#include <boost/detail/no_exceptions_support.hpp>
+//
+#include <utility>
+#include <fstream>
+#include <new>
+#include <boost/assert.hpp>
+
+//!\file
+//!Describes a named shared memory allocation user class.
+//!
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<class BasicManagedMemoryImpl>
+class create_open_func;
+
+template<
+ class CharType,
+ class MemoryAlgorithm,
+ template<class IndexConfig> class IndexType
+ >
+struct segment_manager_type
+{
+ typedef segment_manager<CharType, MemoryAlgorithm, IndexType> 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 IndexConfig> 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<class BasicManagedMemoryImpl>
+ friend class create_open_func;
+
+ public:
+ typedef typename segment_manager_type
+ <CharType, MemoryAlgorithm, IndexType>::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;
+
+ /// @cond
+
+ typedef typename
+ segment_manager::char_ptr_holder_t char_ptr_holder_t;
+ //Experimental. Don't use.
+
+ typedef typename segment_manager::multiallocation_chain multiallocation_chain;
+
+ /// @endcond
+
+ static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
+
+ private:
+ typedef basic_managed_memory_impl
+ <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
+ protected:
+ template<class ManagedMemory>
+ static bool grow(const char *filename, size_type extra_bytes)
+ {
+ typedef typename ManagedMemory::device_type device_type;
+ //Increase file size
+ 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 + extra_bytes);
+ }
+ ManagedMemory managed_memory(open_only, filename);
+ //Grow always works
+ managed_memory.self_t::grow(extra_bytes);
+ }
+ catch(...){
+ return false;
+ }
+ return true;
+ }
+
+ template<class ManagedMemory>
+ static bool shrink_to_fit(const char *filename)
+ {
+ typedef typename ManagedMemory::device_type device_type;
+ size_type new_size;
+ try{
+ ManagedMemory managed_memory(open_only, filename);
+ managed_memory.get_size();
+ managed_memory.self_t::shrink_to_fit();
+ new_size = managed_memory.get_size();
+ }
+ catch(...){
+ return false;
+ }
+
+ //Decrease file size
+ {
+ device_type f(open_or_create, filename, read_write);
+ f.truncate(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
+ mp_header = new(addr) 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<segment_manager*>(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<char*>(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<const char*>(ptr) -
+ reinterpret_cast<const char*>(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<const char*>(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<char*>(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, std::nothrow_t nothrow)
+ { return mp_header->allocate(nbytes, nothrow); }
+
+ //!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, std::nothrow_t nothrow)
+ { return mp_header->allocate_aligned(nbytes, alignment, nothrow); }
+
+ template<class T>
+ std::pair<T *, bool>
+ allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
+ size_type preferred_size,size_type &received_size,
+ T *reuse_ptr = 0)
+ {
+ return mp_header->allocation_command
+ (command, limit_size, preferred_size, received_size, reuse_ptr);
+ }
+
+ //!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); }
+
+ /// @cond
+
+ //Experimental. Don't use.
+
+ //!Allocates n_elements of elem_size bytes.
+ multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements)
+ { return mp_header->allocate_many(elem_bytes, num_elements); }
+
+ //!Allocates n_elements, each one of elem_sizes[i] bytes.
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
+ { return mp_header->allocate_many(elem_sizes, n_elements); }
+
+ //!Allocates n_elements of elem_size bytes.
+ multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow)
+ { return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
+
+ //!Allocates n_elements, each one of elem_sizes[i] bytes.
+ multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow)
+ { return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
+
+ //!Allocates n_elements, each one of elem_sizes[i] bytes.
+ void deallocate_many(multiallocation_chain chain)
+ { return mp_header->deallocate_many(boost::move(chain)); }
+
+ /// @endcond
+
+ //!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 <class T>
+ std::pair<T*, size_type> find (char_ptr_holder_t name)
+ { return mp_header->template find<T>(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 <class T>
+ typename segment_manager::template construct_proxy<T>::type
+ construct(char_ptr_holder_t name)
+ { return mp_header->template construct<T>(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 <class T>
+ typename segment_manager::template construct_proxy<T>::type
+ find_or_construct(char_ptr_holder_t name)
+ { return mp_header->template find_or_construct<T>(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 <class T>
+ typename segment_manager::template construct_proxy<T>::type
+ construct(char_ptr_holder_t name, std::nothrow_t nothrow)
+ { return mp_header->template construct<T>(name, nothrow); }
+
+ //!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 <class T>
+ typename segment_manager::template construct_proxy<T>::type
+ find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
+ { return mp_header->template find_or_construct<T>(name, nothrow); }
+
+ //!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 <class T>
+ typename segment_manager::template construct_iter_proxy<T>::type
+ construct_it(char_ptr_holder_t name)
+ { return mp_header->template construct_it<T>(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 <class T>
+ typename segment_manager::template construct_iter_proxy<T>::type
+ find_or_construct_it(char_ptr_holder_t name)
+ { return mp_header->template find_or_construct_it<T>(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 <class T>
+ typename segment_manager::template construct_iter_proxy<T>::type
+ construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
+ { return mp_header->template construct_it<T>(name, nothrow); }
+
+ //!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 <class T>
+ typename segment_manager::template construct_iter_proxy<T>::type
+ find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
+ { return mp_header->template find_or_construct_it<T>(name, nothrow); }
+
+ //!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 <class Func>
+ 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 <class Func>
+ 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 <class T>
+ bool destroy(const CharType *name)
+ { return mp_header->template destroy<T>(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 <class T>
+ bool destroy(const unique_instance_t *const )
+ { return mp_header->template destroy<T>(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 <class T>
+ void destroy_ptr(const T *ptr)
+ { mp_header->template destroy_ptr<T>(ptr); }
+
+ //!Returns the name of an object created with construct/find_or_construct
+ //!functions. Does not throw
+ template<class T>
+ 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<class T>
+ 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<class T>
+ 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<class T>
+ struct allocator
+ {
+ typedef typename segment_manager::template allocator<T>::type type;
+ };
+
+ //!Returns an instance of the default allocator for type T
+ //!initialized that allocates memory from this segment manager.
+ template<class T>
+ typename allocator<T>::type
+ get_allocator()
+ { return mp_header->template get_allocator<T>(); }
+
+ //!This is the default deleter to delete types T
+ //!from this managed segment.
+ template<class T>
+ struct deleter
+ {
+ typedef typename segment_manager::template deleter<T>::type type;
+ };
+
+ //!Returns an instance of the default allocator for type T
+ //!initialized that allocates memory from this segment manager.
+ template<class T>
+ typename deleter<T>::type
+ get_deleter()
+ { return mp_header->template get_deleter<T>(); }
+
+ /// @cond
+ //!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 <class T>
+ std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
+ { return mp_header->template find_no_lock<T>(name); }
+ /// @endcond
+
+ protected:
+ //!Swaps the segment manager's managed by this managed memory segment.
+ //!NOT thread-safe. Never throws.
+ void swap(basic_managed_memory_impl &other)
+ { std::swap(mp_header, other.mp_header); }
+
+ private:
+ segment_manager *mp_header;
+};
+
+template<class BasicManagedMemoryImpl>
+class create_open_func
+{
+ public:
+ create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
+ : m_frontend(frontend), m_type(type){}
+
+ bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const
+ {
+ if(((m_type == DoOpen) && created) ||
+ ((m_type == DoCreate) && !created))
+ return false;
+
+ if(created)
+ return m_frontend->create_impl(addr, size);
+ else
+ return m_frontend->open_impl (addr, size);
+ }
+
+ private:
+ BasicManagedMemoryImpl *m_frontend;
+ create_enum_t m_type;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
+
diff --git a/boost/interprocess/detail/managed_multi_shared_memory.hpp b/boost/interprocess/detail/managed_multi_shared_memory.hpp
new file mode 100644
index 0000000..579d1ad
--- /dev/null
+++ b/boost/interprocess/detail/managed_multi_shared_memory.hpp
@@ -0,0 +1,408 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_MULTI_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/multi_segment_services.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/containers/list.hpp>//list
+#include <boost/interprocess/mapped_region.hpp> //mapped_region
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> //managed_open_or_create_impl
+#include <new>
+#include <boost/interprocess/containers/string.hpp>
+#include <boost/interprocess/streams/vectorstream.hpp>
+#include <memory>
+#include <boost/assert.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+
+//!\file
+//!Describes a named shared memory object allocation user class.
+
+namespace boost {
+
+namespace interprocess {
+
+//TODO: We must somehow obtain the permissions of the first segment
+//to apply them to subsequent segments
+//-Use GetSecurityInfo?
+//-Change everything to use only a shared memory object expanded via truncate()?
+
+//!A basic shared memory named object creation class. Initializes the
+//!shared memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType>
+template
+ <
+ class CharType,
+ class MemoryAlgorithm,
+ template<class IndexConfig> class IndexType
+ >
+class basic_managed_multi_shared_memory
+ : public ipcdetail::basic_managed_memory_impl
+ <CharType, MemoryAlgorithm, IndexType>
+{
+
+ typedef basic_managed_multi_shared_memory
+ <CharType, MemoryAlgorithm, IndexType> self_t;
+ typedef ipcdetail::basic_managed_memory_impl
+ <CharType, MemoryAlgorithm, IndexType> base_t;
+
+ typedef typename MemoryAlgorithm::void_pointer void_pointer;
+ typedef typename ipcdetail::
+ managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment> managed_impl;
+ typedef typename void_pointer::segment_group_id segment_group_id;
+ typedef typename base_t::size_type size_type;
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Some internal helper structs/functors
+ //
+ ////////////////////////////////////////////////////////////////////////
+ //!This class defines an operator() that creates a shared memory
+ //!of the requested size. The rest of the parameters are
+ //!passed in the constructor. The class a template parameter
+ //!to be used with create_from_file/create_from_istream functions
+ //!of basic_named_object classes
+
+// class segment_creator
+// {
+// public:
+// segment_creator(shared_memory &shmem,
+// const char *mem_name,
+// const void *addr)
+// : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){}
+//
+// void *operator()(size_type size)
+// {
+// if(!m_shmem.create(m_mem_name, size, m_addr))
+// return 0;
+// return m_shmem.get_address();
+// }
+// private:
+// shared_memory &m_shmem;
+// const char *m_mem_name;
+// const void *m_addr;
+// };
+
+ class group_services
+ : public multi_segment_services
+ {
+ public:
+ typedef std::pair<void *, size_type> result_type;
+ typedef basic_managed_multi_shared_memory frontend_t;
+ typedef typename
+ basic_managed_multi_shared_memory::void_pointer void_pointer;
+ typedef typename void_pointer::segment_group_id segment_group_id;
+ group_services(frontend_t *const frontend)
+ : mp_frontend(frontend), m_group(0), m_min_segment_size(0){}
+
+ virtual std::pair<void *, size_type> create_new_segment(size_type alloc_size)
+ { (void)alloc_size;
+ /*
+ //We should allocate an extra byte so that the
+ //[base_addr + alloc_size] byte belongs to this segment
+ alloc_size += 1;
+
+ //If requested size is less than minimum, update that
+ alloc_size = (m_min_segment_size > alloc_size) ?
+ m_min_segment_size : alloc_size;
+ if(mp_frontend->priv_new_segment(create_open_func::DoCreate,
+ alloc_size, 0, permissions())){
+ typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
+ return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
+ }*/
+ return result_type(static_cast<void *>(0), 0);
+ }
+
+ virtual bool update_segments ()
+ { return true; }
+
+ virtual ~group_services(){}
+
+ void set_group(segment_group_id group)
+ { m_group = group; }
+
+ segment_group_id get_group() const
+ { return m_group; }
+
+ void set_min_segment_size(size_type min_segment_size)
+ { m_min_segment_size = min_segment_size; }
+
+ size_type get_min_segment_size() const
+ { return m_min_segment_size; }
+
+ private:
+
+ frontend_t * const mp_frontend;
+ segment_group_id m_group;
+ size_type m_min_segment_size;
+ };
+
+ //!Functor to execute atomically when opening or creating a shared memory
+ //!segment.
+ struct create_open_func
+ {
+ enum type_t { DoCreate, DoOpen, DoOpenOrCreate };
+ typedef typename
+ basic_managed_multi_shared_memory::void_pointer void_pointer;
+
+ create_open_func(self_t * const frontend,
+ type_t type, size_type segment_number)
+ : mp_frontend(frontend), m_type(type), m_segment_number(segment_number){}
+
+ bool operator()(void *addr, size_type size, bool created) const
+ {
+ if(((m_type == DoOpen) && created) ||
+ ((m_type == DoCreate) && !created))
+ return false;
+ segment_group_id group = mp_frontend->m_group_services.get_group();
+ bool mapped = false;
+ bool impl_done = false;
+
+ //Associate this newly created segment as the
+ //segment id = 0 of this group
+ void_pointer::insert_mapping
+ ( group
+ , static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
+ , size + managed_impl::ManagedOpenOrCreateUserOffset);
+ //Check if this is the master segment
+ if(!m_segment_number){
+ //Create or open the Interprocess machinery
+ if((impl_done = created ?
+ mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){
+ return true;
+ }
+ }
+ else{
+ return true;
+ }
+
+ //This is the cleanup part
+ //---------------
+ if(impl_done){
+ mp_frontend->close_impl();
+ }
+ if(mapped){
+ bool ret = void_pointer::erase_last_mapping(group);
+ BOOST_ASSERT(ret);(void)ret;
+ }
+ return false;
+ }
+ self_t * const mp_frontend;
+ type_t m_type;
+ size_type m_segment_number;
+ };
+
+ //!Functor to execute atomically when closing a shared memory segment.
+ struct close_func
+ {
+ typedef typename
+ basic_managed_multi_shared_memory::void_pointer void_pointer;
+
+ close_func(self_t * const frontend)
+ : mp_frontend(frontend){}
+
+ void operator()(const mapped_region &region, bool last) const
+ {
+ if(last) mp_frontend->destroy_impl();
+ else mp_frontend->close_impl();
+ }
+ self_t * const mp_frontend;
+ };
+
+ //Friend declarations
+ friend struct basic_managed_multi_shared_memory::create_open_func;
+ friend struct basic_managed_multi_shared_memory::close_func;
+ friend class basic_managed_multi_shared_memory::group_services;
+
+ typedef list<managed_impl> shmem_list_t;
+
+ basic_managed_multi_shared_memory *get_this_pointer()
+ { return this; }
+
+ public:
+
+ basic_managed_multi_shared_memory(create_only_t,
+ const char *name,
+ size_type size,
+ const permissions &perm = permissions())
+ : m_group_services(get_this_pointer())
+ {
+ priv_open_or_create(create_open_func::DoCreate,name, size, perm);
+ }
+
+ basic_managed_multi_shared_memory(open_or_create_t,
+ const char *name,
+ size_type size,
+ const permissions &perm = permissions())
+ : m_group_services(get_this_pointer())
+ {
+ priv_open_or_create(create_open_func::DoOpenOrCreate, name, size, perm);
+ }
+
+ basic_managed_multi_shared_memory(open_only_t, const char *name)
+ : m_group_services(get_this_pointer())
+ {
+ priv_open_or_create(create_open_func::DoOpen, name, 0, permissions());
+ }
+
+ ~basic_managed_multi_shared_memory()
+ { this->priv_close(); }
+
+ private:
+ bool priv_open_or_create(typename create_open_func::type_t type,
+ const char *name,
+ size_type size,
+ const permissions &perm)
+ {
+ if(!m_shmem_list.empty())
+ return false;
+ typename void_pointer::segment_group_id group = 0;
+ BOOST_TRY{
+ m_root_name = name;
+ //Insert multi segment services and get a group identifier
+ group = void_pointer::new_segment_group(&m_group_services);
+ size = void_pointer::round_size(size);
+ m_group_services.set_group(group);
+ m_group_services.set_min_segment_size(size);
+
+ if(group){
+ if(this->priv_new_segment(type, size, 0, perm)){
+ return true;
+ }
+ }
+ }
+ BOOST_CATCH(const std::bad_alloc&){
+ }
+ BOOST_CATCH_END
+ if(group){
+ void_pointer::delete_group(group);
+ }
+ return false;
+ }
+
+ bool priv_new_segment(typename create_open_func::type_t type,
+ size_type size,
+ const void *addr,
+ const permissions &perm)
+ {
+ BOOST_TRY{
+ //Get the number of groups of this multi_segment group
+ size_type segment_id = m_shmem_list.size();
+ //Format the name of the shared memory: append segment number.
+ boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter;
+ //Pre-reserve string size
+ size_type str_size = m_root_name.length()+10;
+ if(formatter.vector().size() < str_size){
+ //This can throw.
+ formatter.reserve(str_size);
+ }
+ //Format segment's name
+ formatter << m_root_name
+ << static_cast<unsigned int>(segment_id) << std::ends;
+ //This functor will be executed when constructing
+ create_open_func func(this, type, segment_id);
+ const char *name = formatter.vector().c_str();
+ //This can throw.
+ managed_impl mshm;
+
+ switch(type){
+ case create_open_func::DoCreate:
+ {
+ managed_impl shm(create_only, name, size, read_write, addr, func, perm);
+ mshm = boost::move(shm);
+ }
+ break;
+
+ case create_open_func::DoOpen:
+ {
+ managed_impl shm(open_only, name,read_write, addr, func);
+ mshm = boost::move(shm);
+ }
+ break;
+
+ case create_open_func::DoOpenOrCreate:
+ {
+ managed_impl shm(open_or_create, name, size, read_write, addr, func, perm);
+ mshm = boost::move(shm);
+ }
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ //This can throw.
+ m_shmem_list.push_back(boost::move(mshm));
+ return true;
+ }
+ BOOST_CATCH(const std::bad_alloc&){
+ }
+ BOOST_CATCH_END
+ return false;
+ }
+
+ //!Frees resources. Never throws.
+ void priv_close()
+ {
+ if(!m_shmem_list.empty()){
+ bool ret;
+ //Obtain group identifier
+ segment_group_id group = m_group_services.get_group();
+ //Erase main segment and its resources
+ //typename shmem_list_t::iterator itbeg = m_shmem_list.begin(),
+ // itend = m_shmem_list.end(),
+ // it = itbeg;
+ //(*itbeg)->close_with_func(close_func(this));
+ //Delete group. All mappings are erased too.
+ ret = void_pointer::delete_group(group);
+ (void)ret;
+ BOOST_ASSERT(ret);
+ m_shmem_list.clear();
+ }
+ }
+
+ private:
+ shmem_list_t m_shmem_list;
+ group_services m_group_services;
+ std::string m_root_name;
+};
+
+typedef basic_managed_multi_shared_memory
+ < char
+ , rbtree_best_fit<mutex_family, intersegment_ptr<void> >
+ , iset_index>
+ managed_multi_shared_memory;
+
+} //namespace interprocess {
+
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
+
diff --git a/boost/interprocess/detail/managed_open_or_create_impl.hpp b/boost/interprocess/detail/managed_open_or_create_impl.hpp
new file mode 100644
index 0000000..4d6997f
--- /dev/null
+++ b/boost/interprocess/detail/managed_open_or_create_impl.hpp
@@ -0,0 +1,483 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_MANAGED_OPEN_OR_CREATE_IMPL
+#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/move/move.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+
+
+template<class DeviceAbstraction>
+struct managed_open_or_create_impl_device_id_t
+{
+ typedef const char *type;
+};
+
+#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+class xsi_shared_memory_file_wrapper;
+class xsi_key;
+
+template<>
+struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper>
+{
+ typedef xsi_key type;
+};
+
+#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+/// @endcond
+
+namespace ipcdetail {
+
+
+template <bool StoreDevice, class DeviceAbstraction>
+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 DeviceAbstraction>
+class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
+{
+ public:
+ DeviceAbstraction &get_device()
+ { return dev; }
+
+ const DeviceAbstraction &get_device() const
+ { return dev; }
+
+ private:
+ DeviceAbstraction dev;
+};
+
+template<class DeviceAbstraction, std::size_t MemAlignment = 0, bool FileBased = true, bool StoreDevice = true>
+class managed_open_or_create_impl
+ : public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
+{
+ //Non-copyable
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
+
+ typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t;
+ typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder;
+ enum
+ {
+ UninitializedSegment,
+ InitializingSegment,
+ InitializedSegment,
+ CorruptedSegment
+ };
+
+ public:
+ static const std::size_t
+ ManagedOpenOrCreateUserOffset =
+ ct_rounded_size
+ < sizeof(boost::uint32_t)
+ , MemAlignment ? (MemAlignment) :
+ (::boost::alignment_of< ::boost::detail::max_align >::value)
+ >::value;
+
+ managed_open_or_create_impl()
+ {}
+
+ managed_open_or_create_impl(create_only_t,
+ const device_id_t & 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());
+ }
+
+ managed_open_or_create_impl(open_only_t,
+ const device_id_t & id,
+ mode_t mode,
+ const void *addr)
+ {
+ priv_open_or_create
+ ( DoOpen
+ , id
+ , 0
+ , mode
+ , addr
+ , permissions()
+ , null_mapped_region_function());
+ }
+
+
+ managed_open_or_create_impl(open_or_create_t,
+ const device_id_t & 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 <class ConstructFunc>
+ managed_open_or_create_impl(create_only_t,
+ const device_id_t & 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 <class ConstructFunc>
+ managed_open_or_create_impl(open_only_t,
+ const device_id_t & id,
+ mode_t mode,
+ const void *addr,
+ const ConstructFunc &construct_func)
+ {
+ priv_open_or_create
+ ( DoOpen
+ , id
+ , 0
+ , mode
+ , addr
+ , permissions()
+ , construct_func);
+ }
+
+ template <class ConstructFunc>
+ managed_open_or_create_impl(open_or_create_t,
+ const device_id_t & 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);
+ }
+
+ 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<char*>(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<bool dummy>
+ static void truncate_device(DeviceAbstraction &, offset_t, false_)
+ {} //Empty
+
+ template<bool dummy>
+ static void truncate_device(DeviceAbstraction &dev, offset_t size, true_)
+ { dev.truncate(size); }
+
+
+ template<bool dummy>
+ static bool check_offset_t_size(std::size_t , false_)
+ { return true; } //Empty
+
+ template<bool dummy>
+ 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<bool dummy>
+ static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, false_ file_like)
+ {
+ (void)file_like;
+ DeviceAbstraction tmp(create_only, id, read_write, size, perm);
+ tmp.swap(dev);
+ }
+
+ template<bool dummy>
+ static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, true_ file_like)
+ {
+ (void)file_like;
+ DeviceAbstraction tmp(create_only, id, read_write, perm);
+ tmp.swap(dev);
+ }
+
+ template <class ConstructFunc> inline
+ void priv_open_or_create
+ (create_enum_t type,
+ const device_id_t & id,
+ std::size_t size,
+ mode_t mode, const void *addr,
+ const permissions &perm,
+ ConstructFunc construct_func)
+ {
+ typedef bool_<FileBased> file_like_t;
+ (void)mode;
+ error_info err;
+ bool created = false;
+ bool ronly = false;
+ bool cow = false;
+ DeviceAbstraction dev;
+
+ if(type != DoOpen && size < ManagedOpenOrCreateUserOffset){
+ throw interprocess_exception(error_info(size_error));
+ }
+ //Check size can be represented by offset_t (used by truncate)
+ if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){
+ throw interprocess_exception(error_info(size_error));
+ }
+ if(type == DoOpen && mode == read_write){
+ DeviceAbstraction tmp(open_only, id, read_write);
+ tmp.swap(dev);
+ created = false;
+ }
+ else if(type == DoOpen && mode == read_only){
+ DeviceAbstraction tmp(open_only, id, read_only);
+ tmp.swap(dev);
+ created = false;
+ ronly = true;
+ }
+ else if(type == DoOpen && mode == copy_on_write){
+ DeviceAbstraction tmp(open_only, id, read_only);
+ tmp.swap(dev);
+ created = false;
+ cow = true;
+ }
+ else if(type == DoCreate){
+ create_device<FileBased>(dev, id, size, perm, file_like_t());
+ created = true;
+ }
+ else if(type == DoOpenOrCreate){
+ //This loop is very ugly, but brute force is sometimes better
+ //than diplomacy. If someone knows how to open or create a
+ //file and know if we have really created it or just open it
+ //drop me a e-mail!
+ bool completed = false;
+ while(!completed){
+ try{
+ create_device<FileBased>(dev, id, size, perm, file_like_t());
+ created = true;
+ completed = true;
+ }
+ catch(interprocess_exception &ex){
+ if(ex.get_error_code() != already_exists_error){
+ throw;
+ }
+ else{
+ try{
+ DeviceAbstraction tmp(open_only, id, read_write);
+ dev.swap(tmp);
+ created = false;
+ completed = true;
+ }
+ catch(interprocess_exception &ex){
+ if(ex.get_error_code() != not_found_error){
+ throw;
+ }
+ }
+ catch(...){
+ throw;
+ }
+ }
+ }
+ catch(...){
+ throw;
+ }
+ thread_yield();
+ }
+ }
+
+ if(created){
+ try{
+ //If this throws, we are lost
+ truncate_device<FileBased>(dev, 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<boost::uint32_t*>(region.get_address());
+ boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
+
+ if(previous == UninitializedSegment){
+ try{
+ construct_func(static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true);
+ //All ok, just move resources to the external mapped region
+ m_mapped_region.swap(region);
+ }
+ catch(...){
+ atomic_write32(patomic_word, CorruptedSegment);
+ throw;
+ }
+ atomic_write32(patomic_word, InitializedSegment);
+ }
+ else if(previous == InitializingSegment || previous == InitializedSegment){
+ throw interprocess_exception(error_info(already_exists_error));
+ }
+ else{
+ throw interprocess_exception(error_info(corrupted_error));
+ }
+ }
+ catch(...){
+ try{
+ truncate_device<FileBased>(dev, 1u, file_like_t());
+ }
+ catch(...){
+ }
+ throw;
+ }
+ }
+ else{
+ if(FileBased){
+ offset_t filesize = 0;
+ while(filesize == 0){
+ if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
+ throw interprocess_exception(error_info(system_error_code()));
+ }
+ thread_yield();
+ }
+ 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<boost::uint32_t*>(region.get_address());
+ boost::uint32_t value = atomic_read32(patomic_word);
+
+ while(value == InitializingSegment || value == UninitializedSegment){
+ thread_yield();
+ value = atomic_read32(patomic_word);
+ }
+
+ if(value != InitializedSegment)
+ throw interprocess_exception(error_info(corrupted_error));
+
+ construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
+ , region.get_size() - ManagedOpenOrCreateUserOffset
+ , false);
+ //All ok, just move resources to the external mapped region
+ m_mapped_region.swap(region);
+ }
+ if(StoreDevice){
+ this->DevHolder::get_device() = boost::move(dev);
+ }
+ }
+
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction()
+ { interprocess_tester::dont_close_on_destruction(m_mapped_region); }
+
+ mapped_region m_mapped_region;
+};
+
+template<class DeviceAbstraction>
+inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x
+ ,managed_open_or_create_impl<DeviceAbstraction> &y)
+{ x.swap(y); }
+
+} //namespace ipcdetail {
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
diff --git a/boost/interprocess/detail/math_functions.hpp b/boost/interprocess/detail/math_functions.hpp
new file mode 100644
index 0000000..0827416
--- /dev/null
+++ b/boost/interprocess/detail/math_functions.hpp
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Stephen Cleary 2000.
+// (C) Copyright Ion Gaztanaga 2007-2011.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file 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
+
+#include <climits>
+#include <boost/static_assert.hpp>
+
+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 <typename Integer>
+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 <typename Integer>
+inline Integer lcm(const Integer & A, const Integer & B)
+{
+ Integer ret = A;
+ ret /= gcd(A, B);
+ ret *= B;
+ return ret;
+}
+
+template <typename Integer>
+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 <typename Integer>
+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/boost/interprocess/detail/min_max.hpp b/boost/interprocess/detail/min_max.hpp
new file mode 100644
index 0000000..75aa00f
--- /dev/null
+++ b/boost/interprocess/detail/min_max.hpp
@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file 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_MIN_MAX_HPP
+#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template<class T>
+const T &max_value(const T &a, const T &b)
+{ return a > b ? a : b; }
+
+template<class T>
+const T &min_value(const T &a, const T &b)
+{ return a < b ? a : b; }
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
+
diff --git a/boost/interprocess/detail/move.hpp b/boost/interprocess/detail/move.hpp
new file mode 100644
index 0000000..1ec43b2
--- /dev/null
+++ b/boost/interprocess/detail/move.hpp
@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (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
+
+#include <boost/move/move.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using ::boost::move;
+using ::boost::forward;
+
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP
diff --git a/boost/interprocess/detail/mpl.hpp b/boost/interprocess/detail/mpl.hpp
new file mode 100644
index 0000000..c5b6f90
--- /dev/null
+++ b/boost/interprocess/detail/mpl.hpp
@@ -0,0 +1,152 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file 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_MPL_HPP
+#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template <class T, T val>
+struct integral_constant
+{
+ static const T value = val;
+ typedef integral_constant<T,val> type;
+};
+
+template< bool C_ >
+struct bool_ : integral_constant<bool, C_>
+{
+ static const bool value = C_;
+};
+
+typedef bool_<true> true_;
+typedef bool_<false> false_;
+
+typedef true_ true_type;
+typedef false_ false_type;
+
+typedef char yes_type;
+struct no_type
+{
+ char padding[8];
+};
+
+template <bool B, class T = void>
+struct enable_if_c {
+ typedef T type;
+};
+
+template <class T>
+struct enable_if_c<false, T> {};
+
+template <class Cond, class T = void>
+struct enable_if : public enable_if_c<Cond::value, T> {};
+
+template <class Cond, class T = void>
+struct disable_if : public enable_if_c<!Cond::value, T> {};
+
+template <class T, class U>
+class is_convertible
+{
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ static true_t dispatch(U);
+ static false_t dispatch(...);
+ static T trigger();
+ public:
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+template<
+ bool C
+ , typename T1
+ , typename T2
+ >
+struct if_c
+{
+ typedef T1 type;
+};
+
+template<
+ typename T1
+ , typename T2
+ >
+struct if_c<false,T1,T2>
+{
+ typedef T2 type;
+};
+
+template<
+ typename T1
+ , typename T2
+ , typename T3
+ >
+struct if_
+{
+ typedef typename if_c<0 != T1::value, T2, T3>::type type;
+};
+
+
+template <class Pair>
+struct select1st
+// : public std::unary_function<Pair, typename Pair::first_type>
+{
+ template<class OtherPair>
+ const typename Pair::first_type& operator()(const OtherPair& x) const
+ { return x.first; }
+
+ const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
+ { return x; }
+};
+
+// identity is an extension: it is not part of the standard.
+template <class T>
+struct identity
+// : public std::unary_function<T,T>
+{
+ typedef T type;
+ const T& operator()(const T& x) const
+ { return x; }
+};
+
+template<std::size_t S>
+struct ls_zeros
+{
+ static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
+};
+
+template<>
+struct ls_zeros<0>
+{
+ static const std::size_t value = 0;
+};
+
+template<>
+struct ls_zeros<1>
+{
+ static const std::size_t value = 0;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
+
diff --git a/boost/interprocess/detail/multi_segment_services.hpp b/boost/interprocess/detail/multi_segment_services.hpp
new file mode 100644
index 0000000..4b6cafc
--- /dev/null
+++ b/boost/interprocess/detail/multi_segment_services.hpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_MULTI_SEGMENT_SERVICES_HPP
+#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+
+/*!\file
+ Describes a named shared memory allocation user class.
+*/
+
+namespace boost {
+
+namespace interprocess {
+
+class multi_segment_services
+{
+ public:
+ virtual std::pair<void *, std::size_t> create_new_segment(std::size_t mem) = 0;
+ virtual bool update_segments () = 0;
+ virtual ~multi_segment_services() = 0;
+};
+
+inline multi_segment_services::~multi_segment_services()
+{}
+
+
+}} //namespace boost { namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifdef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
diff --git a/boost/interprocess/detail/named_proxy.hpp b/boost/interprocess/detail/named_proxy.hpp
new file mode 100644
index 0000000..604d788
--- /dev/null
+++ b/boost/interprocess/detail/named_proxy.hpp
@@ -0,0 +1,349 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <new>
+#include <iterator>
+#include <boost/interprocess/detail/in_place_interface.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#else
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/variadic_templates_tools.hpp>
+#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+//!\file
+//!Describes a proxy class that implements named allocation syntax.
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+template<class T, bool is_iterator, class ...Args>
+struct CtorNArg : public placement_destroy<T>
+{
+ typedef bool_<is_iterator> IsIterator;
+ typedef CtorNArg<T, is_iterator, Args...> self_t;
+ typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+
+ self_t& operator++()
+ {
+ this->do_increment(IsIterator(), index_tuple_t());
+ return *this;
+ }
+
+ self_t operator++(int) { return ++*this; *this; }
+
+ CtorNArg(Args && ...args)
+ : args_(args...)
+ {}
+
+ virtual void construct_n(void *mem
+ , std::size_t num
+ , std::size_t &constructed)
+ {
+ T* memory = static_cast<T*>(mem);
+ for(constructed = 0; constructed < num; ++constructed){
+ this->construct(memory++, IsIterator(), index_tuple_t());
+ this->do_increment(IsIterator(), index_tuple_t());
+ }
+ }
+
+ private:
+ template<int ...IdxPack>
+ void construct(void *mem, true_, const index_tuple<IdxPack...>&)
+ { new((void*)mem)T(*boost::forward<Args>(get<IdxPack>(args_))...); }
+
+ template<int ...IdxPack>
+ void construct(void *mem, false_, const index_tuple<IdxPack...>&)
+ { new((void*)mem)T(boost::forward<Args>(get<IdxPack>(args_))...); }
+
+ template<int ...IdxPack>
+ void do_increment(true_, const index_tuple<IdxPack...>&)
+ {
+ this->expansion_helper(++get<IdxPack>(args_)...);
+ }
+
+ template<class ...ExpansionArgs>
+ void expansion_helper(ExpansionArgs &&...)
+ {}
+
+ template<int ...IdxPack>
+ void do_increment(false_, const index_tuple<IdxPack...>&)
+ {}
+
+ tuple<Args&...> 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<class ...Args>
+ T *operator()(Args &&...args) const
+ {
+ CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
+ (boost::forward<Args>(args)...);
+ return mp_mngr->template
+ generic_construct<T>(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
+
+//!Function object that makes placement new
+//!without arguments
+template<class T>
+struct Ctor0Arg : public placement_destroy<T>
+{
+ typedef Ctor0Arg self_t;
+
+ Ctor0Arg(){}
+
+ self_t& operator++() { return *this; }
+ self_t operator++(int) { return *this; }
+
+ void construct(void *mem)
+ { new((void*)mem)T; }
+
+ virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
+ {
+ T* memory = static_cast<T*>(mem);
+ for(constructed = 0; constructed < num; ++constructed)
+ new((void*)memory++)T;
+ }
+};
+
+////////////////////////////////////////////////////////////////
+// What the macro should generate (n == 2):
+//
+// template<class T, bool is_iterator, class P1, class P2>
+// struct Ctor2Arg
+// : public placement_destroy<T>
+// {
+// typedef bool_<is_iterator> IsIterator;
+// typedef Ctor2Arg self_t;
+//
+// void do_increment(false_)
+// { ++m_p1; ++m_p2; }
+//
+// void do_increment(true_){}
+//
+// self_t& operator++()
+// {
+// this->do_increment(IsIterator());
+// return *this;
+// }
+//
+// self_t operator++(int) { return ++*this; *this; }
+//
+// Ctor2Arg(const P1 &p1, const P2 &p2)
+// : p1((P1 &)p_1), p2((P2 &)p_2) {}
+//
+// void construct(void *mem)
+// { new((void*)object)T(m_p1, m_p2); }
+//
+// virtual void construct_n(void *mem
+// , std::size_t num
+// , std::size_t &constructed)
+// {
+// T* memory = static_cast<T*>(mem);
+// for(constructed = 0; constructed < num; ++constructed){
+// this->construct(memory++, IsIterator());
+// this->do_increment(IsIterator());
+// }
+// }
+//
+// private:
+// void construct(void *mem, true_)
+// { new((void*)mem)T(*m_p1, *m_p2); }
+//
+// void construct(void *mem, false_)
+// { new((void*)mem)T(m_p1, m_p2); }
+//
+// P1 &m_p1; P2 &m_p2;
+// };
+////////////////////////////////////////////////////////////////
+
+//Note:
+//We define template parameters as const references to
+//be able to bind temporaries. After that we will un-const them.
+//This cast is ugly but it is necessary until "perfect forwarding"
+//is achieved in C++0x. Meanwhile, if we want to be able to
+//bind lvalues with non-const references, we have to be ugly
+#define BOOST_PP_LOCAL_MACRO(n) \
+ template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
+ struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
+ : public placement_destroy<T> \
+ { \
+ typedef bool_<is_iterator> IsIterator; \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
+ \
+ void do_increment(true_) \
+ { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); } \
+ \
+ void do_increment(false_){} \
+ \
+ self_t& operator++() \
+ { \
+ this->do_increment(IsIterator()); \
+ return *this; \
+ } \
+ \
+ self_t operator++(int) { return ++*this; *this; } \
+ \
+ BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
+ ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
+ : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {} \
+ \
+ virtual void construct_n(void *mem \
+ , std::size_t num \
+ , std::size_t &constructed) \
+ { \
+ T* memory = static_cast<T*>(mem); \
+ for(constructed = 0; constructed < num; ++constructed){ \
+ this->construct(memory++, IsIterator()); \
+ this->do_increment(IsIterator()); \
+ } \
+ } \
+ \
+ private: \
+ void construct(void *mem, true_) \
+ { \
+ new((void*)mem) T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
+ } \
+ \
+ void construct(void *mem, false_) \
+ { \
+ new((void*)mem) T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ } \
+ \
+ BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _) \
+ }; \
+//!
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+//!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)
+ {}
+
+ //!makes a named allocation and calls the
+ //!default constructor
+ T *operator()() const
+ {
+ Ctor0Arg<T> ctor_obj;
+ return mp_mngr->template
+ generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
+ }
+ //!
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
+ { \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
+ <T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
+ ctor_obj_t; \
+ ctor_obj_t ctor_obj \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ return mp_mngr->template generic_construct<T> \
+ (mp_name, m_num, m_find, m_dothrow, ctor_obj); \
+ } \
+ //!
+
+ #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ ////////////////////////////////////////////////////////////////////////
+ // What the macro should generate (n == 2)
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // template <class P1, class P2>
+ // T *operator()(P1 &p1, P2 &p2) const
+ // {
+ // typedef Ctor2Arg
+ // <T, is_iterator, P1, P2>
+ // ctor_obj_t;
+ // ctor_obj_t ctor_obj(p1, p2);
+ //
+ // return mp_mngr->template generic_construct<T>
+ // (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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp
new file mode 100644
index 0000000..b680c57
--- /dev/null
+++ b/boost/interprocess/detail/os_file_functions.hpp
@@ -0,0 +1,696 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_OS_FILE_FUNCTIONS_HPP
+#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+#include <string>
+#include <limits>
+#include <climits>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+# include <boost/interprocess/detail/win32_api.hpp>
+#else
+# ifdef BOOST_HAS_UNISTD_H
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <errno.h>
+# include <cstdio>
+# include <dirent.h>
+# if 0
+# include <sys/file.h>
+# endif
+# else
+# error Unknown platform
+# endif
+#endif
+
+#include <cstring>
+#include <cstdlib>
+
+namespace boost {
+namespace interprocess {
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef void * file_handle_t;
+typedef long long offset_t;
+typedef struct mapping_handle_impl_t{
+ void * handle;
+ bool is_shm;
+} mapping_handle_t;
+
+typedef enum { read_only = winapi::generic_read
+ , read_write = winapi::generic_read | winapi::generic_write
+ , copy_on_write
+ , read_private
+ , invalid_mode = 0xffff
+ } mode_t;
+
+typedef enum { file_begin = winapi::file_begin
+ , file_end = winapi::file_end
+ , file_current = winapi::file_current
+ } file_pos_t;
+
+namespace ipcdetail{
+
+inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
+{
+ mapping_handle_t ret;
+ ret.handle = hnd;
+ ret.is_shm = false;
+ return ret;
+}
+
+inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
+{
+ mapping_handle_t ret;
+ ret.handle = hnd;
+ ret.is_shm = true;
+ return ret;
+}
+
+inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
+{ return hnd.handle; }
+
+inline bool create_directory(const char *path)
+{ return winapi::create_directory(path); }
+
+inline const char *get_temporary_path()
+{ return std::getenv("TMP"); }
+
+
+inline file_handle_t create_new_file
+ (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+ return winapi::create_file
+ ( name, (unsigned int)mode, winapi::create_new, attr
+ , (winapi::interprocess_security_attributes*)perm.get_permissions());
+}
+
+inline file_handle_t create_or_open_file
+ (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+ return winapi::create_file
+ ( name, (unsigned int)mode, winapi::open_always, attr
+ , (winapi::interprocess_security_attributes*)perm.get_permissions());
+}
+
+inline file_handle_t open_existing_file
+ (const char *name, mode_t mode, bool temporary = false)
+{
+ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+ return winapi::create_file
+ (name, (unsigned int)mode, winapi::open_existing, attr, 0);
+}
+
+inline bool delete_file(const char *name)
+{ return winapi::unlink_file(name); }
+
+inline bool truncate_file (file_handle_t hnd, std::size_t size)
+{
+ offset_t filesize;
+ if(!winapi::get_file_size(hnd, filesize))
+ return false;
+
+ const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
+ //Avoid unused variable warnings in 32 bit systems
+ (void)max_filesize;
+ if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){
+ winapi::set_last_error(winapi::error_file_too_large);
+ return false;
+ }
+
+ if(offset_t(size) > filesize){
+ if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
+ return false;
+ }
+ //We will write zeros in the end of the file
+ //since set_end_of_file does not guarantee this
+ for(std::size_t remaining = size - filesize, write_size = 0
+ ;remaining > 0
+ ;remaining -= write_size){
+ const std::size_t DataSize = 512;
+ static char data [DataSize];
+ write_size = DataSize < remaining ? DataSize : remaining;
+ unsigned long written;
+ winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
+ if(written != write_size){
+ return false;
+ }
+ }
+ }
+ else{
+ if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
+ return false;
+ }
+ if(!winapi::set_end_of_file(hnd)){
+ return false;
+ }
+ }
+ return true;
+}
+
+inline bool get_file_size(file_handle_t hnd, offset_t &size)
+{ return winapi::get_file_size(hnd, size); }
+
+inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
+{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
+
+inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
+{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
+
+inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
+{
+ unsigned long written;
+ return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
+}
+
+inline file_handle_t invalid_file()
+{ return winapi::invalid_handle_value; }
+
+inline bool close_file(file_handle_t hnd)
+{ return 0 != winapi::close_handle(hnd); }
+
+inline bool acquire_file_lock(file_handle_t hnd)
+{
+ static winapi::interprocess_overlapped overlapped;
+ const unsigned long len = 0xffffffff;
+// winapi::interprocess_overlapped overlapped;
+// std::memset(&overlapped, 0, sizeof(overlapped));
+ return winapi::lock_file_ex
+ (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
+}
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+ const unsigned long len = 0xffffffff;
+ winapi::interprocess_overlapped overlapped;
+ std::memset(&overlapped, 0, sizeof(overlapped));
+ if(!winapi::lock_file_ex
+ (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
+ 0, len, len, &overlapped)){
+ return winapi::get_last_error() == winapi::error_lock_violation ?
+ acquired = false, true : false;
+
+ }
+ return (acquired = true);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{
+ const unsigned long len = 0xffffffff;
+ winapi::interprocess_overlapped overlapped;
+ std::memset(&overlapped, 0, sizeof(overlapped));
+ return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
+}
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{
+ const unsigned long len = 0xffffffff;
+ winapi::interprocess_overlapped overlapped;
+ std::memset(&overlapped, 0, sizeof(overlapped));
+ return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
+}
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+ const unsigned long len = 0xffffffff;
+ winapi::interprocess_overlapped overlapped;
+ std::memset(&overlapped, 0, sizeof(overlapped));
+ if(!winapi::lock_file_ex
+ (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
+ return winapi::get_last_error() == winapi::error_lock_violation ?
+ acquired = false, true : false;
+ }
+ return (acquired = true);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{ return release_file_lock(hnd); }
+
+inline bool delete_subdirectories_recursive
+ (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
+{
+ bool bSubdirectory = false; // Flag, indicating whether
+ // subdirectories have been found
+ void * hFile; // Handle to directory
+ std::string strFilePath; // Filepath
+ std::string strPattern; // Pattern
+ winapi::win32_find_data_t FileInformation; // File information
+
+ //Find all files and directories
+ strPattern = refcstrRootDirectory + "\\*.*";
+ hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
+ if(hFile != winapi::invalid_handle_value){
+ do{
+ //If it's not "." or ".." or the pointed root_level dont_delete_this erase it
+ if(FileInformation.cFileName[0] != '.' &&
+ !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
+ strFilePath.erase();
+ strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
+
+ //If it's a directory, go recursive
+ if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
+ // Delete subdirectory
+ if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
+ return false;
+ }
+ //If it's a file, just delete it
+ else{
+ // Set file attributes
+ //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
+ //return winapi::get_last_error();
+ // Delete file
+ winapi::delete_file(strFilePath.c_str());
+ }
+ }
+ //Go to the next file
+ } while(winapi::find_next_file(hFile, &FileInformation) == 1);
+
+ // Close handle
+ winapi::find_close(hFile);
+
+ //See if the loop has ended with an error or just because we've traversed all the files
+ if(winapi::get_last_error() != winapi::error_no_more_files){
+ return false;
+ }
+ else
+ {
+ //Erase empty subdirectories or original refcstrRootDirectory
+ if(!bSubdirectory && count)
+ {
+ // Set directory attributes
+ //if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
+ //return ::GetLastError();
+ // Delete directory
+ if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
+inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+ return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
+}
+
+
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+ void * hFile; // Handle to directory
+ winapi::win32_find_data_t FileInformation; // File information
+
+ //Get base directory
+ std::string str(dir);
+ const std::size_t base_root_dir_len = str.size();
+
+ //Find all files and directories
+ str += "\\*.*";
+ hFile = winapi::find_first_file(str.c_str(), &FileInformation);
+ if(hFile != winapi::invalid_handle_value){
+ do{ //Now loop every file
+ str.erase(base_root_dir_len);
+ //If it's not "." or ".." skip it
+ if(FileInformation.cFileName[0] != '.'){
+ str += "\\"; str += FileInformation.cFileName;
+ //If it's a file, apply erase logic
+ if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
+ f(str.c_str(), FileInformation.cFileName);
+ }
+ }
+ //Go to the next file
+ } while(winapi::find_next_file(hFile, &FileInformation) == 1);
+
+ // Close handle and see if the loop has ended with an error
+ winapi::find_close(hFile);
+ if(winapi::get_last_error() != winapi::error_no_more_files){
+ return false;
+ }
+ }
+ return true;
+}
+
+
+#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef int file_handle_t;
+typedef off_t offset_t;
+
+typedef struct mapping_handle_impl_t
+{
+ file_handle_t handle;
+ bool is_xsi;
+} mapping_handle_t;
+
+typedef enum { read_only = O_RDONLY
+ , read_write = O_RDWR
+ , copy_on_write
+ , read_private
+ , invalid_mode = 0xffff
+ } mode_t;
+
+typedef enum { file_begin = SEEK_SET
+ , file_end = SEEK_END
+ , file_current = SEEK_CUR
+ } file_pos_t;
+
+namespace ipcdetail{
+
+inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
+{
+ mapping_handle_t ret;
+ ret.handle = hnd;
+ ret.is_xsi = false;
+ return ret;
+}
+
+inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
+{ return hnd.handle; }
+
+inline bool create_directory(const char *path)
+{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
+
+inline const char *get_temporary_path()
+{
+ const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" };
+ const int names_size = sizeof(names)/sizeof(names[0]);
+ struct stat data;
+ for(int i = 0; i != names_size; ++i){
+ if(::stat(names[i], &data) == 0){
+ return names[i];
+ }
+ }
+ return "/tmp";
+}
+
+inline file_handle_t create_new_file
+ (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+ (void)temporary;
+ int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
+ if(ret >= 0){
+ ::fchmod(ret, perm.get_permissions());
+ }
+ return ret;
+}
+
+inline file_handle_t create_or_open_file
+ (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+ (void)temporary;
+ int ret = -1;
+ //We need a loop to change permissions correctly using fchmod, since
+ //with "O_CREAT only" ::open we don't know if we've created or opened the file.
+ while(1){
+ ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
+ if(ret >= 0){
+ ::fchmod(ret, perm.get_permissions());
+ break;
+ }
+ else if(errno == EEXIST){
+ if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+inline file_handle_t open_existing_file
+ (const char *name, mode_t mode, bool temporary = false)
+{
+ (void)temporary;
+ return ::open(name, (int)mode);
+}
+
+inline bool delete_file(const char *name)
+{ return ::unlink(name) == 0; }
+
+inline bool truncate_file (file_handle_t hnd, std::size_t size)
+{
+ if(sizeof(off_t) == sizeof(std::size_t)){
+ if(size > ((~std::size_t(0)) >> 1)){
+ errno = EINVAL;
+ return false;
+ }
+ }
+ return 0 == ::ftruncate(hnd, off_t(size));
+}
+
+inline bool get_file_size(file_handle_t hnd, offset_t &size)
+{
+ struct stat data;
+ bool ret = 0 == ::fstat(hnd, &data);
+ if(ret){
+ size = data.st_size;
+ }
+ return ret;
+}
+
+inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
+{ return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
+
+inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
+{
+ off = ::lseek(hnd, 0, SEEK_CUR);
+ return off != ((off_t)-1);
+}
+
+inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
+{ return (ssize_t(numdata)) == ::write(hnd, data, numdata); }
+
+inline file_handle_t invalid_file()
+{ return -1; }
+
+inline bool close_file(file_handle_t hnd)
+{ return ::close(hnd) == 0; }
+
+inline bool acquire_file_lock(file_handle_t hnd)
+{
+ struct ::flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ return -1 != ::fcntl(hnd, F_SETLKW, &lock);
+}
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+ struct ::flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ int ret = ::fcntl(hnd, F_SETLK, &lock);
+ if(ret == -1){
+ return (errno == EAGAIN || errno == EACCES) ?
+ acquired = false, true : false;
+ }
+ return (acquired = true);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{
+ struct ::flock lock;
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ return -1 != ::fcntl(hnd, F_SETLK, &lock);
+}
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{
+ struct ::flock lock;
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ return -1 != ::fcntl(hnd, F_SETLKW, &lock);
+}
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+ struct flock lock;
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ int ret = ::fcntl(hnd, F_SETLK, &lock);
+ if(ret == -1){
+ return (errno == EAGAIN || errno == EACCES) ?
+ acquired = false, true : false;
+ }
+ return (acquired = true);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{ return release_file_lock(hnd); }
+
+#if 0
+inline bool acquire_file_lock(file_handle_t hnd)
+{ return 0 == ::flock(hnd, LOCK_EX); }
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+ int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
+ acquired = ret == 0;
+ return (acquired || errno == EWOULDBLOCK);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{ return 0 == ::flock(hnd, LOCK_UN); }
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{ return 0 == ::flock(hnd, LOCK_SH); }
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+ int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
+ acquired = ret == 0;
+ return (acquired || errno == EWOULDBLOCK);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{ return 0 == ::flock(hnd, LOCK_UN); }
+#endif
+
+inline bool delete_subdirectories_recursive
+ (const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+ DIR *d = opendir(refcstrRootDirectory.c_str());
+ if(!d) {
+ return false;
+ }
+
+ struct dir_close
+ {
+ DIR *d_;
+ dir_close(DIR *d) : d_(d) {}
+ ~dir_close() { ::closedir(d_); }
+ } dc(d); (void)dc;
+
+ struct ::dirent *de;
+ struct ::stat st;
+ std::string fn;
+
+ while((de=::readdir(d))) {
+ if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
+ || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
+ continue;
+ }
+ if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
+ continue;
+ }
+ fn = refcstrRootDirectory;
+ fn += '/';
+ fn += de->d_name;
+
+ if(std::remove(fn.c_str())) {
+ if(::stat(fn.c_str(), & st)) {
+ return false;
+ }
+ if(S_ISDIR(st.st_mode)) {
+ if(!delete_subdirectories_recursive(fn, 0) ){
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+ return std::remove(refcstrRootDirectory.c_str()) ? false : true;
+}
+
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+ std::string refcstrRootDirectory(dir);
+
+ DIR *d = opendir(refcstrRootDirectory.c_str());
+ if(!d) {
+ return false;
+ }
+
+ struct dir_close
+ {
+ DIR *d_;
+ dir_close(DIR *d) : d_(d) {}
+ ~dir_close() { ::closedir(d_); }
+ } dc(d); (void)dc;
+
+ struct ::dirent *de;
+ struct ::stat st;
+ std::string fn;
+
+ while((de=::readdir(d))) {
+ if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
+ || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
+ continue;
+ }
+ fn = refcstrRootDirectory;
+ fn += '/';
+ fn += de->d_name;
+
+ if(::stat(fn.c_str(), & st)) {
+ return false;
+ }
+ //If it's a file, apply erase logic
+ if(!S_ISDIR(st.st_mode)) {
+ f(fn.c_str(), de->d_name);
+ }
+ }
+ return true;
+}
+
+
+//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
+inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+ return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
+}
+
+#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+inline bool open_or_create_directory(const char *dir_name)
+{
+ //If fails, check that it's because it already exists
+ if(!create_directory(dir_name)){
+ error_info info(system_error_code());
+ if(info.get_error_code() != already_exists_error){
+ return false;
+ }
+ }
+ return true;
+}
+
+
+} //namespace ipcdetail{
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp
new file mode 100644
index 0000000..e49e82c
--- /dev/null
+++ b/boost/interprocess/detail/os_thread_functions.hpp
@@ -0,0 +1,211 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_OS_THREAD_FUNCTIONS_HPP
+#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/streams/bufferstream.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+# include <boost/interprocess/detail/win32_api.hpp>
+#else
+# ifdef BOOST_HAS_UNISTD_H
+# include <pthread.h>
+# include <unistd.h>
+# include <sched.h>
+# include <time.h>
+# else
+# error Unknown platform
+# endif
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef unsigned long OS_process_id_t;
+typedef unsigned long OS_thread_id_t;
+typedef OS_thread_id_t OS_systemwide_thread_id_t;
+
+//process
+inline OS_process_id_t get_current_process_id()
+{ return winapi::get_current_process_id(); }
+
+inline OS_process_id_t get_invalid_process_id()
+{ return OS_process_id_t(0); }
+
+//thread
+inline OS_thread_id_t get_current_thread_id()
+{ return winapi::get_current_thread_id(); }
+
+inline OS_thread_id_t get_invalid_thread_id()
+{ return OS_thread_id_t(0xffffffff); }
+
+inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
+{ return id1 == id2; }
+
+inline void thread_yield()
+{ winapi::sched_yield(); }
+
+inline void thread_sleep(unsigned int ms)
+{ winapi::Sleep(ms); }
+
+//systemwide thread
+inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
+{
+ return get_current_thread_id();
+}
+
+inline void systemwide_thread_id_copy
+ (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
+{
+ to = from;
+}
+
+inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
+{
+ return equal_thread_id(id1, id2);
+}
+
+inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
+{
+ return get_invalid_thread_id();
+}
+
+inline long double get_current_process_creation_time()
+{
+ winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
+
+ get_process_times
+ ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
+
+ typedef long double ldouble_t;
+ const ldouble_t resolution = (100.0l/1000000000.0l);
+ return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
+ CreationTime.dwLowDateTime*resolution;
+}
+
+
+#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef pthread_t OS_thread_id_t;
+typedef pid_t OS_process_id_t;
+
+struct OS_systemwide_thread_id_t
+{
+ OS_systemwide_thread_id_t()
+ : pid(), tid()
+ {}
+
+ OS_systemwide_thread_id_t(pid_t p, pthread_t t)
+ : pid(p), tid(t)
+ {}
+
+ OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
+ : pid(x.pid), tid(x.tid)
+ {}
+
+ OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
+ : pid(x.pid), tid(x.tid)
+ {}
+
+ OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
+ { pid = x.pid; tid = x.tid; return *this; }
+
+ OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
+ { pid = x.pid; tid = x.tid; return *this; }
+
+ void operator=(const OS_systemwide_thread_id_t &x) volatile
+ { pid = x.pid; tid = x.tid; }
+
+ pid_t pid;
+ pthread_t tid;
+};
+
+inline void systemwide_thread_id_copy
+ (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
+{
+ to.pid = from.pid;
+ to.tid = from.tid;
+}
+
+//process
+inline OS_process_id_t get_current_process_id()
+{ return ::getpid(); }
+
+inline OS_process_id_t get_invalid_process_id()
+{ return pid_t(0); }
+
+//thread
+inline OS_thread_id_t get_current_thread_id()
+{ return ::pthread_self(); }
+
+inline OS_thread_id_t get_invalid_thread_id()
+{
+ static pthread_t invalid_id;
+ return invalid_id;
+}
+
+inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
+{ return 0 != pthread_equal(id1, id2); }
+
+inline void thread_yield()
+{ ::sched_yield(); }
+
+inline void thread_sleep(unsigned int ms)
+{
+ const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u };
+ ::nanosleep(&rqt, 0);
+}
+
+//systemwide thread
+inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
+{
+ return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
+}
+
+inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
+{
+ return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
+}
+
+inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
+{
+ return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
+}
+
+inline long double get_current_process_creation_time()
+{ return 0.0L; }
+
+#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
+
+inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
+{
+ bufferstream bstream(pid_str, sizeof(pid_str));
+ bstream << pid << std::ends;
+}
+
+inline void get_pid_str(pid_str_t &pid_str)
+{ get_pid_str(pid_str, get_current_process_id()); }
+
+} //namespace ipcdetail{
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
diff --git a/boost/interprocess/detail/pointer_type.hpp b/boost/interprocess/detail/pointer_type.hpp
new file mode 100644
index 0000000..7c45be0
--- /dev/null
+++ b/boost/interprocess/detail/pointer_type.hpp
@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011.
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct two {char _[2];};
+
+namespace pointer_type_imp {
+
+template <class U> static two test(...);
+template <class U> static char test(typename U::pointer* = 0);
+
+} //namespace pointer_type_imp {
+
+template <class T>
+struct has_pointer_type
+{
+ static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
+};
+
+namespace pointer_type_imp {
+
+template <class T, class D, bool = has_pointer_type<D>::value>
+struct pointer_type
+{
+ typedef typename D::pointer type;
+};
+
+template <class T, class D>
+struct pointer_type<T, D, false>
+{
+ typedef T* type;
+};
+
+} //namespace pointer_type_imp {
+
+template <class T, class D>
+struct pointer_type
+{
+ typedef typename pointer_type_imp::pointer_type<T,
+ typename ipcdetail::remove_reference<D>::type>::type type;
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
+
diff --git a/boost/interprocess/detail/posix_time_types_wrk.hpp b/boost/interprocess/detail/posix_time_types_wrk.hpp
new file mode 100644
index 0000000..c1276f0
--- /dev/null
+++ b/boost/interprocess/detail/posix_time_types_wrk.hpp
@@ -0,0 +1,42 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+
+//workaround to avoid winsock redefines when using date-time
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifndef WIN32_LEAN_AND_MEAN
+#endif //#ifdef _WIN32
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+
+namespace boost {
+namespace interprocess {
+
+typedef boost::date_time::microsec_clock<boost::posix_time::ptime> microsec_clock;
+
+}
+}
+
+#ifdef _WIN32
+#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifdef _WIN32
+
+#endif //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+
diff --git a/boost/interprocess/detail/preprocessor.hpp b/boost/interprocess/detail/preprocessor.hpp
new file mode 100644
index 0000000..4af2686
--- /dev/null
+++ b/boost/interprocess/detail/preprocessor.hpp
@@ -0,0 +1,137 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_PREPROCESSOR_HPP
+#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
+
+//Note:
+//We define template parameters as const references to
+//be able to bind temporaries. After that we will un-const them.
+//This cast is ugly but it is necessary until "perfect forwarding"
+//is achieved in C++0x. Meanwhile, if we want to be able to
+//bind rvalues with non-const references, we have to be ugly
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+ const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
+ //!
+#endif
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ #define BOOST_INTERPROCESS_PP_PARAM(U, u) \
+ U && u \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PP_PARAM(U, u) \
+ const U & u \
+ //!
+#endif
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (BOOST_INTERPROCESS_MOVE_NAMESPACE::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
+//!
+
+#else
+
+#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
+//!
+
+#endif
+
+#else
+#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
+//!
+#endif
+
+#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
+ BOOST_PP_CAT(++m_p, n) \
+//!
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+//!
+
+#else
+
+#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
+//!
+
+#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+
+#else
+#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+//!
+#endif
+
+#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
+::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+//!
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#include <boost/container/detail/stored_ref.hpp>
+
+#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
+::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \
+//!
+
+#else
+
+#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
+::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
+//!
+
+#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
+BOOST_PP_CAT(*m_p, n) \
+//!
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#else
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
diff --git a/boost/interprocess/detail/ptime_wrk.hpp b/boost/interprocess/detail/ptime_wrk.hpp
new file mode 100644
index 0000000..4a4709e
--- /dev/null
+++ b/boost/interprocess/detail/ptime_wrk.hpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_PTIME_WRK_HPP
+#define BOOST_INTERPROCESS_PTIME_WRK_HPP
+
+//workaround to avoid winsock redefines when using date-time
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifndef WIN32_LEAN_AND_MEAN
+#endif //#ifdef _WIN32
+
+#include <boost/date_time/posix_time/ptime.hpp>
+
+#ifdef _WIN32
+#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif //#ifdef _WIN32
+
+#endif //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
+
diff --git a/boost/interprocess/detail/robust_emulation.hpp b/boost/interprocess/detail/robust_emulation.hpp
new file mode 100644
index 0000000..b2097d0
--- /dev/null
+++ b/boost/interprocess/detail/robust_emulation.hpp
@@ -0,0 +1,439 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+namespace robust_emulation_helpers {
+
+template<class T>
+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)
+{
+ tmp_folder(s);
+ s += "/";
+ s += robust_lock_subdir_path();
+}
+
+inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid)
+{
+ file_locking_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(!file_locking_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 Mutex>
+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> mutex_traits_t;
+
+ robust_spin_mutex();
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &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 owner);
+ void owner_to_filename(boost::uint32_t owner, 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<class Mutex>
+inline robust_spin_mutex<Mutex>::robust_spin_mutex()
+ : mtx(), owner(get_invalid_process_id()), state(correct_state)
+{}
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::lock()
+{
+ //If the mutex is broken (recovery didn't call consistent()),
+ //then throw an exception
+ if(atomic_read32(&this->state) == broken_state){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ //This function provokes intermodule_singleton instantiation
+ if(!this->lock_own_unique_file()){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ //Now the logic. Try to lock, if successful mark the owner
+ //if it fails, start recovery logic
+ unsigned int spin_count = 0;
+ while(1){
+ if (mtx.try_lock()){
+ atomic_write32(&this->owner, get_current_process_id());
+ break;
+ }
+ else{
+ //Do the dead owner checking each spin_threshold lock tries
+ ipcdetail::thread_yield();
+ ++spin_count;
+ if(spin_count > spin_threshold){
+ //Check if owner dead and take ownership if possible
+ if(!this->robust_check()){
+ spin_count = 0;
+ }
+ else{
+ break;
+ }
+ }
+ }
+ }
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<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, get_current_process_id());
+ return true;
+ }
+ else{
+ if(!this->robust_check()){
+ return false;
+ }
+ else{
+ return true;
+ }
+ }
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ //Same as lock() but with an additional timeout
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ if(now >= abs_time)
+ return this->try_lock();
+
+ do{
+ if(this->try_lock()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return this->try_lock();
+ }
+ // relinquish current time slice
+ ipcdetail::thread_yield();
+ }while (true);
+
+ return true;
+}
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s)
+{
+ robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner);
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<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<class Mutex>
+inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_atomically()
+{
+ boost::uint32_t cur_owner = 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<class Mutex>
+inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t owner)
+{
+ //If owner is an invalid id, then it's clear it's dead
+ if(owner == (boost::uint32_t)get_invalid_process_id()){
+ return true;
+ }
+
+ //Obtain the lock filename of the owner field
+ std::string file;
+ this->owner_to_filename(owner, 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<class Mutex>
+inline void robust_spin_mutex<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<class Mutex>
+inline bool robust_spin_mutex<Mutex>::previous_owner_dead()
+{
+ //Notifies if a owner recovery has been performed in the last lock()
+ return atomic_read32(&this->state) == fixing_state;
+};
+
+template<class Mutex>
+inline void robust_spin_mutex<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, get_invalid_process_id());
+ mtx.unlock();
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::lock_own_unique_file()
+{
+ //This function forces instantiation of the singleton
+ robust_emulation_helpers::robust_mutex_lock_file* dummy =
+ &ipcdetail::intermodule_singleton
+ <robust_emulation_helpers::robust_mutex_lock_file>::get();
+ return dummy != 0;
+}
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif
diff --git a/boost/interprocess/detail/segment_manager_helper.hpp b/boost/interprocess/detail/segment_manager_helper.hpp
new file mode 100644
index 0000000..ea820b3
--- /dev/null
+++ b/boost/interprocess/detail/segment_manager_helper.hpp
@@ -0,0 +1,513 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/in_place_interface.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <cstddef> //std::size_t
+#include <string> //char_traits
+#include <new> //std::nothrow
+#include <utility> //std::pair
+#include <boost/assert.hpp> //BOOST_ASSERT
+#include <functional> //unary_function
+#ifndef BOOST_NO_EXCEPTIONS
+#include <exception>
+#endif
+
+//!\file
+//!Describes the object placed in a memory segment that provides
+//!named object allocation capabilities.
+
+namespace boost{
+namespace interprocess{
+
+template<class MemoryManager>
+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 MemoryAlgorithm>
+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); }
+};
+
+/// @cond
+template<class size_type>
+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 value_bytes
+ ,size_type value_alignment
+ ,unsigned char alloc_type
+ ,std::size_t sizeof_char
+ ,std::size_t num_char
+ )
+ : m_value_bytes(value_bytes)
+ , m_num_char((unsigned short)num_char)
+ , m_value_alignment((unsigned char)value_alignment)
+ , m_alloc_type_sizeof_char
+ ( (alloc_type << 5u) |
+ ((unsigned char)sizeof_char & 0x1F) )
+ {};
+
+
+ template<class T>
+ block_header &operator= (const T& )
+ { return *this; }
+
+ size_type total_size() const
+ {
+ if(alloc_type() != anonymous_type){
+ return name_offset() + (m_num_char+1)*sizeof_char();
+ }
+ else{
+ return this->value_offset() + m_value_bytes;
+ }
+ }
+
+ size_type value_bytes() const
+ { return m_value_bytes; }
+
+ template<class Header>
+ size_type total_size_with_header() const
+ {
+ return get_rounded_size
+ ( size_type(sizeof(Header))
+ , size_type(::boost::alignment_of<block_header<size_type> >::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<class CharType>
+ CharType *name() const
+ {
+ return const_cast<CharType*>(reinterpret_cast<const CharType*>
+ (reinterpret_cast<const char*>(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<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
+ }
+
+ size_type value_offset() const
+ {
+ return get_rounded_size(size_type(sizeof(block_header<size_type>)), size_type(m_value_alignment));
+ }
+
+ template<class CharType>
+ bool less_comp(const block_header<size_type> &b) const
+ {
+ return m_num_char < b.m_num_char ||
+ (m_num_char < b.m_num_char &&
+ std::char_traits<CharType>::compare
+ (name<CharType>(), b.name<CharType>(), m_num_char) < 0);
+ }
+
+ template<class CharType>
+ bool equal_comp(const block_header<size_type> &b) const
+ {
+ return m_num_char == b.m_num_char &&
+ std::char_traits<CharType>::compare
+ (name<CharType>(), b.name<CharType>(), m_num_char) == 0;
+ }
+
+ template<class T>
+ static block_header<size_type> *block_header_from_value(T *value)
+ { return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value); }
+
+ static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
+ {
+ block_header * hdr =
+ const_cast<block_header*>
+ (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(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<class Header>
+ static block_header<size_type> *from_first_header(Header *header)
+ {
+ block_header<size_type> * hdr =
+ reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
+ get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
+ //Some sanity checks
+ return hdr;
+ }
+
+ template<class Header>
+ static Header *to_first_header(block_header<size_type> *bheader)
+ {
+ Header * hdr =
+ reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
+ get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
+ //Some sanity checks
+ return hdr;
+ }
+};
+
+inline void array_construct(void *mem, std::size_t num, in_place_interface &table)
+{
+ //Try constructors
+ std::size_t constructed = 0;
+ BOOST_TRY{
+ table.construct_n(mem, num, constructed);
+ }
+ //If there is an exception call destructors and erase index node
+ BOOST_CATCH(...){
+ std::size_t destroyed = 0;
+ table.destroy_n(mem, constructed, destroyed);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+template<class CharT>
+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<instance_type type>
+class instance_t
+{
+ instance_t(){}
+};
+
+template<class T>
+struct char_if_void
+{
+ typedef T type;
+};
+
+template<>
+struct char_if_void<void>
+{
+ typedef char type;
+};
+
+typedef instance_t<anonymous_type> anonymous_instance_t;
+typedef instance_t<unique_type> unique_instance_t;
+
+
+template<class Hook, class CharType, class SizeType>
+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::alignment_of<block_header<size_type> >::value };
+
+ block_header<size_type> *get_block_header() const
+ {
+ return const_cast<block_header<size_type>*>
+ (reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
+ get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
+ }
+
+ bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
+ { return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header()); }
+
+ bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
+ { return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header()); }
+
+ static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
+ {
+ return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
+ get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
+ }
+
+ CharType *name() const
+ { return get_block_header()->template name<CharType>(); }
+
+ unsigned short name_length() const
+ { return get_block_header()->name_length(); }
+
+ void *value() const
+ { return get_block_header()->value(); }
+};
+
+template<class CharType>
+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<CharType*>(0))
+ {}
+
+ char_ptr_holder(const unique_instance_t *)
+ : m_name(reinterpret_cast<CharType*>(-1))
+ {}
+
+ operator const CharType *()
+ { return m_name; }
+
+ 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<class CharT, class VoidPointer>
+struct index_key
+{
+ typedef typename boost::intrusive::
+ pointer_traits<VoidPointer>::template
+ rebind_pointer<const CharT>::type const_char_ptr_t;
+ typedef CharT char_type;
+ typedef typename boost::intrusive::pointer_traits<const_char_ptr_t>::difference_type difference_type;
+ typedef typename boost::make_unsigned<difference_type>::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 *name, size_type length)
+ : mp_str(name), 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<char_type>::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<char_type>::compare
+ (to_raw_pointer(mp_str),
+ to_raw_pointer(right.mp_str), m_len) == 0;
+ }
+
+ void name(const CharT *name)
+ { mp_str = name; }
+
+ 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<class VoidPointer>
+struct index_data
+{
+ typedef VoidPointer void_pointer;
+ void_pointer m_ptr;
+ index_data(void *ptr) : m_ptr(ptr){}
+
+ void *value() const
+ { return static_cast<void*>(to_raw_pointer(m_ptr)); }
+};
+
+template<class MemoryAlgorithm>
+struct segment_manager_base_type
+{ typedef segment_manager_base<MemoryAlgorithm> type; };
+
+template<class CharT, class MemoryAlgorithm>
+struct index_config
+{
+ typedef typename MemoryAlgorithm::void_pointer void_pointer;
+ typedef CharT char_type;
+ typedef index_key<CharT, void_pointer> key_type;
+ typedef index_data<void_pointer> mapped_type;
+ typedef typename segment_manager_base_type
+ <MemoryAlgorithm>::type segment_manager_base;
+
+ template<class HeaderBase>
+ struct intrusive_value_type
+ { typedef intrusive_value_type_impl<HeaderBase, CharT, typename segment_manager_base::size_type> type; };
+
+ typedef intrusive_compare_key<CharT> intrusive_compare_key_type;
+};
+
+template<class Iterator, bool intrusive>
+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 Iterator>
+class segment_manager_iterator_value_adaptor<Iterator, false>
+{
+ 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 reinterpret_cast<block_header<size_type>*>
+ (to_raw_pointer(m_val->second.m_ptr))->value();
+ }
+
+ const typename Iterator::value_type *m_val;
+};
+
+template<class Iterator, bool intrusive>
+struct segment_manager_iterator_transform
+ : std::unary_function< typename Iterator::value_type
+ , segment_manager_iterator_value_adaptor<Iterator, intrusive> >
+{
+ typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
+
+ result_type operator()(const typename Iterator::value_type &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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
+
diff --git a/boost/interprocess/detail/tmp_dir_helpers.hpp b/boost/interprocess/detail/tmp_dir_helpers.hpp
new file mode 100644
index 0000000..38aafb2
--- /dev/null
+++ b/boost/interprocess/detail/tmp_dir_helpers.hpp
@@ -0,0 +1,174 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_TMP_DIR_HELPERS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+ //#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
+ //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ //#include <boost/interprocess/detail/win32_api.hpp>
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ //#include <sys/sysctl.h>
+ //#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
+ //#define BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME
+ //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ //#endif
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME)
+inline void get_bootstamp(std::string &s, bool add = false)
+{
+ std::string bootstamp;
+ winapi::get_last_bootup_time(bootstamp);
+ if(add){
+ s += bootstamp;
+ }
+ else{
+ s.swap(bootstamp);
+ }
+}
+#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
+inline void get_bootstamp(std::string &s, bool add = false)
+{
+ // FreeBSD specific: sysctl "kern.boottime"
+ int request[2] = { CTL_KERN, KERN_BOOTTIME };
+ struct ::timeval result;
+ std::size_t result_len = sizeof result;
+
+ if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
+ return;
+
+ char bootstamp_str[256];
+
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ std::size_t char_counter = 0;
+ //32 bit values to allow 32 and 64 bit process IPC
+ boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
+ for(std::size_t field = 0; field != 2; ++field){
+ for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
+ const char *ptr = (const char *)&fields[field];
+ bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
+ bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
+ }
+ }
+ bootstamp_str[char_counter] = 0;
+ if(add){
+ s += bootstamp_str;
+ }
+ else{
+ s = bootstamp_str;
+ }
+}
+#endif
+
+inline void get_tmp_base_dir(std::string &tmp_name)
+{
+ #if defined (BOOST_INTERPROCESS_WINDOWS)
+ winapi::get_shared_documents_folder(tmp_name);
+ if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
+ tmp_name = get_temporary_path();
+ }
+ #else
+ tmp_name = get_temporary_path();
+ #endif
+ if(tmp_name.empty()){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ //Remove final null.
+ tmp_name += "/boost_interprocess";
+}
+
+inline void tmp_folder(std::string &tmp_name)
+{
+ get_tmp_base_dir(tmp_name);
+ #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ tmp_name += "/";
+ get_bootstamp(tmp_name, true);
+ #endif
+}
+
+inline void tmp_filename(const char *filename, std::string &tmp_name)
+{
+ tmp_folder(tmp_name);
+ tmp_name += "/";
+ tmp_name += filename;
+}
+
+inline void create_tmp_and_clean_old(std::string &tmp_name)
+{
+ //First get the temp directory
+ std::string root_tmp_name;
+ get_tmp_base_dir(root_tmp_name);
+
+ //If fails, check that it's because already exists
+ if(!create_directory(root_tmp_name.c_str())){
+ error_info info(system_error_code());
+ if(info.get_error_code() != already_exists_error){
+ throw interprocess_exception(info);
+ }
+ }
+
+ #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ tmp_folder(tmp_name);
+
+ //If fails, check that it's because already exists
+ if(!create_directory(tmp_name.c_str())){
+ error_info info(system_error_code());
+ if(info.get_error_code() != already_exists_error){
+ throw interprocess_exception(info);
+ }
+ }
+ //Now erase all old directories created in the previous boot sessions
+ std::string subdir = tmp_name;
+ subdir.erase(0, root_tmp_name.size()+1);
+ delete_subdirectories(root_tmp_name, subdir.c_str());
+ #else
+ tmp_name = root_tmp_name;
+ #endif
+}
+
+inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
+{
+ create_tmp_and_clean_old(tmp_name);
+ tmp_name += "/";
+ tmp_name += filename;
+}
+
+inline void add_leading_slash(const char *name, std::string &new_name)
+{
+ if(name[0] != '/'){
+ new_name = '/';
+ }
+ new_name += name;
+}
+
+} //namespace boost{
+} //namespace interprocess {
+} //namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
diff --git a/boost/interprocess/detail/transform_iterator.hpp b/boost/interprocess/detail/transform_iterator.hpp
new file mode 100644
index 0000000..ef646fb
--- /dev/null
+++ b/boost/interprocess/detail/transform_iterator.hpp
@@ -0,0 +1,195 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011.
+// (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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+
+#include <iterator>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template <class PseudoReference>
+struct operator_arrow_proxy
+{
+ operator_arrow_proxy(const PseudoReference &px)
+ : m_value(px)
+ {}
+
+ PseudoReference* operator->() const { return &m_value; }
+ // This function is needed for MWCW and BCC, which won't call operator->
+ // again automatically per 13.3.1.2 para 8
+// operator T*() const { return &m_value; }
+ mutable PseudoReference m_value;
+};
+
+template <class T>
+struct operator_arrow_proxy<T&>
+{
+ operator_arrow_proxy(T &px)
+ : m_value(px)
+ {}
+
+ T* operator->() const { return const_cast<T*>(&m_value); }
+ // This function is needed for MWCW and BCC, which won't call operator->
+ // again automatically per 13.3.1.2 para 8
+// operator T*() const { return &m_value; }
+ T &m_value;
+};
+
+template <class Iterator, class UnaryFunction>
+class transform_iterator
+ : public UnaryFunction
+ , public std::iterator
+ < typename Iterator::iterator_category
+ , typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type
+ , typename Iterator::difference_type
+ , operator_arrow_proxy<typename UnaryFunction::result_type>
+ , typename UnaryFunction::result_type>
+{
+ public:
+ explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
+ : UnaryFunction(f), m_it(it)
+ {}
+
+ explicit transform_iterator()
+ : UnaryFunction(), m_it()
+ {}
+
+ //Constructors
+ transform_iterator& operator++()
+ { increment(); return *this; }
+
+ transform_iterator operator++(int)
+ {
+ transform_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ transform_iterator& operator--()
+ { decrement(); return *this; }
+
+ transform_iterator operator--(int)
+ {
+ transform_iterator result (*this);
+ decrement();
+ return result;
+ }
+
+ friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const transform_iterator& i, const transform_iterator& i2)
+ { return i < i2; }
+
+ friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i < i2); }
+
+ friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ transform_iterator& operator+=(typename Iterator::difference_type off)
+ { this->advance(off); return *this; }
+
+ transform_iterator operator+(typename Iterator::difference_type off) const
+ {
+ transform_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
+ { return right + off; }
+
+ transform_iterator& operator-=(typename Iterator::difference_type off)
+ { this->advance(-off); return *this; }
+
+ transform_iterator operator-(typename Iterator::difference_type off) const
+ { return *this + (-off); }
+
+ typename UnaryFunction::result_type operator*() const
+ { return dereference(); }
+
+ typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const
+ { return UnaryFunction::operator()(m_it[off]); }
+
+ operator_arrow_proxy<typename UnaryFunction::result_type>
+ operator->() const
+ { return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
+
+ Iterator & base()
+ { return m_it; }
+
+ const Iterator & base() const
+ { return m_it; }
+
+ private:
+ Iterator m_it;
+
+ void increment()
+ { ++m_it; }
+
+ void decrement()
+ { --m_it; }
+
+ bool equal(const transform_iterator &other) const
+ { return m_it == other.m_it; }
+
+ bool less(const transform_iterator &other) const
+ { return other.m_it < m_it; }
+
+ typename UnaryFunction::result_type dereference() const
+ { return UnaryFunction::operator()(*m_it); }
+
+ void advance(typename Iterator::difference_type n)
+ { std::advance(m_it, n); }
+
+ typename Iterator::difference_type distance_to(const transform_iterator &other)const
+ { return std::distance(other.m_it, m_it); }
+};
+
+template <class Iterator, class UnaryFunc>
+transform_iterator<Iterator, UnaryFunc>
+make_transform_iterator(Iterator it, UnaryFunc fun)
+{
+ return transform_iterator<Iterator, UnaryFunc>(it, fun);
+}
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
+
diff --git a/boost/interprocess/detail/type_traits.hpp b/boost/interprocess/detail/type_traits.hpp
new file mode 100644
index 0000000..2cfa0be
--- /dev/null
+++ b/boost/interprocess/detail/type_traits.hpp
@@ -0,0 +1,145 @@
+//////////////////////////////////////////////////////////////////////////////
+// (C) Copyright John Maddock 2000.
+// (C) Copyright Ion Gaztanaga 2005-2011.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file 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_TYPE_TRAITS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct nat{};
+
+template<class T>
+struct remove_reference
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference<T&>
+{
+ typedef T type;
+};
+
+template<class T>
+struct is_reference
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_reference<T&>
+{
+ static const bool value = true;
+};
+
+template<class T>
+struct is_pointer
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_pointer<T*>
+{
+ static const bool value = true;
+};
+
+template <typename T>
+struct add_reference
+{
+ typedef T& type;
+};
+
+template<class T>
+struct add_reference<T&>
+{
+ typedef T& type;
+};
+
+template<>
+struct add_reference<void>
+{
+ typedef nat &type;
+};
+
+template<>
+struct add_reference<const void>
+{
+ typedef const nat &type;
+};
+
+template <class T>
+struct add_const_reference
+{ typedef const T &type; };
+
+template <class T>
+struct add_const_reference<T&>
+{ typedef T& type; };
+
+template<class T>
+struct remove_const
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_const<const T>
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_volatile
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_volatile<volatile T>
+{
+ typedef T type;
+};
+
+template <typename T, typename U>
+struct is_same
+{
+ typedef char yes_type;
+ struct no_type
+ {
+ char padding[8];
+ };
+
+ template <typename V>
+ static yes_type is_same_tester(V*, V*);
+ static no_type is_same_tester(...);
+
+ static T *t;
+ static U *u;
+
+ static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
+};
+
+} // namespace ipcdetail
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp
new file mode 100644
index 0000000..625a915
--- /dev/null
+++ b/boost/interprocess/detail/utilities.hpp
@@ -0,0 +1,160 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011.
+// (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_UTILITIES_HPP
+#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/move/move.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/interprocess/detail/min_max.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/transform_iterator.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/move/move.hpp>
+#include <utility>
+#include <algorithm>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template <class T>
+inline T* to_raw_pointer(T* p)
+{ return p; }
+
+template <class Pointer>
+inline typename boost::intrusive::pointer_traits<Pointer>::element_type*
+to_raw_pointer(const Pointer &p)
+{ return boost::interprocess::ipcdetail::to_raw_pointer(p.operator->()); }
+
+//!To avoid ADL problems with swap
+template <class T>
+inline void do_swap(T& x, T& y)
+{
+ using std::swap;
+ swap(x, y);
+}
+
+//Rounds "orig_size" by excess to round_to bytes
+template<class SizeType>
+inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
+{
+ return ((orig_size-1)/round_to+1)*round_to;
+}
+
+//Truncates "orig_size" to a multiple of "multiple" bytes.
+template<class SizeType>
+inline SizeType get_truncated_size(SizeType orig_size, SizeType multiple)
+{
+ return orig_size/multiple*multiple;
+}
+
+//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
+template<class SizeType>
+inline SizeType get_rounded_size_po2(SizeType orig_size, SizeType round_to)
+{
+ return ((orig_size-1)&(~(round_to-1))) + round_to;
+}
+
+//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two
+template<class SizeType>
+inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple)
+{
+ return (orig_size & (~(multiple-1)));
+}
+
+template <std::size_t OrigSize, std::size_t RoundTo>
+struct ct_rounded_size
+{
+ static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo;
+};
+
+// Gennaro Prota wrote this. Thanks!
+template <int p, int n = 4>
+struct ct_max_pow2_less
+{
+ static const std::size_t c = 2*n < p;
+
+ static const std::size_t value =
+ c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n;
+};
+
+template <>
+struct ct_max_pow2_less<0, 0>
+{
+ static const std::size_t value = 0;
+};
+
+} //namespace ipcdetail {
+
+//!Trait class to detect if an index is a node
+//!index. This allows more efficient operations
+//!when deallocating named objects.
+template <class Index>
+struct is_node_index
+{
+ static const bool value = false;
+};
+
+//!Trait class to detect if an index is an intrusive
+//!index. This will embed the derivation hook in each
+//!allocation header, to provide memory for the intrusive
+//!container.
+template <class Index>
+struct is_intrusive_index
+{
+ static const bool value = false;
+};
+
+template <typename T> T*
+addressof(T& v)
+{
+ return reinterpret_cast<T*>(
+ &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+}
+
+//Anti-exception node eraser
+template<class Cont>
+class value_eraser
+{
+ public:
+ value_eraser(Cont & cont, typename Cont::iterator it)
+ : m_cont(cont), m_index_it(it), m_erase(true){}
+ ~value_eraser()
+ { if(m_erase) m_cont.erase(m_index_it); }
+
+ void release() { m_erase = false; }
+
+ private:
+ Cont &m_cont;
+ typename Cont::iterator m_index_it;
+ bool m_erase;
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
+
diff --git a/boost/interprocess/detail/variadic_templates_tools.hpp b/boost/interprocess/detail/variadic_templates_tools.hpp
new file mode 100644
index 0000000..1e6c421
--- /dev/null
+++ b/boost/interprocess/detail/variadic_templates_tools.hpp
@@ -0,0 +1,153 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <cstddef> //std::size_t
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<typename... Values>
+class tuple;
+
+template<> class tuple<>
+{};
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+ : private tuple<Tail...>
+{
+ typedef tuple<Tail...> inherited;
+
+ public:
+ tuple() { }
+
+ // implicit copy-constructor is okay
+ // Construct tuple from separate arguments.
+ tuple(typename add_const_reference<Head>::type v,
+ typename add_const_reference<Tail>::type... vtail)
+ : inherited(vtail...), m_head(v)
+ {}
+
+ // Construct tuple from another tuple.
+ template<typename... VValues>
+ tuple(const tuple<VValues...>& other)
+ : m_head(other.head()), inherited(other.tail())
+ {}
+
+ template<typename... VValues>
+ tuple& operator=(const tuple<VValues...>& other)
+ {
+ m_head = other.head();
+ tail() = other.tail();
+ return this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+ protected:
+ Head m_head;
+};
+
+
+template<typename... Values>
+tuple<Values&&...> tie_forward(Values&&... values)
+{ return tuple<Values&&...>(values...); }
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+
+ public:
+ typedef typename add_reference<Element>::type type;
+ typedef typename add_const_reference<Element>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+ static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+ public:
+ typedef typename add_reference<Head>::type type;
+ typedef typename add_const_reference<Head>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return t.head(); }
+ static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
+};
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+////////////////////////////////////////////////////
+// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
+// be used to "unpack" into comma-separated values
+// in a function call.
+////////////////////////////////////////////////////
+
+template<int... Indexes>
+struct index_tuple{};
+
+template<std::size_t Num, typename Tuple = index_tuple<> >
+struct build_number_seq;
+
+template<std::size_t Num, int... Indexes>
+struct build_number_seq<Num, index_tuple<Indexes...> >
+ : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
+{};
+
+template<int... Indexes>
+struct build_number_seq<0, index_tuple<Indexes...> >
+{ typedef index_tuple<Indexes...> type; };
+
+
+}}} //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp
new file mode 100644
index 0000000..b420c3d
--- /dev/null
+++ b/boost/interprocess/detail/win32_api.hpp
@@ -0,0 +1,1766 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_WIN32_PRIMITIVES_HPP
+#define BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/date_time/filetime_functions.hpp>
+#include <cstddef>
+#include <cstring>
+#include <cassert>
+#include <string>
+#include <vector>
+#include <memory>
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+# pragma comment( lib, "advapi32.lib" )
+# pragma comment( lib, "oleaut32.lib" )
+# pragma comment( lib, "Ole32.lib" )
+# pragma comment( lib, "Psapi.lib" )
+#endif
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+# include <cstdarg>
+# include <boost/detail/interlocked.hpp>
+#else
+# error "This file can only be included in Windows OS"
+#endif
+
+
+//The structures used in Interprocess with the
+//same binary interface as windows ones
+namespace boost {
+namespace interprocess {
+namespace winapi {
+
+//Some used constants
+static const unsigned long infinite_time = 0xFFFFFFFF;
+static const unsigned long error_already_exists = 183L;
+static const unsigned long error_sharing_violation = 32L;
+static const unsigned long error_file_not_found = 2u;
+static const unsigned long error_no_more_files = 18u;
+//Retries in CreateFile, see http://support.microsoft.com/kb/316609
+static const unsigned int error_sharing_violation_tries = 3u;
+static const unsigned int error_sharing_violation_sleep_ms = 250u;
+static const unsigned int error_file_too_large = 223u;
+
+static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3;
+static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001;
+
+static const unsigned long page_readonly = 0x02;
+static const unsigned long page_readwrite = 0x04;
+static const unsigned long page_writecopy = 0x08;
+
+static const unsigned long standard_rights_required = 0x000F0000L;
+static const unsigned long section_query = 0x0001;
+static const unsigned long section_map_write = 0x0002;
+static const unsigned long section_map_read = 0x0004;
+static const unsigned long section_map_execute = 0x0008;
+static const unsigned long section_extend_size = 0x0010;
+static const unsigned long section_all_access = standard_rights_required |
+ section_query |
+ section_map_write |
+ section_map_read |
+ section_map_execute |
+ section_extend_size;
+
+static const unsigned long file_map_copy = section_query;
+static const unsigned long file_map_write = section_map_write;
+static const unsigned long file_map_read = section_map_read;
+static const unsigned long file_map_all_access = section_all_access;
+static const unsigned long delete_access = 0x00010000L;
+static const unsigned long file_flag_backup_semantics = 0x02000000;
+static const long file_flag_delete_on_close = 0x04000000;
+
+//Native API constants
+static const unsigned long file_open_for_backup_intent = 0x00004000;
+static const int file_share_valid_flags = 0x00000007;
+static const long file_delete_on_close = 0x00001000L;
+static const long obj_case_insensitive = 0x00000040L;
+
+static const unsigned long movefile_copy_allowed = 0x02;
+static const unsigned long movefile_delay_until_reboot = 0x04;
+static const unsigned long movefile_replace_existing = 0x01;
+static const unsigned long movefile_write_through = 0x08;
+static const unsigned long movefile_create_hardlink = 0x10;
+static const unsigned long movefile_fail_if_not_trackable = 0x20;
+
+static const unsigned long file_share_read = 0x00000001;
+static const unsigned long file_share_write = 0x00000002;
+static const unsigned long file_share_delete = 0x00000004;
+
+static const unsigned long file_attribute_readonly = 0x00000001;
+static const unsigned long file_attribute_hidden = 0x00000002;
+static const unsigned long file_attribute_system = 0x00000004;
+static const unsigned long file_attribute_directory = 0x00000010;
+static const unsigned long file_attribute_archive = 0x00000020;
+static const unsigned long file_attribute_device = 0x00000040;
+static const unsigned long file_attribute_normal = 0x00000080;
+static const unsigned long file_attribute_temporary = 0x00000100;
+
+static const unsigned long generic_read = 0x80000000L;
+static const unsigned long generic_write = 0x40000000L;
+
+static const unsigned long wait_object_0 = 0;
+static const unsigned long wait_abandoned = 0x00000080L;
+static const unsigned long wait_timeout = 258L;
+static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF;
+
+static const unsigned long duplicate_close_source = (unsigned long)0x00000001;
+static const unsigned long duplicate_same_access = (unsigned long)0x00000002;
+
+static const unsigned long format_message_allocate_buffer
+ = (unsigned long)0x00000100;
+static const unsigned long format_message_ignore_inserts
+ = (unsigned long)0x00000200;
+static const unsigned long format_message_from_string
+ = (unsigned long)0x00000400;
+static const unsigned long format_message_from_hmodule
+ = (unsigned long)0x00000800;
+static const unsigned long format_message_from_system
+ = (unsigned long)0x00001000;
+static const unsigned long format_message_argument_array
+ = (unsigned long)0x00002000;
+static const unsigned long format_message_max_width_mask
+ = (unsigned long)0x000000FF;
+static const unsigned long lang_neutral = (unsigned long)0x00;
+static const unsigned long sublang_default = (unsigned long)0x01;
+static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF;
+static const unsigned long invalid_file_attributes = ((unsigned long)-1);
+static void * const invalid_handle_value = (void*)(long)(-1);
+static const unsigned long create_new = 1;
+static const unsigned long create_always = 2;
+static const unsigned long open_existing = 3;
+static const unsigned long open_always = 4;
+static const unsigned long truncate_existing = 5;
+
+static const unsigned long file_begin = 0;
+static const unsigned long file_current = 1;
+static const unsigned long file_end = 2;
+
+static const unsigned long lockfile_fail_immediately = 1;
+static const unsigned long lockfile_exclusive_lock = 2;
+static const unsigned long error_lock_violation = 33;
+static const unsigned long security_descriptor_revision = 1;
+
+//Own defines
+static const long SystemTimeOfDayInfoLength = 48;
+static const long BootAndSystemstampLength = 16;
+static const long BootstampLength = 8;
+static const unsigned long MaxPath = 260;
+
+
+//Keys
+static void * const hkey_local_machine = (void*)(unsigned long*)(long)(0x80000002);
+static unsigned long key_query_value = 0x0001;
+
+//COM API
+const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4;
+const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL;
+const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL;
+const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3;
+const signed long EOAC_NONE_BIPC = 0;
+const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1;
+const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4;
+const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10;
+const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0;
+const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20;
+const signed long WBEM_INFINITE_BIPC = 0xffffffffL;
+const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L;
+const signed long S_OK_BIPC = 0L;
+const signed long S_FALSE_BIPC = 1;
+
+} //namespace winapi {
+} //namespace interprocess {
+} //namespace boost {
+
+
+namespace boost {
+namespace interprocess {
+namespace winapi {
+
+struct GUID_BIPC
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+};
+
+const GUID_BIPC CLSID_WbemAdministrativeLocator =
+ { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}};
+
+const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
+
+struct wchar_variant
+{
+ unsigned long long dummy;
+ union value_t{
+ wchar_t *pbstrVal;
+ unsigned long long dummy;
+ } value;
+};
+
+ struct IUnknown_BIPC
+ {
+ public:
+ virtual long __stdcall QueryInterface(
+ /* [in] */ const GUID_BIPC &riid,
+ /* [iid_is][out] */ void **ppvObject) = 0;
+
+ virtual unsigned long __stdcall AddRef( void) = 0;
+
+ virtual unsigned long __stdcall Release( void) = 0;
+ };
+
+struct IWbemClassObject_BIPC : public IUnknown_BIPC
+{
+ public:
+ virtual long __stdcall GetQualifierSet(
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall Get(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_variant *pVal,
+ /* [unique][in][out] */ long *pType,
+ /* [unique][in][out] */ long *plFlavor) = 0;
+
+ virtual long __stdcall Put(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pVal,
+ /* [in] */ long Type) = 0;
+
+ virtual long __stdcall Delete(
+ /* [string][in] */ const wchar_t * wszName) = 0;
+
+ virtual long __stdcall GetNames(
+ /* [string][in] */ const wchar_t * wszQualifierName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pQualifierVal,
+ /* [out] */ void * *pNames) = 0;
+
+ virtual long __stdcall BeginEnumeration(
+ /* [in] */ long lEnumFlags) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_t * *strName,
+ /* [unique][in][out] */ wchar_variant *pVal,
+ /* [unique][in][out] */ long *pType,
+ /* [unique][in][out] */ long *plFlavor) = 0;
+
+ virtual long __stdcall EndEnumeration( void) = 0;
+
+ virtual long __stdcall GetPropertyQualifierSet(
+ /* [string][in] */ const wchar_t * wszProperty,
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall Clone(
+ /* [out] */ IWbemClassObject_BIPC **ppCopy) = 0;
+
+ virtual long __stdcall GetObjectText(
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_t * *pstrObjectText) = 0;
+
+ virtual long __stdcall SpawnDerivedClass(
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_BIPC **ppNewClass) = 0;
+
+ virtual long __stdcall SpawnInstance(
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_BIPC **ppNewInstance) = 0;
+
+ virtual long __stdcall CompareTo(
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0;
+
+ virtual long __stdcall GetPropertyOrigin(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [out] */ wchar_t * *pstrClassName) = 0;
+
+ virtual long __stdcall InheritsFrom(
+ /* [in] */ const wchar_t * strAncestor) = 0;
+
+ virtual long __stdcall GetMethod(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_BIPC **ppInSignature,
+ /* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
+
+ virtual long __stdcall PutMethod(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemClassObject_BIPC *pInSignature,
+ /* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0;
+
+ virtual long __stdcall DeleteMethod(
+ /* [string][in] */ const wchar_t * wszName) = 0;
+
+ virtual long __stdcall BeginMethodEnumeration(
+ /* [in] */ long lEnumFlags) = 0;
+
+ virtual long __stdcall NextMethod(
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_t * *pstrName,
+ /* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature,
+ /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0;
+
+ virtual long __stdcall EndMethodEnumeration( void) = 0;
+
+ virtual long __stdcall GetMethodQualifierSet(
+ /* [string][in] */ const wchar_t * wszMethod,
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall GetMethodOrigin(
+ /* [string][in] */ const wchar_t * wszMethodName,
+ /* [out] */ wchar_t * *pstrClassName) = 0;
+
+};
+
+
+struct IWbemContext_BIPC : public IUnknown_BIPC
+{
+public:
+ virtual long __stdcall Clone(
+ /* [out] */ IWbemContext_BIPC **ppNewCopy) = 0;
+
+ virtual long __stdcall GetNames(
+ /* [in] */ long lFlags,
+ /* [out] */ void * *pNames) = 0;
+
+ virtual long __stdcall BeginEnumeration(
+ /* [in] */ long lFlags) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_t * *pstrName,
+ /* [out] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall EndEnumeration( void) = 0;
+
+ virtual long __stdcall SetValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall GetValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall DeleteValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags) = 0;
+
+ virtual long __stdcall DeleteAll( void) = 0;
+
+};
+
+
+struct IEnumWbemClassObject_BIPC : public IUnknown_BIPC
+{
+public:
+ virtual long __stdcall Reset( void) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lTimeout,
+ /* [in] */ unsigned long uCount,
+ /* [length_is][size_is][out] */ IWbemClassObject_BIPC **apObjects,
+ /* [out] */ unsigned long *puReturned) = 0;
+
+ virtual long __stdcall NextAsync(
+ /* [in] */ unsigned long uCount,
+ /* [in] */ void *pSink) = 0;
+
+ virtual long __stdcall Clone(
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall Skip(
+ /* [in] */ long lTimeout,
+ /* [in] */ unsigned long nCount) = 0;
+
+};
+
+struct IWbemServices_BIPC : public IUnknown_BIPC
+{
+public:
+ virtual long __stdcall OpenNamespace(
+ /* [in] */ const wchar_t * strNamespace,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppWorkingNamespace,
+ /* [unique][in][out] */ void **ppResult) = 0;
+
+ virtual long __stdcall CancelAsyncCall(
+ /* [in] */ void *pSink) = 0;
+
+ virtual long __stdcall QueryObjectSink(
+ /* [in] */ long lFlags,
+ /* [out] */ void **ppResponseHandler) = 0;
+
+ virtual long __stdcall GetObject(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppObject,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall GetObjectAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall PutClass(
+ /* [in] */ IWbemClassObject_BIPC *pObject,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall PutClassAsync(
+ /* [in] */ IWbemClassObject_BIPC *pObject,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall DeleteClass(
+ /* [in] */ const wchar_t * strClass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall DeleteClassAsync(
+ /* [in] */ const wchar_t * strClass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall CreateClassEnum(
+ /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall CreateClassEnumAsync(
+ /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall PutInstance(
+ /* [in] */ void *pInst,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall PutInstanceAsync(
+ /* [in] */ void *pInst,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall DeleteInstance(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall DeleteInstanceAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall CreateInstanceEnum(
+ /* [in] */ const wchar_t * strFilter,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall CreateInstanceEnumAsync(
+ /* [in] */ const wchar_t * strFilter,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecQuery(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0;
+
+ virtual long __stdcall ExecQueryAsync(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecNotificationQuery(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall ExecNotificationQueryAsync(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecMethod(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [in] */ IWbemClassObject_BIPC *pInParams,
+ /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutParams,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall ExecMethodAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_BIPC *pCtx,
+ /* [in] */ IWbemClassObject_BIPC *pInParams,
+ /* [in] */ void *pResponseHandler) = 0;
+
+};
+
+struct IWbemLocator_BIPC : public IUnknown_BIPC
+{
+public:
+ virtual long __stdcall ConnectServer(
+ /* [in] */ const wchar_t * strNetworkResource,
+ /* [in] */ const wchar_t * strUser,
+ /* [in] */ const wchar_t * strPassword,
+ /* [in] */ const wchar_t * strLocale,
+ /* [in] */ long lSecurityFlags,
+ /* [in] */ const wchar_t * strAuthority,
+ /* [in] */ void *pCtx,
+ /* [out] */ IWbemServices_BIPC **ppNamespace) = 0;
+
+};
+
+
+
+struct interprocess_overlapped
+{
+ unsigned long *internal;
+ unsigned long *internal_high;
+ union {
+ struct {
+ unsigned long offset;
+ unsigned long offset_high;
+ }dummy;
+ void *pointer;
+ };
+
+ void *h_event;
+};
+
+struct interprocess_filetime
+{
+ unsigned long dwLowDateTime;
+ unsigned long dwHighDateTime;
+};
+
+struct win32_find_data_t
+{
+ unsigned long dwFileAttributes;
+ interprocess_filetime ftCreationTime;
+ interprocess_filetime ftLastAccessTime;
+ interprocess_filetime ftLastWriteTime;
+ unsigned long nFileSizeHigh;
+ unsigned long nFileSizeLow;
+ unsigned long dwReserved0;
+ unsigned long dwReserved1;
+ char cFileName[MaxPath];
+ char cAlternateFileName[14];
+};
+
+struct interprocess_security_attributes
+{
+ unsigned long nLength;
+ void *lpSecurityDescriptor;
+ int bInheritHandle;
+};
+
+struct system_info {
+ union {
+ unsigned long dwOemId; // Obsolete field...do not use
+ struct {
+ unsigned short wProcessorArchitecture;
+ unsigned short wReserved;
+ } dummy;
+ };
+ unsigned long dwPageSize;
+ void * lpMinimumApplicationAddress;
+ void * lpMaximumApplicationAddress;
+ unsigned long * dwActiveProcessorMask;
+ unsigned long dwNumberOfProcessors;
+ unsigned long dwProcessorType;
+ unsigned long dwAllocationGranularity;
+ unsigned short wProcessorLevel;
+ unsigned short wProcessorRevision;
+};
+
+struct interprocess_memory_basic_information
+{
+ void * BaseAddress;
+ void * AllocationBase;
+ unsigned long AllocationProtect;
+ unsigned long RegionSize;
+ unsigned long State;
+ unsigned long Protect;
+ unsigned long Type;
+};
+
+typedef struct _interprocess_acl
+{
+ unsigned char AclRevision;
+ unsigned char Sbz1;
+ unsigned short AclSize;
+ unsigned short AceCount;
+ unsigned short Sbz2;
+} interprocess_acl;
+
+typedef struct _interprocess_security_descriptor
+{
+ unsigned char Revision;
+ unsigned char Sbz1;
+ unsigned short Control;
+ void *Owner;
+ void *Group;
+ interprocess_acl *Sacl;
+ interprocess_acl *Dacl;
+} interprocess_security_descriptor;
+
+enum file_information_class_t {
+ file_directory_information = 1,
+ file_full_directory_information,
+ file_both_directory_information,
+ file_basic_information,
+ file_standard_information,
+ file_internal_information,
+ file_ea_information,
+ file_access_information,
+ file_name_information,
+ file_rename_information,
+ file_link_information,
+ file_names_information,
+ file_disposition_information,
+ file_position_information,
+ file_full_ea_information,
+ file_mode_information,
+ file_alignment_information,
+ file_all_information,
+ file_allocation_information,
+ file_end_of_file_information,
+ file_alternate_name_information,
+ file_stream_information,
+ file_pipe_information,
+ file_pipe_local_information,
+ file_pipe_remote_information,
+ file_mailslot_query_information,
+ file_mailslot_set_information,
+ file_compression_information,
+ file_copy_on_write_information,
+ file_completion_information,
+ file_move_cluster_information,
+ file_quota_information,
+ file_reparse_point_information,
+ file_network_open_information,
+ file_object_id_information,
+ file_tracking_information,
+ file_ole_directory_information,
+ file_content_index_information,
+ file_inherit_content_index_information,
+ file_ole_information,
+ file_maximum_information
+};
+
+struct file_name_information_t {
+ unsigned long FileNameLength;
+ wchar_t FileName[1];
+};
+
+struct file_rename_information_t {
+ int Replace;
+ void *RootDir;
+ unsigned long FileNameLength;
+ wchar_t FileName[1];
+};
+
+struct unicode_string_t {
+ unsigned short Length;
+ unsigned short MaximumLength;
+ wchar_t *Buffer;
+};
+
+struct object_attributes_t {
+ unsigned long Length;
+ void * RootDirectory;
+ unicode_string_t *ObjectName;
+ unsigned long Attributes;
+ void *SecurityDescriptor;
+ void *SecurityQualityOfService;
+};
+
+struct io_status_block_t {
+ union {
+ long Status;
+ void *Pointer;
+ };
+
+ unsigned long *Information;
+};
+
+union system_timeofday_information
+{
+ struct data_t
+ {
+ __int64 liKeBootTime;
+ __int64 liKeSystemTime;
+ __int64 liExpTimeZoneBias;
+ unsigned long uCurrentTimeZoneId;
+ unsigned long dwReserved;
+ } data;
+ unsigned char Reserved1[SystemTimeOfDayInfoLength];
+};
+
+struct interprocess_by_handle_file_information
+{
+ unsigned long dwFileAttributes;
+ interprocess_filetime ftCreationTime;
+ interprocess_filetime ftLastAccessTime;
+ interprocess_filetime ftLastWriteTime;
+ unsigned long dwVolumeSerialNumber;
+ unsigned long nFileSizeHigh;
+ unsigned long nFileSizeLow;
+ unsigned long nNumberOfLinks;
+ unsigned long nFileIndexHigh;
+ unsigned long nFileIndexLow;
+};
+
+enum system_information_class {
+ system_basic_information = 0,
+ system_performance_information = 2,
+ system_time_of_day_information = 3,
+ system_process_information = 5,
+ system_processor_performance_information = 8,
+ system_interrupt_information = 23,
+ system_exception_information = 33,
+ system_registry_quota_information = 37,
+ system_lookaside_information = 45
+};
+
+enum object_information_class
+{
+ object_basic_information,
+ object_name_information,
+ object_type_information,
+ object_all_information,
+ object_data_information
+};
+
+struct object_name_information_t
+{
+ unicode_string_t Name;
+ wchar_t NameBuffer[1];
+};
+
+//Some windows API declarations
+extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
+extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
+extern "C" __declspec(dllimport) int __stdcall GetProcessTimes
+ ( void *hProcess, interprocess_filetime* lpCreationTime
+ , interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime
+ , interprocess_filetime *lpUserTime );
+extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
+extern "C" __declspec(dllimport) int __stdcall SwitchToThread();
+extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
+extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long);
+extern "C" __declspec(dllimport) void * __stdcall GetCurrentProcess();
+extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*);
+extern "C" __declspec(dllimport) int __stdcall DuplicateHandle
+ ( void *hSourceProcessHandle, void *hSourceHandle
+ , void *hTargetProcessHandle, void **lpTargetHandle
+ , unsigned long dwDesiredAccess, int bInheritHandle
+ , unsigned long dwOptions);
+extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData);
+extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData);
+extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
+//extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
+//extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out);
+extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *);
+extern "C" __declspec(dllimport) void * __stdcall OpenMutexA(unsigned long, int, const char *);
+extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void *, unsigned long);
+extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void *);
+extern "C" __declspec(dllimport) int __stdcall UnmapViewOfFile(void *);
+extern "C" __declspec(dllimport) void * __stdcall CreateSemaphoreA(interprocess_security_attributes*, long, long, const char *);
+extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void *, long, long *);
+extern "C" __declspec(dllimport) void * __stdcall OpenSemaphoreA(unsigned long, int, const char *);
+extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, interprocess_security_attributes*, unsigned long, unsigned long, unsigned long, const char *);
+extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*);
+extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
+extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *);
+extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *);
+extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long);
+extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
+extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
+extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *);
+extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
+extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
+ (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
+ unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize,
+ std::va_list *Arguments);
+extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *);
+extern "C" __declspec(dllimport) unsigned long __stdcall GetFileAttributesA(const char *);
+extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*);
+extern "C" __declspec(dllimport) int __stdcall RemoveDirectoryA(const char *lpPathName);
+extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer);
+extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*);
+extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size);
+extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *);
+extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method);
+extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
+extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
+extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
+extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
+extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped);
+extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
+extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
+extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *);
+extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *);
+extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*);
+extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*);
+extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
+extern "C" __declspec(dllimport) unsigned long __stdcall GetMappedFileNameW(void *, void *, wchar_t *, unsigned long);
+extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(void *, const char *, unsigned long, unsigned long, void **);
+extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
+extern "C" __declspec(dllimport) long __stdcall RegCloseKey(void *);
+extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount);
+
+//COM API
+extern "C" __declspec(dllimport) long __stdcall CoInitialize(void *pvReserved);
+extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
+ void* pSecDesc,
+ long cAuthSvc,
+ void *asAuthSvc,
+ void *pReserved1,
+ unsigned long dwAuthnLevel,
+ unsigned long dwImpLevel,
+ void *pAuthList,
+ unsigned long dwCapabilities,
+ void *pReserved3 );
+
+ extern "C" __declspec(dllimport) long __stdcall CoSetProxyBlanket(
+ IUnknown_BIPC *pProxy,
+ unsigned long dwAuthnSvc,
+ unsigned long dwAuthzSvc,
+ wchar_t *pServerPrincName,
+ unsigned long dwAuthnLevel,
+ unsigned long dwImpLevel,
+ void *pAuthInfo,
+ unsigned long dwCapabilities);
+
+extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
+extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_BIPC & rclsid, IUnknown_BIPC *pUnkOuter,
+ unsigned long dwClsContext, const GUID_BIPC & riid, void** ppv);
+extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void);
+
+
+
+//API function typedefs
+//Pointer to functions
+typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
+typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass );
+typedef long (__stdcall * NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *);
+typedef long (__stdcall * NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *);
+typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int);
+typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long);
+typedef long (__stdcall *NtClose_t) (void*);
+typedef long (__stdcall *RtlCreateUnicodeStringFromAsciiz_t)(unicode_string_t *, const char *);
+typedef void (__stdcall *RtlFreeUnicodeString_t)(unicode_string_t *);
+typedef void (__stdcall *RtlInitUnicodeString_t)( unicode_string_t *, const wchar_t * );
+typedef long (__stdcall *RtlAppendUnicodeToString_t)(unicode_string_t *Destination, const wchar_t *Source);
+typedef unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long);
+typedef long (__stdcall * RegOpenKeyEx_t)(void *, const char *, unsigned long, unsigned long, void **);
+typedef long (__stdcall * RegQueryValueEx_t)(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*);
+typedef long (__stdcall * RegCloseKey_t)(void *);
+
+} //namespace winapi {
+} //namespace interprocess {
+} //namespace boost {
+
+namespace boost {
+namespace interprocess {
+namespace winapi {
+
+inline unsigned long get_last_error()
+{ return GetLastError(); }
+
+inline void set_last_error(unsigned long err)
+{ return SetLastError(err); }
+
+inline unsigned long format_message
+ (unsigned long dwFlags, const void *lpSource,
+ unsigned long dwMessageId, unsigned long dwLanguageId,
+ char *lpBuffer, unsigned long nSize, std::va_list *Arguments)
+{
+ return FormatMessageA
+ (dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
+}
+
+//And now, wrapper functions
+inline void * local_free(void *hmem)
+{ return LocalFree(hmem); }
+
+inline unsigned long make_lang_id(unsigned long p, unsigned long s)
+{ return ((((unsigned short)(s)) << 10) | (unsigned short)(p)); }
+
+inline void sched_yield()
+{
+ if(!SwitchToThread()){
+ Sleep(1);
+ }
+}
+
+inline void sleep(unsigned long ms)
+{ Sleep(ms); }
+
+inline unsigned long get_current_thread_id()
+{ return GetCurrentThreadId(); }
+
+inline bool get_process_times
+ ( void *hProcess, interprocess_filetime* lpCreationTime
+ , interprocess_filetime *lpExitTime, interprocess_filetime *lpKernelTime
+ , interprocess_filetime *lpUserTime )
+{ return 0 != GetProcessTimes(hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); }
+
+inline unsigned long get_current_process_id()
+{ return GetCurrentProcessId(); }
+
+inline unsigned int close_handle(void* handle)
+{ return CloseHandle(handle); }
+
+inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData)
+{ return FindFirstFileA(lpFileName, lpFindFileData); }
+
+inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData)
+{ return FindNextFileA(hFindFile, lpFindFileData) != 0; }
+
+inline bool find_close(void *handle)
+{ return FindClose(handle) != 0; }
+
+inline bool duplicate_current_process_handle
+ (void *hSourceHandle, void **lpTargetHandle)
+{
+ return 0 != DuplicateHandle
+ ( GetCurrentProcess(), hSourceHandle, GetCurrentProcess()
+ , lpTargetHandle, 0, 0
+ , duplicate_same_access);
+}
+/*
+inline void get_system_time_as_file_time(interprocess_filetime *filetime)
+{ GetSystemTimeAsFileTime(filetime); }
+
+inline bool file_time_to_local_file_time
+ (const interprocess_filetime *in, const interprocess_filetime *out)
+{ return 0 != FileTimeToLocalFileTime(in, out); }
+*/
+inline void *open_or_create_mutex(const char *name, bool initial_owner, interprocess_security_attributes *attr)
+{ return CreateMutexA(attr, (int)initial_owner, name); }
+
+inline unsigned long wait_for_single_object(void *handle, unsigned long time)
+{ return WaitForSingleObject(handle, time); }
+
+inline int release_mutex(void *handle)
+{ return ReleaseMutex(handle); }
+
+inline int unmap_view_of_file(void *address)
+{ return UnmapViewOfFile(address); }
+
+inline void *open_or_create_semaphore(const char *name, long initial_count, long maximum_count, interprocess_security_attributes *attr)
+{ return CreateSemaphoreA(attr, initial_count, maximum_count, name); }
+
+inline int release_semaphore(void *handle, long release_count, long *prev_count)
+{ return ReleaseSemaphore(handle, release_count, prev_count); }
+
+class interprocess_all_access_security
+{
+ interprocess_security_attributes sa;
+ interprocess_security_descriptor sd;
+ bool initialized;
+
+ public:
+ interprocess_all_access_security()
+ : initialized(false)
+ {
+ if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision))
+ return;
+ if(!SetSecurityDescriptorDacl(&sd, true, 0, false))
+ return;
+ sa.lpSecurityDescriptor = &sd;
+ sa.nLength = sizeof(interprocess_security_attributes);
+ sa.bInheritHandle = false;
+ initialized = false;
+ }
+
+ interprocess_security_attributes *get_attributes()
+ { return &sa; }
+};
+
+inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name, interprocess_security_attributes *psec)
+{
+ return CreateFileMappingA (handle, psec, access, high_size, low_size, name);
+}
+
+inline void * open_file_mapping (unsigned long access, const char *name)
+{ return OpenFileMappingA (access, 0, name); }
+
+inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr)
+{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); }
+
+inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec)
+{
+ for (unsigned int attempt(0); attempt < error_sharing_violation_tries; ++attempt){
+ void * const handle = CreateFileA(name, access,
+ file_share_read | file_share_write | file_share_delete,
+ psec, creation_flags, attributes, 0);
+ bool const invalid(invalid_handle_value == handle);
+ if (!invalid){
+ return handle;
+ }
+ if (error_sharing_violation != get_last_error()){
+ return handle;
+ }
+ Sleep(error_sharing_violation_sleep_ms);
+ }
+ return invalid_handle_value;
+}
+
+inline bool delete_file(const char *name)
+{ return 0 != DeleteFileA(name); }
+
+inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags)
+{ return 0 != MoveFileExA(source_filename, destination_filename, flags); }
+
+inline void get_system_info(system_info *info)
+{ GetSystemInfo(info); }
+
+inline bool flush_view_of_file(void *base_addr, std::size_t numbytes)
+{ return 0 != FlushViewOfFile(base_addr, numbytes); }
+
+inline bool flush_file_buffers(void *handle)
+{ return 0 != FlushFileBuffers(handle); }
+
+inline bool get_file_size(void *handle, __int64 &size)
+{ return 0 != GetFileSizeEx(handle, &size); }
+
+inline bool create_directory(const char *name)
+{
+ interprocess_all_access_security sec;
+ return 0 != CreateDirectoryA(name, sec.get_attributes());
+}
+
+inline bool remove_directory(const char *lpPathName)
+{ return 0 != RemoveDirectoryA(lpPathName); }
+
+inline unsigned long get_temp_path(unsigned long length, char *buffer)
+{ return GetTempPathA(length, buffer); }
+
+inline int set_end_of_file(void *handle)
+{ return 0 != SetEndOfFile(handle); }
+
+inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method)
+{ return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method); }
+
+inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
+{ return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); }
+
+inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
+{ return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); }
+
+inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped)
+{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
+
+inline bool get_file_information_by_handle(void *hnd, interprocess_by_handle_file_information *info)
+{ return 0 != GetFileInformationByHandle(hnd, info); }
+
+inline long interlocked_increment(long volatile *addr)
+{ return BOOST_INTERLOCKED_INCREMENT(addr); }
+
+inline long interlocked_decrement(long volatile *addr)
+{ return BOOST_INTERLOCKED_DECREMENT(addr); }
+
+inline long interlocked_compare_exchange(long volatile *addr, long val1, long val2)
+{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(addr, val1, val2); }
+
+inline long interlocked_exchange_add(long volatile* addend, long value)
+{ return BOOST_INTERLOCKED_EXCHANGE_ADD(const_cast<long*>(addend), value); }
+
+inline long interlocked_exchange(long volatile* addend, long value)
+{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
+
+//Forward functions
+inline void *load_library(const char *name)
+{ return LoadLibraryA(name); }
+
+inline bool free_library(void *module)
+{ return 0 != FreeLibrary(module); }
+
+inline void *get_proc_address(void *module, const char *name)
+{ return GetProcAddress(module, name); }
+
+inline void *get_current_process()
+{ return GetCurrentProcess(); }
+
+inline void *get_module_handle(const char *name)
+{ return GetModuleHandleA(name); }
+
+inline unsigned long get_mapped_file_name(void *process, void *lpv, wchar_t *lpfilename, unsigned long nSize)
+{ return GetMappedFileNameW(process, lpv, lpfilename, nSize); }
+
+inline long reg_open_key_ex(void *hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void **phkResult)
+{ return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); }
+
+inline long reg_query_value_ex(void *hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData)
+{ return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
+
+inline long reg_close_key(void *hKey)
+{ return RegCloseKey(hKey); }
+
+inline bool query_performance_counter(__int64 *lpPerformanceCount)
+{
+ return 0 != QueryPerformanceCounter(lpPerformanceCount);
+}
+
+inline void initialize_object_attributes
+( object_attributes_t *pobject_attr, unicode_string_t *name
+ , unsigned long attr, void *rootdir, void *security_descr)
+
+{
+ pobject_attr->Length = sizeof(object_attributes_t);
+ pobject_attr->RootDirectory = rootdir;
+ pobject_attr->Attributes = attr;
+ pobject_attr->ObjectName = name;
+ pobject_attr->SecurityDescriptor = security_descr;
+ pobject_attr->SecurityQualityOfService = 0;
+}
+
+inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf, unsigned short bufSize)
+{
+ ucStr->Buffer = buf;
+ ucStr->Length = 0;
+ ucStr->MaximumLength = bufSize;
+}
+
+//A class that locates and caches loaded DLL function addresses.
+template<int Dummy>
+struct function_address_holder
+{
+ enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NumFunction };
+ enum { NtDll_dll, NumModule };
+
+ private:
+ static void *FunctionAddresses[NumFunction];
+ static volatile long FunctionStates[NumFunction];
+ static void *ModuleAddresses[NumModule];
+ static volatile long ModuleStates[NumModule];
+
+ static void *get_module_from_id(unsigned int id)
+ {
+ assert(id < (unsigned int)NumModule);
+ const char *module[] = { "ntdll.dll" };
+ bool compile_check[sizeof(module)/sizeof(module[0]) == NumModule];
+ (void)compile_check;
+ return get_module_handle(module[id]);
+ }
+
+ static void *get_module(const unsigned int id)
+ {
+ assert(id < (unsigned int)NumModule);
+ while(ModuleStates[id] < 2){
+ if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){
+ ModuleAddresses[id] = get_module_from_id(id);
+ interlocked_increment(&ModuleStates[id]);
+ break;
+ }
+ else{
+ sched_yield();
+ }
+ }
+ return ModuleAddresses[id];
+ }
+
+ static void *get_address_from_dll(const unsigned int id)
+ {
+ assert(id < (unsigned int)NumFunction);
+ const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject" };
+ bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction];
+ (void)compile_check;
+ return get_proc_address(get_module(NtDll_dll), function[id]);
+ }
+
+ public:
+ static void *get(const unsigned int id)
+ {
+ assert(id < (unsigned int)NumFunction);
+ while(FunctionStates[id] < 2){
+ if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){
+ FunctionAddresses[id] = get_address_from_dll(id);
+ interlocked_increment(&FunctionStates[id]);
+ break;
+ }
+ else{
+ sched_yield();
+ }
+ }
+ return FunctionAddresses[id];
+ }
+};
+
+template<int Dummy>
+void *function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction];
+
+template<int Dummy>
+volatile long function_address_holder<Dummy>::FunctionStates[function_address_holder<Dummy>::NumFunction];
+
+template<int Dummy>
+void *function_address_holder<Dummy>::ModuleAddresses[function_address_holder<Dummy>::NumModule];
+
+template<int Dummy>
+volatile long function_address_holder<Dummy>::ModuleStates[function_address_holder<Dummy>::NumModule];
+
+
+struct dll_func
+ : public function_address_holder<0>
+{};
+
+//Complex winapi based functions...
+struct library_unloader
+{
+ void *lib_;
+ library_unloader(void *module) : lib_(module){}
+ ~library_unloader(){ free_library(lib_); }
+};
+
+//pszFilename must have room for at least MaxPath+1 characters
+inline bool get_file_name_from_handle_function
+ (void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length)
+{
+ if(length <= MaxPath){
+ return false;
+ }
+
+// void *hiPSAPI = load_library("PSAPI.DLL");
+// if (0 == hiPSAPI)
+// return 0;
+// library_unloader unloader(hiPSAPI);
+
+// Pointer to function getMappedFileName() in PSAPI.DLL
+// GetMappedFileName_t pfGMFN =
+// (GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW");
+// if (! pfGMFN){
+// return 0; // Failed: unexpected error
+// }
+
+ bool bSuccess = false;
+
+ // Create a file mapping object.
+ void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0, 0);
+ if(hFileMap){
+ // Create a file mapping to get the file name.
+ void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 0, 1, 0);
+
+ if (pMem){
+ //out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath);
+ out_length = get_mapped_file_name(get_current_process(), pMem, pszFilename, MaxPath);
+ if(out_length){
+ bSuccess = true;
+ }
+ unmap_view_of_file(pMem);
+ }
+ close_handle(hFileMap);
+ }
+
+ return(bSuccess);
+}
+
+inline bool get_system_time_of_day_information(system_timeofday_information &info)
+{
+ NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t)
+ //get_proc_address(get_module_handle("ntdll.dll"), "NtQuerySystemInformation");
+ dll_func::get(dll_func::NtQuerySystemInformation);
+ unsigned long res;
+ long status = pNtQuerySystemInformation(system_time_of_day_information, &info, sizeof(info), &res);
+ if(status){
+ return false;
+ }
+ return true;
+}
+
+inline bool get_boot_time(unsigned char (&bootstamp) [BootstampLength])
+{
+ system_timeofday_information info;
+ bool ret = get_system_time_of_day_information(info);
+ if(!ret){
+ return false;
+ }
+ std::memcpy(&bootstamp[0], &info.Reserved1, sizeof(bootstamp));
+ return true;
+}
+
+inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSystemstampLength])
+{
+ system_timeofday_information info;
+ bool ret = get_system_time_of_day_information(info);
+ if(!ret){
+ return false;
+ }
+ std::memcpy(&bootsystemstamp[0], &info.Reserved1, sizeof(bootsystemstamp));
+ return true;
+}
+
+inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars
+{
+ if(s < (BootstampLength*2))
+ return false;
+ system_timeofday_information info;
+ bool ret = get_system_time_of_day_information(info);
+ if(!ret){
+ return false;
+ }
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ std::size_t char_counter = 0;
+ for(std::size_t i = 0; i != static_cast<std::size_t>(BootstampLength); ++i){
+ bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
+ bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
+ }
+ s = BootstampLength*2;
+ return true;
+}
+
+inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars
+{
+ if(s < (BootAndSystemstampLength*2))
+ return false;
+ system_timeofday_information info;
+ bool ret = get_system_time_of_day_information(info);
+ if(!ret){
+ return false;
+ }
+ const wchar_t Characters [] =
+ { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
+ , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
+ std::size_t char_counter = 0;
+ for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){
+ bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
+ bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
+ }
+ s = BootAndSystemstampLength*2;
+ return true;
+}
+
+class handle_closer
+{
+ void *handle_;
+ public:
+ handle_closer(void *handle) : handle_(handle){}
+ ~handle_closer(){ close_handle(handle_); }
+};
+
+union ntquery_mem_t
+{
+ object_name_information_t name;
+ struct ren_t
+ {
+ file_rename_information_t info;
+ wchar_t buf[32767];
+ } ren;
+};
+
+inline bool unlink_file(const char *filename)
+{
+ if(!delete_file(filename)){
+ try{
+ NtSetInformationFile_t pNtSetInformationFile =
+ //(NtSetInformationFile_t)get_proc_address(get_module_handle("ntdll.dll"), "NtSetInformationFile");
+ (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile);
+ if(!pNtSetInformationFile){
+ return false;
+ }
+
+ NtQueryObject_t pNtQueryObject =
+ //(NtQueryObject_t)get_proc_address(get_module_handle("ntdll.dll"), "NtQueryObject");
+ (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
+
+ //First step: Obtain a handle to the file using Win32 rules. This resolves relative paths
+ void *fh = create_file(filename, generic_read | delete_access, open_existing,
+ file_flag_backup_semantics | file_flag_delete_on_close, 0);
+ if(fh == invalid_handle_value){
+ return false;
+ }
+
+ handle_closer h_closer(fh);
+
+ std::auto_ptr<ntquery_mem_t> pmem(new ntquery_mem_t);
+ file_rename_information_t *pfri = &pmem->ren.info;
+ const std::size_t RenMaxNumChars =
+ ((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
+
+ //Obtain file name
+ unsigned long size;
+ if(pNtQueryObject(fh, object_name_information, pmem.get(), sizeof(ntquery_mem_t), &size)){
+ return false;
+ }
+
+ //Copy filename to the rename member
+ std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
+ std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t);
+
+ //Second step: obtain the complete native-nt filename
+ //if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){
+ //return 0;
+ //}
+
+ //Add trailing mark
+ if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){
+ return false;
+ }
+
+ //Search '\\' character to replace it
+ for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
+ if(pmem->ren.info.FileName[--i] == L'\\')
+ break;
+ }
+
+ //Add random number
+ std::size_t s = RenMaxNumChars - filename_string_length;
+ if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){
+ return false;
+ }
+ filename_string_length += s;
+
+ //Fill rename information (FileNameLength is in bytes)
+ pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length));
+ pfri->Replace = 1;
+ pfri->RootDir = 0;
+
+ //Final step: change the name of the in-use file:
+ io_status_block_t io;
+ if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){
+ return false;
+ }
+ return true;
+ }
+ catch(...){
+ return false;
+ }
+ }
+ return true;
+}
+
+struct reg_closer
+{
+ //reg_closer(RegCloseKey_t func, void *key) : func_(func), key_(key){}
+ //~reg_closer(){ (*func_)(key_); }
+ //RegCloseKey_t func_;
+ void *key_;
+ reg_closer(void *key) : key_(key){}
+ ~reg_closer(){ reg_close_key(key_); }
+};
+
+inline void get_shared_documents_folder(std::string &s)
+{
+ s.clear();
+ //void *hAdvapi = load_library("Advapi32.dll");
+ //if (hAdvapi){
+ //library_unloader unloader(hAdvapi);
+ // Pointer to function RegOpenKeyA
+ //RegOpenKeyEx_t pRegOpenKey =
+ //(RegOpenKeyEx_t)get_proc_address(hAdvapi, "RegOpenKeyExA");
+ //if (pRegOpenKey){
+ // Pointer to function RegCloseKey
+ //RegCloseKey_t pRegCloseKey =
+ //(RegCloseKey_t)get_proc_address(hAdvapi, "RegCloseKey");
+ //if (pRegCloseKey){
+ // Pointer to function RegQueryValueA
+ //RegQueryValueEx_t pRegQueryValue =
+ //(RegQueryValueEx_t)get_proc_address(hAdvapi, "RegQueryValueExA");
+ //if (pRegQueryValue){
+ //Open the key
+ void *key;
+ //if ((*pRegOpenKey)( hkey_local_machine
+ //, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ //, 0
+ //, key_query_value
+ //, &key) == 0){
+ //reg_closer key_closer(pRegCloseKey, key);
+ if (reg_open_key_ex( hkey_local_machine
+ , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ , 0
+ , key_query_value
+ , &key) == 0){
+ reg_closer key_closer(key);
+
+ //Obtain the value
+ unsigned long size;
+ unsigned long type;
+ const char *const reg_value = "Common AppData";
+ //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size);
+ long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size);
+ if(!err){
+ //Size includes terminating NULL
+ s.resize(size);
+ //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
+ err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
+ if(!err)
+ s.erase(s.end()-1);
+ (void)err;
+ }
+ }
+ //}
+ //}
+ //}
+ //}
+}
+
+
+inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s)
+{
+ s.clear();
+ //void *hAdvapi = load_library("Advapi32.dll");
+ //if (hAdvapi){
+ //library_unloader unloader(hAdvapi);
+ // Pointer to function RegOpenKeyA
+ //RegOpenKeyEx_t pRegOpenKey =
+ //(RegOpenKeyEx_t)get_proc_address(hAdvapi, "RegOpenKeyExA");
+ //if (pRegOpenKey){
+ // Pointer to function RegCloseKey
+ //RegCloseKey_t pRegCloseKey =
+ //(RegCloseKey_t)get_proc_address(hAdvapi, "RegCloseKey");
+ //if (pRegCloseKey){
+ // Pointer to function RegQueryValueA
+ //RegQueryValueEx_t pRegQueryValue =
+ //(RegQueryValueEx_t)get_proc_address(hAdvapi, "RegQueryValueExA");
+ //if (pRegQueryValue){
+ //Open the key
+ void *key;
+ //if ((*pRegOpenKey)( hkey_local_machine
+ //, folder
+ //, 0
+ //, key_query_value
+ //, &key) == 0){
+ //reg_closer key_closer(pRegCloseKey, key);
+ if (reg_open_key_ex( hkey_local_machine
+ , folder
+ , 0
+ , key_query_value
+ , &key) == 0){
+ reg_closer key_closer(key);
+
+ //Obtain the value
+ unsigned long size;
+ unsigned long type;
+ const char *const reg_value = value_key;
+ //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size);
+ long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size);
+ if(!err){
+ //Size includes terminating NULL
+ s.resize(size);
+ //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
+ err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
+ if(!err)
+ s.erase(s.end()-1);
+ (void)err;
+ }
+ }
+ //}
+ //}
+ //}
+ //}
+}
+
+struct co_uninitializer
+{ ~co_uninitializer() { CoUninitialize(); } };
+
+template<class Object>
+struct com_releaser
+{
+ Object *&object_;
+ com_releaser(Object *&object) : object_(object) {}
+ ~com_releaser() { object_->Release(); object_ = 0; }
+};
+
+inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var)
+{
+ //See example http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx
+ long co_init_ret = CoInitialize(0);
+ if(co_init_ret != S_OK_BIPC && co_init_ret != S_FALSE_BIPC)
+ return false;
+ co_uninitializer co_initialize_end;
+ (void)co_initialize_end;
+
+ bool bRet = false;
+ long sec_init_ret = CoInitializeSecurity
+ ( 0 //pVoid
+ ,-1 //cAuthSvc
+ , 0 //asAuthSvc
+ , 0 //pReserved1
+ , RPC_C_AUTHN_LEVEL_PKT_BIPC //dwAuthnLevel
+ , RPC_C_IMP_LEVEL_IMPERSONATE_BIPC //dwImpLevel
+ , 0 //pAuthList
+ , EOAC_NONE_BIPC //dwCapabilities
+ , 0 //pReserved3
+ );
+ if( 0 == sec_init_ret || RPC_E_TOO_LATE_BIPC == sec_init_ret)
+ {
+ IWbemLocator_BIPC * pIWbemLocator = 0;
+ const wchar_t * bstrNamespace = L"root\\cimv2";
+
+ if( 0 != CoCreateInstance(
+ CLSID_WbemAdministrativeLocator,
+ 0,
+ CLSCTX_INPROC_SERVER_BIPC | CLSCTX_LOCAL_SERVER_BIPC,
+ IID_IUnknown, (void **)&pIWbemLocator)){
+ return false;
+ }
+
+ com_releaser<IWbemLocator_BIPC> IWbemLocator_releaser(pIWbemLocator);
+
+ IWbemServices_BIPC *pWbemServices = 0;
+
+ if( 0 != pIWbemLocator->ConnectServer(
+ bstrNamespace, // Namespace
+ 0, // Userid
+ 0, // PW
+ 0, // Locale
+ 0, // flags
+ 0, // Authority
+ 0, // Context
+ &pWbemServices
+ )
+ ){
+ return false;
+ }
+
+ if( S_OK_BIPC != CoSetProxyBlanket(
+ pWbemServices,
+ RPC_C_AUTHN_DEFAULT_BIPC,
+ RPC_C_AUTHZ_DEFAULT_BIPC,
+ 0,
+ RPC_C_AUTHN_LEVEL_PKT_BIPC,
+ RPC_C_IMP_LEVEL_IMPERSONATE_BIPC,
+ 0,
+ EOAC_NONE_BIPC
+ )
+ ){
+ return false;
+ }
+
+ com_releaser<IWbemServices_BIPC> IWbemServices_releaser(pWbemServices);
+
+ strValue.clear();
+ strValue += L"Select ";
+ strValue += wmi_class_var;
+ strValue += L" from ";
+ strValue += wmi_class;
+
+ IEnumWbemClassObject_BIPC * pEnumObject = 0;
+
+ if ( 0 != pWbemServices->ExecQuery(
+ L"WQL",
+ strValue.c_str(),
+ //WBEM_FLAG_RETURN_IMMEDIATELY_BIPC,
+ WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC | WBEM_FLAG_FORWARD_ONLY_BIPC,
+ 0,
+ &pEnumObject
+ )
+ ){
+ return false;
+ }
+
+ com_releaser<IEnumWbemClassObject_BIPC> IEnumWbemClassObject_releaser(pEnumObject);
+
+ //WBEM_FLAG_FORWARD_ONLY_BIPC incompatible with Reset
+ //if ( 0 != pEnumObject->Reset() ){
+ //return false;
+ //}
+
+ wchar_variant vwchar;
+ unsigned long uCount = 1, uReturned;
+ IWbemClassObject_BIPC * pClassObject = 0;
+ while( 0 == pEnumObject->Next( WBEM_INFINITE_BIPC, uCount, &pClassObject, &uReturned ) )
+ {
+ com_releaser<IWbemClassObject_BIPC> IWbemClassObject_releaser(pClassObject);
+ if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){
+ bRet = true;
+ strValue = vwchar.value.pbstrVal;
+ VariantClear(&vwchar );
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+inline bool get_last_bootup_time( std::wstring& strValue )
+{
+ bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime");
+ std::size_t timezone = strValue.find(L'+');
+ if(timezone != std::wstring::npos){
+ strValue.erase(timezone);
+ }
+ timezone = strValue.find(L'-');
+ if(timezone != std::wstring::npos){
+ strValue.erase(timezone);
+ }
+ return ret;
+}
+
+inline bool get_last_bootup_time( std::string& str )
+{
+ std::wstring wstr;
+ bool ret = get_last_bootup_time(wstr);
+ str.resize(wstr.size());
+ for(std::size_t i = 0, max = str.size(); i != max; ++i){
+ str[i] = '0' + (wstr[i]-L'0');
+ }
+ return ret;
+}
+
+inline bool is_directory(const char *path)
+{
+ unsigned long attrib = GetFileAttributesA(path);
+
+ return (attrib != invalid_file_attributes &&
+ (attrib & file_attribute_directory));
+}
+
+} //namespace winapi
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifdef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP
diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp
new file mode 100644
index 0000000..896a220
--- /dev/null
+++ b/boost/interprocess/detail/workaround.hpp
@@ -0,0 +1,148 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_WORKAROUND_HPP
+#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
+
+#define BOOST_INTERPROCESS_WINDOWS
+
+/*
+#if !defined(_MSC_EXTENSIONS)
+#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions"
+#endif
+*/
+
+#endif
+
+#if !defined(BOOST_INTERPROCESS_WINDOWS)
+
+ #include <unistd.h>
+
+ #if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
+ //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
+ //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
+ # if !defined(__CYGWIN__) && !defined(__APPLE__)
+ # define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+ # endif
+ #endif
+
+ #if ((_POSIX_BARRIERS - 0) > 0)
+ # define BOOST_INTERPROCESS_POSIX_BARRIERS
+ # endif
+
+ #if ((_POSIX_SEMAPHORES - 0) > 0)
+ # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ # if defined(__CYGWIN__)
+ #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
+ # endif
+ //Some platforms have a limited (name length) named semaphore support
+ #elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
+ # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ #endif
+
+ #if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\
+ ((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\
+ ((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\
+ ((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\
+ ((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\
+ ((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\
+ ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\
+ ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
+ #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
+ #else
+ #endif
+
+ //Check for XSI shared memory objects. They are available in nearly all UNIX platforms
+ #if !defined(__QNXNTO__)
+ # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+ #endif
+
+ #if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
+ # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ #else
+ //VMS and MACOS don't define it but the have shm_open/close interface
+ # if defined(__vms)
+ # if __CRTL_VER >= 70200000
+ # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ # endif
+ //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
+ # elif defined (__APPLE__)
+// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
+ # endif
+ #endif
+
+ //Now check if we have only XSI shared memory
+ #if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\
+ !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
+ //# define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
+ #endif
+
+ #if ((_POSIX_TIMEOUTS - 0) > 0)
+ # define BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ #endif
+
+
+ #ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ //Some systems have filesystem-based resources, so the
+ //portable "/shmname" format does not work due to permission issues
+ //For those systems we need to form a path to a temporary directory:
+ // hp-ux tru64 vms freebsd
+ #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
+ #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+ #elif defined(__FreeBSD__)
+ #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+ #endif
+ #endif
+
+ #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ #if defined(__osf__) || defined(__vms)
+ #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
+ #endif
+ #endif
+
+ #if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500)
+ #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
+ #endif
+
+#endif
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
+ && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
+#define BOOST_INTERPROCESS_PERFECT_FORWARDING
+#endif
+
+//Now declare some Boost.Interprocess features depending on the implementation
+
+#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
+
+#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+
+#endif
+
+#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
+
+#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
+
+#endif
+
+// Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set
+#ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS
+#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
+#endif
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
diff --git a/boost/interprocess/detail/xsi_shared_memory_device.hpp b/boost/interprocess/detail/xsi_shared_memory_device.hpp
new file mode 100644
index 0000000..d2e2bf2
--- /dev/null
+++ b/boost/interprocess/detail/xsi_shared_memory_device.hpp
@@ -0,0 +1,392 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_DEVICE_HPP
+#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+#error "This header can't be used in Windows operating systems"
+#endif
+
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+#include <boost/interprocess/xsi_shared_memory.hpp>
+#include <boost/interprocess/sync/xsi/xsi_named_mutex.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <cstddef>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <cstring>
+
+//!\file
+//!Describes a class representing a native xsi shared memory.
+
+namespace boost {
+namespace interprocess {
+
+class xsi_shared_memory_device
+{
+ /// @cond
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
+ /// @endcond
+
+ public:
+
+ xsi_shared_memory_device();
+
+ xsi_shared_memory_device(create_only_t, const char *name, mode_t mode, std::size_t size)
+ { this->priv_open_or_create_name_only(ipcdetail::DoCreate, name, mode, size); }
+
+ xsi_shared_memory_device(open_or_create_t, const char *name, mode_t mode, std::size_t size)
+ { this->priv_open_or_create_name_only(ipcdetail::DoOpenOrCreate, name, mode, size); }
+
+ xsi_shared_memory_device(open_only_t, const char *name, mode_t mode)
+ { this->priv_open_or_create_name_only(ipcdetail::DoOpen, name, mode, 0); }
+
+ xsi_shared_memory_device(create_only_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
+ { this->priv_open_or_create_name_id(ipcdetail::DoCreate, name, id, mode, size); }
+
+ xsi_shared_memory_device(open_or_create_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
+ { this->priv_open_or_create_name_id(ipcdetail::DoOpenOrCreate, id, name, mode, size); }
+
+ xsi_shared_memory_device(open_only_t, const char *filepath, boost::uint8_t id, mode_t mode)
+ { this->priv_open_or_create_name_id(ipcdetail::DoOpen, name, id, mode, 0); }
+
+ xsi_shared_memory_device(BOOST_RV_REF(xsi_shared_memory_device) moved)
+ { this->swap(moved); }
+
+ xsi_shared_memory_device &operator=(BOOST_RV_REF(xsi_shared_memory_device) moved)
+ {
+ xsi_shared_memory_device tmp(boost::move(moved));
+ this->swap(tmp);
+ return *this;
+ }
+
+ //!Swaps two xsi_shared_memory_device. Does not throw
+ void swap(xsi_shared_memory_device &other);
+
+ //!Destroys *this. The shared memory won't be destroyed, just
+ //!this connection to it. Use remove() to destroy the shared memory.
+ ~xsi_shared_memory_device();
+
+ //!Returns the name of the
+ //!shared memory.
+ const char *get_name() const;
+
+ //!Returns the shared memory ID that
+ //!identifies the shared memory
+ int get_shmid() const;
+
+ //!Returns access
+ //!permissions
+ mode_t get_mode() const;
+
+ //!Returns the mapping handle.
+ //!Never throws
+ mapping_handle_t get_mapping_handle() const;
+
+ //!Erases a XSI shared memory object identified by shmname
+ //!from the system.
+ //!Returns false on error. Never throws
+ static bool remove(const char *shmname);
+
+ //!Erases the XSI shared memory object identified by shmid
+ //!from the system.
+ //!Returns false on error. Never throws
+ static bool remove(int shmid);
+
+ /// @cond
+ private:
+ template<int Dummy>
+ struct info_constants_t
+ {
+ static const std::size_t MaxName = 32;
+ static const std::size_t FirstID = 2;
+ static const std::size_t LastID = 256;
+ static const std::size_t NumID = LastID - FirstID;
+ };
+
+ struct info_t
+ {
+ struct names_t
+ {
+ char buf[info_constants_t<0>::MaxName];
+ } names[info_constants_t<0>::NumID];
+ };
+
+ static void priv_obtain_index(mapped_region &m, xsi_named_mutex &m, std::string &path);
+ static bool priv_remove_dead_memory(info_t *info, const char *path);
+
+ bool priv_open_or_create_name_only( ipcdetail::create_enum_t type
+ , const char *shmname
+ , mode_t mode
+ , std::size_t size);
+ bool priv_open_or_create_name_id( ipcdetail::create_enum_t type
+ , const char *shmname
+ , boost::uint8_t id
+ , mode_t mode
+ , std::size_t size);
+ xsi_shared_memory m_shm;
+ mode_t m_mode;
+ std::string m_name;
+ /// @endcond
+};
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::MaxName;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::FirstID;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::LastID;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::NumID;
+
+/// @cond
+
+inline xsi_shared_memory_device::xsi_shared_memory_device()
+ : m_shm(), m_mode(invalid_mode), m_name()
+{}
+
+inline xsi_shared_memory_device::~xsi_shared_memory_device()
+{}
+
+inline const char *xsi_shared_memory_device::get_name() const
+{ return m_name.c_str(); }
+
+inline void xsi_shared_memory_device::swap(xsi_shared_memory_device &other)
+{
+ m_shm.swap(other.m_shm);
+ std::swap(m_mode, other.m_mode);
+ m_name.swap(other.m_name);
+}
+
+inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const
+{ return m_shm.get_mapping_handle(); }
+
+inline mode_t xsi_shared_memory_device::get_mode() const
+{ return m_mode; }
+
+inline int xsi_shared_memory::get_shmid() const
+{ return m_shm.get_shmid(); }
+
+inline void xsi_shared_memory_device::priv_obtain_index
+ (mapped_region &reg, xsi_named_mutex &mut, std::string &path)
+{
+ const char *const filename = "xsi_shm_emulation_file";
+ permissions p;
+ p.set_unrestricted();
+ std::string xsi_shm_emulation_file_path;
+ ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path);
+ ipcdetail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p);
+ const std::size_t MemSize = sizeof(info_t);
+
+ xsi_shared_memory index_shm(open_or_create, xsi_shm_emulation_file_path.c_str(), 1, MemSize, 0666);
+ mapped_region r(index_shm, read_write, 0, MemSize, 0);
+ xsi_named_mutex m(open_or_create, xsi_shm_emulation_file_path.c_str(), 2, 0666);
+ reg = boost::move(r);
+ mut = boost::move(m);
+ path.swap(xsi_shm_emulation_file_path);
+}
+
+inline bool xsi_shared_memory_device::priv_remove_dead_memory
+ (xsi_shared_memory_device::info_t *info, const char *path)
+{
+ bool removed = false;
+ for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+ if(info->names[i].buf[0]){
+ try{
+ xsi_shared_memory temp( open_only, path, i+info_constants_t<0>::FirstID, 0600);
+ }
+ catch(interprocess_exception &e){
+ if(e.get_error_code() == not_found_error){
+ std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
+ removed = true;
+ }
+ }
+ }
+ }
+ return removed;
+}
+
+inline bool xsi_shared_memory_device::priv_open_or_create_name_id
+ (ipcdetail::create_enum_t type, const char *filepath, mode_t mode, std::size_t size)
+{
+ //Set accesses
+ if (mode != read_write && mode != read_only){
+ error_info err = other_error;
+ throw interprocess_exception(err);
+ }
+
+ int perm = (mode == read_only) ? (0444) : (0666);
+
+ if(type == ipcdetail::DoOpen){
+ if(!found){
+ error_info err = not_found_error;
+ throw interprocess_exception(err);
+ }
+ xsi_shared_memory temp(open_only, filepath, id, perm);
+ m_shm = boost::move(temp);
+ }
+ else if(type == ipcdetail::DoCreate){
+ //Try to reuse slot
+ xsi_shared_memory temp(create_only, filepath, id, size, perm);
+ std::strcpy(info->names[target_entry].buf, shmname);
+ m_shm = boost::move(temp);
+ }
+ else{ // if(type == ipcdetail::DoOpenOrCreate){
+ xsi_shared_memory temp(open_or_create, filepath, id, size, perm);
+ m_shm = boost::move(temp);
+ }
+
+ m_mode = mode;
+ m_name.clear();
+ return true;
+}
+
+inline bool xsi_shared_memory_device::priv_open_or_create_name_only
+ (ipcdetail::create_enum_t type, const char *shmname, mode_t mode, std::size_t size)
+{
+ //Set accesses
+ if (mode != read_write && mode != read_only){
+ error_info err = other_error;
+ throw interprocess_exception(err);
+ }
+
+ if (std::strlen(shmname) >= (info_constants_t<0>::MaxName)){
+ error_info err = other_error;
+ throw interprocess_exception(err);
+ }
+
+ {
+ //Obtain index and index lock
+ mapped_region region;
+ xsi_named_mutex mut;
+ std::string xsi_shm_emulation_file_path;
+ priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
+ info_t *info = static_cast<info_t *>(region.get_address());
+ scoped_lock<xsi_named_mutex> lock(mut);
+
+ //Find the correct entry or the first empty index
+ bool found = false;
+ int target_entry = -1;
+ int tries = 2;
+ while(tries--){
+ for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+ if(target_entry < 0 && !info->names[i].buf[0]){
+ target_entry = static_cast<int>(i);
+ }
+ else if(0 == std::strcmp(info->names[i].buf, shmname)){
+ found = true;
+ target_entry = static_cast<int>(i);
+ break;
+ }
+ }
+ if(target_entry < 0){
+ if(!tries || !priv_remove_dead_memory(info, xsi_shm_emulation_file_path.c_str())){
+ error_info err = out_of_resource_error;
+ throw interprocess_exception(err);
+ }
+ }
+ }
+ //Now handle the result
+ int perm = (mode == read_only) ? (0444) : (0666);
+ if(type == ipcdetail::DoOpen){
+ if(!found){
+ error_info err = not_found_error;
+ throw interprocess_exception(err);
+ }
+ xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
+ , target_entry+info_constants_t<0>::FirstID, perm);
+ m_shm = boost::move(temp);
+ }
+ else{
+
+ if(type == ipcdetail::DoCreate){
+ //Try to reuse slot
+ xsi_shared_memory temp( create_only, xsi_shm_emulation_file_path.c_str()
+ , target_entry+info_constants_t<0>::FirstID, size, perm);
+ std::strcpy(info->names[target_entry].buf, shmname);
+ m_shm = boost::move(temp);
+ }
+ else{ // if(type == ipcdetail::DoOpenOrCreate){
+ xsi_shared_memory temp( open_or_create, xsi_shm_emulation_file_path.c_str()
+ , target_entry+info_constants_t<0>::FirstID, size, perm);
+ if(!found){
+ std::memset(info->names[target_entry].buf, 0, info_constants_t<0>::MaxName);
+ std::strcpy(info->names[target_entry].buf, shmname);
+ }
+ m_shm = boost::move(temp);
+ }
+ }
+ }
+
+ m_mode = mode;
+ m_name = shmname;
+ return true;
+}
+
+inline bool xsi_shared_memory_device::remove(const char *shmname)
+{
+ try{
+ //Obtain index and index lockss
+ mapped_region region;
+ xsi_named_mutex mut;
+ std::string xsi_shm_emulation_file_path;
+ priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
+ scoped_lock<xsi_named_mutex> lock(mut);
+ info_t *info = static_cast<info_t *>(region.get_address());
+
+ //Now check and remove
+ bool removed = false;
+
+ for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+ if(0 == std::strcmp(info->names[i].buf, name)){
+ xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
+ , i+info_constants_t<0>::FirstID);
+ if(!xsi_shared_memory::remove(temp.get_shmid()) && (system_error_code() != invalid_argument)){
+ return false;
+ }
+ std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
+ removed = true;
+ break;
+ }
+ }
+ return removed;
+ }
+ catch(...){
+ return false;
+ }
+}
+
+inline bool xsi_shared_memory_device::remove(int shmid)
+{ return xsi_shared_memory::remove(shmid); }
+
+///@endcond
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
diff --git a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
new file mode 100644
index 0000000..d74d966
--- /dev/null
+++ b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/detail/workaround.hpp>
+
+#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 <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+#include <boost/interprocess/xsi_shared_memory.hpp>
+
+//!\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
+{
+ /// @cond
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
+ /// @endcond
+ public:
+
+ xsi_shared_memory_file_wrapper() : xsi_shared_memory() {}
+
+ xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, 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 mode, 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 mode, const permissions& perm = 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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
diff --git a/boost/interprocess/errors.hpp b/boost/interprocess/errors.hpp
new file mode 100644
index 0000000..e36b8e4
--- /dev/null
+++ b/boost/interprocess/errors.hpp
@@ -0,0 +1,236 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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 this code are taken from boost::filesystem library
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2002 Beman Dawes
+// Copyright (C) 2001 Dietmar Kuehl
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
+// at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See library home page at http://www.boost.org/libs/filesystem
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef BOOST_INTERPROCESS_ERRORS_HPP
+#define BOOST_INTERPROCESS_ERRORS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <stdarg.h>
+#include <string>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+# include <boost/interprocess/detail/win32_api.hpp>
+#else
+# ifdef BOOST_HAS_UNISTD_H
+# include <errno.h> //Errors
+# include <cstring> //strerror
+# else //ifdef BOOST_HAS_UNISTD_H
+# error Unknown platform
+# endif //ifdef BOOST_HAS_UNISTD_H
+#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+//!\file
+//!Describes the error numbering of interprocess classes
+
+namespace boost {
+namespace interprocess {
+/// @cond
+inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
+{
+ #if (defined BOOST_INTERPROCESS_WINDOWS)
+ return winapi::get_last_error();
+ #else
+ return errno; // GCC 3.1 won't accept ::errno
+ #endif
+}
+
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+inline void fill_system_message(int sys_err_code, std::string &str)
+{
+ void *lpMsgBuf;
+ winapi::format_message(
+ winapi::format_message_allocate_buffer |
+ winapi::format_message_from_system |
+ winapi::format_message_ignore_inserts,
+ 0,
+ sys_err_code,
+ winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
+ reinterpret_cast<char *>(&lpMsgBuf),
+ 0,
+ 0
+ );
+ str += static_cast<const char*>(lpMsgBuf);
+ winapi::local_free( lpMsgBuf ); // free the buffer
+ while ( str.size()
+ && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
+ str.erase( str.size()-1 );
+}
+# else
+inline void fill_system_message( int system_error, std::string &str)
+{ str = std::strerror(system_error); }
+# endif
+/// @endcond
+
+enum error_code_t
+{
+ no_error = 0,
+ system_error, // system generated error; if possible, is translated
+ // to one of the more specific errors below.
+ other_error, // library generated error
+ security_error, // includes access rights, permissions failures
+ read_only_error,
+ io_error,
+ path_error,
+ not_found_error,
+// not_directory_error,
+ busy_error, // implies trying again might succeed
+ already_exists_error,
+ not_empty_error,
+ is_directory_error,
+ out_of_space_error,
+ out_of_memory_error,
+ out_of_resource_error,
+ lock_error,
+ sem_error,
+ mode_error,
+ size_error,
+ corrupted_error,
+ not_such_file_or_directory,
+ invalid_argument,
+ timeout_when_locking_error,
+ timeout_when_waiting_error,
+};
+
+typedef int native_error_t;
+
+/// @cond
+struct ec_xlate
+{
+ native_error_t sys_ec;
+ error_code_t ec;
+};
+
+static const ec_xlate ec_table[] =
+{
+ #if (defined BOOST_INTERPROCESS_WINDOWS)
+ { /*ERROR_ACCESS_DENIED*/5L, security_error },
+ { /*ERROR_INVALID_ACCESS*/12L, security_error },
+ { /*ERROR_SHARING_VIOLATION*/32L, security_error },
+ { /*ERROR_LOCK_VIOLATION*/33L, security_error },
+ { /*ERROR_LOCKED*/212L, security_error },
+ { /*ERROR_NOACCESS*/998L, security_error },
+ { /*ERROR_WRITE_PROTECT*/19L, read_only_error },
+ { /*ERROR_NOT_READY*/21L, io_error },
+ { /*ERROR_SEEK*/25L, io_error },
+ { /*ERROR_READ_FAULT*/30L, io_error },
+ { /*ERROR_WRITE_FAULT*/29L, io_error },
+ { /*ERROR_CANTOPEN*/1011L, io_error },
+ { /*ERROR_CANTREAD*/1012L, io_error },
+ { /*ERROR_CANTWRITE*/1013L, io_error },
+ { /*ERROR_DIRECTORY*/267L, path_error },
+ { /*ERROR_INVALID_NAME*/123L, path_error },
+ { /*ERROR_FILE_NOT_FOUND*/2L, not_found_error },
+ { /*ERROR_PATH_NOT_FOUND*/3L, not_found_error },
+ { /*ERROR_DEV_NOT_EXIST*/55L, not_found_error },
+ { /*ERROR_DEVICE_IN_USE*/2404L, busy_error },
+ { /*ERROR_OPEN_FILES*/2401L, busy_error },
+ { /*ERROR_BUSY_DRIVE*/142L, busy_error },
+ { /*ERROR_BUSY*/170L, busy_error },
+ { /*ERROR_FILE_EXISTS*/80L, already_exists_error },
+ { /*ERROR_ALREADY_EXISTS*/183L, already_exists_error },
+ { /*ERROR_DIR_NOT_EMPTY*/145L, not_empty_error },
+ { /*ERROR_HANDLE_DISK_FULL*/39L, out_of_space_error },
+ { /*ERROR_DISK_FULL*/112L, out_of_space_error },
+ { /*ERROR_OUTOFMEMORY*/14L, out_of_memory_error },
+ { /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error },
+ { /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error },
+ { /*ERROR_INVALID_ADDRESS*/487L, busy_error }
+ #else //#if (defined BOOST_INTERPROCESS_WINDOWS)
+ { EACCES, security_error },
+ { EROFS, read_only_error },
+ { EIO, io_error },
+ { ENAMETOOLONG, path_error },
+ { ENOENT, not_found_error },
+ // { ENOTDIR, not_directory_error },
+ { EAGAIN, busy_error },
+ { EBUSY, busy_error },
+ { ETXTBSY, busy_error },
+ { EEXIST, already_exists_error },
+ { ENOTEMPTY, not_empty_error },
+ { EISDIR, is_directory_error },
+ { ENOSPC, out_of_space_error },
+ { ENOMEM, out_of_memory_error },
+ { EMFILE, out_of_resource_error },
+ { ENOENT, not_such_file_or_directory },
+ { EINVAL, invalid_argument }
+ #endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+};
+
+inline error_code_t lookup_error(native_error_t err)
+{
+ const ec_xlate *cur = &ec_table[0],
+ *end = cur + sizeof(ec_table)/sizeof(ec_xlate);
+ for (;cur != end; ++cur ){
+ if ( err == cur->sys_ec ) return cur->ec;
+ }
+ return system_error; // general system error code
+}
+
+struct error_info
+{
+ error_info(error_code_t ec = other_error )
+ : m_nat(0), m_ec(ec)
+ {}
+
+ error_info(native_error_t sys_err_code)
+ : m_nat(sys_err_code), m_ec(lookup_error(sys_err_code))
+ {}
+
+ error_info & operator =(error_code_t ec)
+ {
+ m_nat = 0;
+ m_ec = ec;
+ return *this;
+ }
+
+ error_info & operator =(native_error_t sys_err_code)
+ {
+ m_nat = sys_err_code;
+ m_ec = lookup_error(sys_err_code);
+ return *this;
+ }
+
+ native_error_t get_native_error()const
+ { return m_nat; }
+
+ error_code_t get_error_code()const
+ { return m_ec; }
+
+ private:
+ native_error_t m_nat;
+ error_code_t m_ec;
+};
+/// @endcond
+
+} // namespace interprocess {
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_ERRORS_HPP
diff --git a/boost/interprocess/exceptions.hpp b/boost/interprocess/exceptions.hpp
new file mode 100644
index 0000000..a4f196f
--- /dev/null
+++ b/boost/interprocess/exceptions.hpp
@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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_EXCEPTIONS_HPP
+#define BOOST_INTERPROCESS_EXCEPTIONS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <stdexcept>
+#include <new>
+
+//!\file
+//!Describes exceptions thrown by interprocess classes
+
+namespace boost {
+
+namespace interprocess {
+
+//!This class is the base class of all exceptions
+//!thrown by boost::interprocess
+class interprocess_exception : public std::exception
+{
+ public:
+ interprocess_exception(const char *err/*error_code_t ec = other_error*/)
+ : m_err(other_error)
+ {
+// try { m_str = "boost::interprocess_exception::library_error"; }
+ try { m_str = err; }
+ catch (...) {}
+ }
+/*
+ interprocess_exception(native_error_t sys_err_code)
+ : m_err(sys_err_code)
+ {
+ try { fill_system_message(m_err.get_native_error(), m_str); }
+ catch (...) {}
+ }*/
+
+ interprocess_exception(const error_info &err_info, const char *str = 0)
+ : m_err(err_info)
+ {
+ try{
+ if(m_err.get_native_error() != 0){
+ fill_system_message(m_err.get_native_error(), m_str);
+ }
+ else if(str){
+ m_str = str;
+ }
+ else{
+ m_str = "boost::interprocess_exception::library_error";
+ }
+ }
+ catch(...){}
+ }
+
+ virtual ~interprocess_exception() throw(){}
+
+ virtual const char * what() const throw()
+ { return m_str.c_str(); }
+
+ native_error_t get_native_error()const { return m_err.get_native_error(); }
+
+ // Note: a value of other_error implies a library (rather than system) error
+ error_code_t get_error_code() const { return m_err.get_error_code(); }
+
+ /// @cond
+ private:
+ error_info m_err;
+ std::string m_str;
+ /// @endcond
+};
+
+//!This is the exception thrown by shared interprocess_mutex family when a deadlock situation
+//!is detected or when using a interprocess_condition the interprocess_mutex is not locked
+class lock_exception : public interprocess_exception
+{
+ public:
+ lock_exception()
+ : interprocess_exception(lock_error)
+ {}
+
+ virtual const char* what() const throw()
+ { return "boost::interprocess::lock_exception"; }
+};
+
+//!This is the exception thrown by named interprocess_semaphore when a deadlock situation
+//!is detected or when an error is detected in the post/wait operation
+/*
+class sem_exception : public interprocess_exception
+{
+ public:
+ sem_exception()
+ : interprocess_exception(lock_error)
+ {}
+
+ virtual const char* what() const throw()
+ { return "boost::interprocess::sem_exception"; }
+};
+*/
+//!This is the exception thrown by synchronization objects when there is
+//!an error in a wait() function
+/*
+class wait_exception : public interprocess_exception
+{
+ public:
+ virtual const char* what() const throw()
+ { return "boost::interprocess::wait_exception"; }
+};
+*/
+
+//!This exception is thrown when a named object is created
+//!in "open_only" mode and the resource was not already created
+/*
+class not_previously_created : public interprocess_exception
+{
+ public:
+ virtual const char* what() const throw()
+ { return "boost::interprocess::not_previously_created"; }
+};
+*/
+
+//!This exception is thrown when a memory request can't be
+//!fulfilled.
+class bad_alloc : public interprocess_exception
+{
+ public:
+ bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc"){}
+ virtual const char* what() const throw()
+ { return "boost::interprocess::bad_alloc"; }
+};
+
+} // namespace interprocess {
+
+} // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_EXCEPTIONS_HPP
diff --git a/boost/interprocess/file_mapping.hpp b/boost/interprocess/file_mapping.hpp
new file mode 100644
index 0000000..3bad98f
--- /dev/null
+++ b/boost/interprocess/file_mapping.hpp
@@ -0,0 +1,184 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/move/move.hpp>
+#include <string> //std::string
+
+//!\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
+{
+ /// @cond
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping)
+ /// @endcond
+
+ public:
+ //!Constructs an empty file mapping.
+ //!Does not throw
+ file_mapping();
+
+ //!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);
+
+ //!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)
+ : m_handle(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_mapping &operator=(BOOST_RV_REF(file_mapping) moved)
+ {
+ file_mapping tmp(boost::move(moved));
+ this->swap(tmp);
+ return *this;
+ }
+
+ //!Swaps to file_mappings.
+ //!Does not throw.
+ void swap(file_mapping &other);
+
+ //!Returns access mode
+ //!used in the constructor
+ mode_t get_mode() const;
+
+ //!Obtains the mapping handle
+ //!to be used with mapped_region
+ mapping_handle_t get_mapping_handle() const;
+
+ //!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;
+
+ //!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);
+
+ /// @cond
+ private:
+ //!Closes a previously opened file mapping. Never throws.
+ void priv_close();
+ file_handle_t m_handle;
+ mode_t m_mode;
+ std::string m_filename;
+ /// @endcond
+};
+
+inline file_mapping::file_mapping()
+ : m_handle(file_handle_t(ipcdetail::invalid_file()))
+{}
+
+inline file_mapping::~file_mapping()
+{ this->priv_close(); }
+
+inline const char *file_mapping::get_name() const
+{ return m_filename.c_str(); }
+
+inline void file_mapping::swap(file_mapping &other)
+{
+ std::swap(m_handle, other.m_handle);
+ std::swap(m_mode, other.m_mode);
+ m_filename.swap(other.m_filename);
+}
+
+inline mapping_handle_t file_mapping::get_mapping_handle() const
+{ return ipcdetail::mapping_handle_from_file_handle(m_handle); }
+
+inline mode_t file_mapping::get_mode() const
+{ 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); }
+
+///@cond
+
+inline void file_mapping::priv_close()
+{
+ if(m_handle != ipcdetail::invalid_file()){
+ ipcdetail::close_file(m_handle);
+ m_handle = ipcdetail::invalid_file();
+ }
+}
+
+///@endcond
+
+//!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); }
+};
+
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_FILE_MAPPING_HPP
diff --git a/boost/interprocess/indexes/flat_map_index.hpp b/boost/interprocess/indexes/flat_map_index.hpp
new file mode 100644
index 0000000..bac387e
--- /dev/null
+++ b/boost/interprocess/indexes/flat_map_index.hpp
@@ -0,0 +1,78 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <functional>
+#include <utility>
+#include <boost/interprocess/containers/flat_map.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+
+//!\file
+//!Describes index adaptor of boost::map container, to use it
+//!as name/shared memory index
+
+//[flat_map_index
+namespace boost { namespace interprocess {
+
+//!Helper class to define typedefs from IndexTraits
+template <class MapConfig>
+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_type> key_less;
+ typedef std::pair<key_type, mapped_type> value_type;
+ typedef allocator<value_type
+ ,segment_manager_base> allocator_type;
+ typedef flat_map<key_type, mapped_type,
+ key_less, allocator_type> index_t;
+};
+
+//!Index type based in flat_map. Just derives from flat_map and
+//!defines the interface needed by managed memory segments.
+template <class MapConfig>
+class flat_map_index
+ //Derive class from flat_map specialization
+ : public flat_map_index_aux<MapConfig>::index_t
+{
+ /// @cond
+ typedef flat_map_index_aux<MapConfig> index_aux;
+ typedef typename index_aux::index_t base_type;
+ typedef typename index_aux::
+ segment_manager_base segment_manager_base;
+ /// @endcond
+
+ 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 <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
diff --git a/boost/interprocess/indexes/iset_index.hpp b/boost/interprocess/indexes/iset_index.hpp
new file mode 100644
index 0000000..9662392
--- /dev/null
+++ b/boost/interprocess/indexes/iset_index.hpp
@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// 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
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <string>
+#include <functional>
+#include <utility>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/intrusive/set.hpp>
+
+
+//!\file
+//!Describes index adaptor of boost::intrusive::set container, to use it
+//!as name/shared memory index
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+//!Helper class to define typedefs from IndexTraits
+template <class MapConfig>
+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<void_pointer>
+ , bi::optimize_size<true>
+ >::type derivation_hook;
+
+ typedef typename MapConfig::template
+ intrusive_value_type<derivation_hook>::type value_type;
+ typedef std::les